From: Barry Naujok Date: Mon, 16 Jul 2007 06:09:45 +0000 (+0000) Subject: Cache disk nlink values in Phase 3 for Phase 7 X-Git-Tag: v2.10.0~53 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0f012a4cfafcfa8fcda19fe87d2215f93eb6825a;p=thirdparty%2Fxfsprogs-dev.git Cache disk nlink values in Phase 3 for Phase 7 Merge of master-melb:xfs-cmds:29142a by kenmcd. Minore cleanup --- diff --git a/repair/Makefile b/repair/Makefile index cfa172cd2..37caf2751 100644 --- a/repair/Makefile +++ b/repair/Makefile @@ -15,7 +15,7 @@ CFILES = agheader.c attr_repair.c avl.c avl64.c bmap.c dino_chunks.c \ dinode.c dir.c dir2.c dir_stack.c globals.c incore.c \ incore_bmc.c init.c incore_ext.c incore_ino.c phase1.c \ phase2.c phase3.c phase4.c phase5.c phase6.c phase7.c rt.c sb.c \ - progress.c prefetch.c scan.c versions.c xfs_repair.c threads.c + progress.c prefetch.c scan.c threads.c versions.c xfs_repair.c LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBPTHREAD) $(LIBRT) LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c index e80e1b8ac..2a316b68c 100644 --- a/repair/dino_chunks.c +++ b/repair/dino_chunks.c @@ -779,6 +779,15 @@ process_inode_chunk(xfs_mount_t *mp, xfs_agnumber_t agno, int num_inos, do_warn(_("would correct imap\n")); } set_inode_used(ino_rec, irec_offset); + + /* + * store on-disk nlink count for comparing in phase 7 + */ + set_inode_disk_nlinks(ino_rec, irec_offset, + dino->di_core.di_version > XFS_DINODE_VERSION_1 + ? be32_to_cpu(dino->di_core.di_nlink) + : be16_to_cpu(dino->di_core.di_onlink)); + } else { set_inode_free(ino_rec, irec_offset); } diff --git a/repair/globals.h b/repair/globals.h index a4727a0b1..53b785945 100644 --- a/repair/globals.h +++ b/repair/globals.h @@ -166,12 +166,12 @@ EXTERN xfs_suminfo_t *sumcompute; /* inode tree records have full or partial backptr fields ? */ -EXTERN int full_backptrs; /* - * if 1, use backptrs_t component - * of ino_un union, if 0, use - * parent_list_t component. see - * incore.h for more details - */ +EXTERN int full_ino_ex_data;/* + * if 1, use ino_ex_data_t component + * of ino_un union, if 0, use + * parent_list_t component. see + * incore.h for more details + */ #define ORPHANAGE "lost+found" diff --git a/repair/incore.h b/repair/incore.h index 7783a6b69..ddc2a89fe 100644 --- a/repair/incore.h +++ b/repair/incore.h @@ -328,6 +328,8 @@ void incore_ext_teardown(xfs_mount_t *mp); typedef xfs_ino_t parent_entry_t; +struct nlink_ops; + typedef struct parent_list { __uint64_t pmask; parent_entry_t *pentries; @@ -336,12 +338,12 @@ typedef struct parent_list { #endif } parent_list_t; -typedef struct backptrs { +typedef struct ino_ex_data { __uint64_t ino_reached; /* bit == 1 if reached */ __uint64_t ino_processed; /* reference checked bit mask */ - __uint32_t nlinks[XFS_INODES_PER_CHUNK]; parent_list_t *parents; -} backptrs_t; + __uint8_t *counted_nlinks;/* counted nlinks in P6 */ +} ino_ex_data_t; typedef struct ino_tree_node { avlnode_t avl_node; @@ -349,14 +351,26 @@ typedef struct ino_tree_node { xfs_inofree_t ir_free; /* inode free bit mask */ __uint64_t ino_confirmed; /* confirmed bitmask */ __uint64_t ino_isa_dir; /* bit == 1 if a directory */ + struct nlink_ops *nlinkops; /* pointer to current nlink ops */ + __uint8_t *disk_nlinks; /* on-disk nlinks, set in P3 */ union { - backptrs_t *backptrs; - parent_list_t *plist; + ino_ex_data_t *ex_data; /* phases 6,7 */ + parent_list_t *plist; /* phases 2-5 */ } ino_un; } ino_tree_node_t; +typedef struct nlink_ops { + const int nlink_size; + void (*disk_nlink_set)(ino_tree_node_t *, int, __uint32_t); + __uint32_t (*disk_nlink_get)(ino_tree_node_t *, int); + __uint32_t (*counted_nlink_get)(ino_tree_node_t *, int); + __uint32_t (*counted_nlink_inc)(ino_tree_node_t *, int); + __uint32_t (*counted_nlink_dec)(ino_tree_node_t *, int); +} nlink_ops_t; + + #define INOS_PER_IREC (sizeof(__uint64_t) * NBBY) -void add_ino_backptrs(xfs_mount_t *mp); +void add_ino_ex_data(xfs_mount_t *mp); /* * return an inode record to the free inode record pool @@ -428,13 +442,13 @@ void clear_uncertain_ino_cache(xfs_agnumber_t agno); #define XFS_INOPROC_MASKN(i,n) ((__uint64_t)((1 << (n)) - 1) << (i)) #define XFS_INOPROC_IS_PROC(rp, i) \ - (((rp)->ino_un.backptrs->ino_processed & XFS_INOPROC_MASK((i))) == 0LL \ + (((rp)->ino_un.ex_data->ino_processed & XFS_INOPROC_MASK((i))) == 0LL \ ? 0 : 1) #define XFS_INOPROC_SET_PROC(rp, i) \ - ((rp)->ino_un.backptrs->ino_processed |= XFS_INOPROC_MASK((i))) + ((rp)->ino_un.ex_data->ino_processed |= XFS_INOPROC_MASK((i))) /* #define XFS_INOPROC_CLR_PROC(rp, i) \ - ((rp)->ino_un.backptrs->ino_processed &= ~XFS_INOPROC_MASK((i))) + ((rp)->ino_un.ex_data->ino_processed &= ~XFS_INOPROC_MASK((i))) */ /* @@ -457,12 +471,12 @@ void clear_uncertain_ino_cache(xfs_agnumber_t agno); #define XFS_INO_RCHD_MASK(i) ((__uint64_t)1 << (i)) #define XFS_INO_RCHD_IS_RCHD(rp, i) \ - (((rp)->ino_un.backptrs->ino_reached & XFS_INO_RCHD_MASK((i))) == 0LL \ + (((rp)->ino_un.ex_data->ino_reached & XFS_INO_RCHD_MASK((i))) == 0LL \ ? 0 : 1) #define XFS_INO_RCHD_SET_RCHD(rp, i) \ - ((rp)->ino_un.backptrs->ino_reached |= XFS_INO_RCHD_MASK((i))) + ((rp)->ino_un.ex_data->ino_reached |= XFS_INO_RCHD_MASK((i))) #define XFS_INO_RCHD_CLR_RCHD(rp, i) \ - ((rp)->ino_un.backptrs->ino_reached &= ~XFS_INO_RCHD_MASK((i))) + ((rp)->ino_un.ex_data->ino_reached &= ~XFS_INO_RCHD_MASK((i))) /* * set/clear/test is inode a directory inode */ @@ -519,16 +533,16 @@ void clear_uncertain_ino_cache(xfs_agnumber_t agno); static inline int is_inode_reached(ino_tree_node_t *ino_rec, int ino_offset) { - ASSERT(ino_rec->ino_un.backptrs != NULL); + ASSERT(ino_rec->ino_un.ex_data != NULL); return(XFS_INO_RCHD_IS_RCHD(ino_rec, ino_offset)); } static inline void add_inode_reached(ino_tree_node_t *ino_rec, int ino_offset) { - ASSERT(ino_rec->ino_un.backptrs != NULL); + ASSERT(ino_rec->ino_un.ex_data != NULL); - ino_rec->ino_un.backptrs->nlinks[ino_offset]++; + (*ino_rec->nlinkops->counted_nlink_inc)(ino_rec, ino_offset); XFS_INO_RCHD_SET_RCHD(ino_rec, ino_offset); ASSERT(is_inode_reached(ino_rec, ino_offset)); @@ -537,33 +551,46 @@ add_inode_reached(ino_tree_node_t *ino_rec, int ino_offset) static inline void add_inode_ref(ino_tree_node_t *ino_rec, int ino_offset) { - ASSERT(ino_rec->ino_un.backptrs != NULL); + ASSERT(ino_rec->ino_un.ex_data != NULL); - ino_rec->ino_un.backptrs->nlinks[ino_offset]++; + (*ino_rec->nlinkops->counted_nlink_inc)(ino_rec, ino_offset); } static inline void drop_inode_ref(ino_tree_node_t *ino_rec, int ino_offset) { - ASSERT(ino_rec->ino_un.backptrs != NULL); - ASSERT(ino_rec->ino_un.backptrs->nlinks[ino_offset] > 0); + ASSERT(ino_rec->ino_un.ex_data != NULL); - if (--ino_rec->ino_un.backptrs->nlinks[ino_offset] == 0) + if ((*ino_rec->nlinkops->counted_nlink_dec)(ino_rec, ino_offset) == 0) XFS_INO_RCHD_CLR_RCHD(ino_rec, ino_offset); } static inline int is_inode_referenced(ino_tree_node_t *ino_rec, int ino_offset) { - ASSERT(ino_rec->ino_un.backptrs != NULL); - return(ino_rec->ino_un.backptrs->nlinks[ino_offset] > 0); + ASSERT(ino_rec->ino_un.ex_data != NULL); + + return (*ino_rec->nlinkops->counted_nlink_get)(ino_rec, ino_offset) > 0; } static inline __uint32_t num_inode_references(ino_tree_node_t *ino_rec, int ino_offset) { - ASSERT(ino_rec->ino_un.backptrs != NULL); - return(ino_rec->ino_un.backptrs->nlinks[ino_offset]); + ASSERT(ino_rec->ino_un.ex_data != NULL); + + return (*ino_rec->nlinkops->counted_nlink_get)(ino_rec, ino_offset); +} + +static inline void +set_inode_disk_nlinks(ino_tree_node_t *ino_rec, int ino_offset, __uint32_t nlinks) +{ + (*ino_rec->nlinkops->disk_nlink_set)(ino_rec, ino_offset, nlinks); +} + +static inline __uint32_t +get_inode_disk_nlinks(ino_tree_node_t *ino_rec, int ino_offset) +{ + return (*ino_rec->nlinkops->disk_nlink_get)(ino_rec, ino_offset); } /* @@ -589,9 +616,6 @@ int is_inode_refchecked(xfs_ino_t ino, */ void set_inode_parent(ino_tree_node_t *irec, int ino_offset, xfs_ino_t ino); -#if 0 -void clear_inode_parent(ino_tree_node_t *irec, int offset); -#endif xfs_ino_t get_inode_parent(ino_tree_node_t *irec, int ino_offset); /* diff --git a/repair/incore_ino.c b/repair/incore_ino.c index c08da769d..370c3614b 100644 --- a/repair/incore_ino.c +++ b/repair/incore_ino.c @@ -50,6 +50,193 @@ typedef struct ino_flist_s { static ino_flist_t ino_flist; /* free list must be initialized before use */ +/* memory optimised nlink counting for all inodes */ + +static void nlink_grow_8_to_16(ino_tree_node_t *irec); +static void nlink_grow_16_to_32(ino_tree_node_t *irec); + +static void +disk_nlink_32_set(ino_tree_node_t *irec, int ino_offset, __uint32_t nlinks) +{ + ((__uint32_t*)irec->disk_nlinks)[ino_offset] = nlinks; +} + +static __uint32_t +disk_nlink_32_get(ino_tree_node_t *irec, int ino_offset) +{ + return ((__uint32_t*)irec->disk_nlinks)[ino_offset]; +} + +static __uint32_t +counted_nlink_32_get(ino_tree_node_t *irec, int ino_offset) +{ + return ((__uint32_t*)irec->ino_un.ex_data->counted_nlinks)[ino_offset]; +} + +static __uint32_t +counted_nlink_32_inc(ino_tree_node_t *irec, int ino_offset) +{ + return ++(((__uint32_t*)irec->ino_un.ex_data->counted_nlinks)[ino_offset]); +} + +static __uint32_t +counted_nlink_32_dec(ino_tree_node_t *irec, int ino_offset) +{ + __uint32_t *nlinks = (__uint32_t*)irec->ino_un.ex_data->counted_nlinks; + + ASSERT(nlinks[ino_offset] > 0); + return --(nlinks[ino_offset]); +} + + +static void +disk_nlink_16_set(ino_tree_node_t *irec, int ino_offset, __uint32_t nlinks) +{ + if (nlinks >= 0x10000) { + nlink_grow_16_to_32(irec); + disk_nlink_32_set(irec, ino_offset, nlinks); + } else + ((__uint16_t*)irec->disk_nlinks)[ino_offset] = nlinks; +} + +static __uint32_t +disk_nlink_16_get(ino_tree_node_t *irec, int ino_offset) +{ + return ((__uint16_t*)irec->disk_nlinks)[ino_offset]; +} + +static __uint32_t +counted_nlink_16_get(ino_tree_node_t *irec, int ino_offset) +{ + return ((__uint16_t*)irec->ino_un.ex_data->counted_nlinks)[ino_offset]; +} + +static __uint32_t +counted_nlink_16_inc(ino_tree_node_t *irec, int ino_offset) +{ + __uint16_t *nlinks = (__uint16_t*)irec->ino_un.ex_data->counted_nlinks; + + if (nlinks[ino_offset] == 0xffff) { + nlink_grow_16_to_32(irec); + return counted_nlink_32_inc(irec, ino_offset); + } + return ++(nlinks[ino_offset]); +} + +static __uint32_t +counted_nlink_16_dec(ino_tree_node_t *irec, int ino_offset) +{ + __uint16_t *nlinks = (__uint16_t*)irec->ino_un.ex_data->counted_nlinks; + + ASSERT(nlinks[ino_offset] > 0); + return --(nlinks[ino_offset]); +} + + +static void +disk_nlink_8_set(ino_tree_node_t *irec, int ino_offset, __uint32_t nlinks) +{ + if (nlinks >= 0x100) { + nlink_grow_8_to_16(irec); + disk_nlink_16_set(irec, ino_offset, nlinks); + } else + irec->disk_nlinks[ino_offset] = nlinks; +} + +static __uint32_t +disk_nlink_8_get(ino_tree_node_t *irec, int ino_offset) +{ + return irec->disk_nlinks[ino_offset]; +} + +static __uint32_t +counted_nlink_8_get(ino_tree_node_t *irec, int ino_offset) +{ + return irec->ino_un.ex_data->counted_nlinks[ino_offset]; +} + +static __uint32_t +counted_nlink_8_inc(ino_tree_node_t *irec, int ino_offset) +{ + if (irec->ino_un.ex_data->counted_nlinks[ino_offset] == 0xff) { + nlink_grow_8_to_16(irec); + return counted_nlink_16_inc(irec, ino_offset); + } + return ++(irec->ino_un.ex_data->counted_nlinks[ino_offset]); +} + +static __uint32_t +counted_nlink_8_dec(ino_tree_node_t *irec, int ino_offset) +{ + ASSERT(irec->ino_un.ex_data->counted_nlinks[ino_offset] > 0); + return --(irec->ino_un.ex_data->counted_nlinks[ino_offset]); +} + + +static nlink_ops_t nlinkops[] = { + {sizeof(__uint8_t) * XFS_INODES_PER_CHUNK, + disk_nlink_8_set, disk_nlink_8_get, + counted_nlink_8_get, counted_nlink_8_inc, counted_nlink_8_dec}, + {sizeof(__uint16_t) * XFS_INODES_PER_CHUNK, + disk_nlink_16_set, disk_nlink_16_get, + counted_nlink_16_get, counted_nlink_16_inc, counted_nlink_16_dec}, + {sizeof(__uint32_t) * XFS_INODES_PER_CHUNK, + disk_nlink_32_set, disk_nlink_32_get, + counted_nlink_32_get, counted_nlink_32_inc, counted_nlink_32_dec}, +}; + +static void +nlink_grow_8_to_16(ino_tree_node_t *irec) +{ + __uint16_t *new_nlinks; + int i; + + new_nlinks = malloc(sizeof(__uint16_t) * XFS_INODES_PER_CHUNK); + if (new_nlinks == NULL) + do_error(_("could not allocate expanded nlink array\n")); + for (i = 0; i < XFS_INODES_PER_CHUNK; i++) + new_nlinks[i] = irec->disk_nlinks[i]; + free(irec->disk_nlinks); + irec->disk_nlinks = (__uint8_t*)new_nlinks; + + if (full_ino_ex_data) { + new_nlinks = malloc(sizeof(__uint16_t) * XFS_INODES_PER_CHUNK); + if (new_nlinks == NULL) + do_error(_("could not allocate expanded nlink array\n")); + for (i = 0; i < XFS_INODES_PER_CHUNK; i++) + new_nlinks[i] = irec->ino_un.ex_data->counted_nlinks[i]; + free(irec->ino_un.ex_data->counted_nlinks); + irec->ino_un.ex_data->counted_nlinks = (__uint8_t*)new_nlinks; + } + irec->nlinkops = &nlinkops[1]; +} + +static void +nlink_grow_16_to_32(ino_tree_node_t *irec) +{ + __uint32_t *new_nlinks; + int i; + + new_nlinks = malloc(sizeof(__uint32_t) * XFS_INODES_PER_CHUNK); + if (new_nlinks == NULL) + do_error(_("could not allocate expanded nlink array\n")); + for (i = 0; i < XFS_INODES_PER_CHUNK; i++) + new_nlinks[i] = ((__int16_t*)&irec->disk_nlinks)[i]; + free(irec->disk_nlinks); + irec->disk_nlinks = (__uint8_t*)new_nlinks; + + if (full_ino_ex_data) { + new_nlinks = malloc(sizeof(__uint32_t) * XFS_INODES_PER_CHUNK); + if (new_nlinks == NULL) + do_error(_("could not allocate expanded nlink array\n")); + for (i = 0; i < XFS_INODES_PER_CHUNK; i++) + new_nlinks[i] = ((__int16_t*)&irec->ino_un.ex_data->counted_nlinks)[i]; + free(irec->ino_un.ex_data->counted_nlinks); + irec->ino_un.ex_data->counted_nlinks = (__uint8_t*)new_nlinks; + } + irec->nlinkops = &nlinkops[2]; +} + /* * next is the uncertain inode list -- a sorted (in ascending order) * list of inode records sorted on the starting inode number. There @@ -65,47 +252,52 @@ static ino_flist_t ino_flist; /* free list must be initialized before use */ */ /* ARGSUSED */ static ino_tree_node_t * -mk_ino_tree_nodes(xfs_agino_t starting_ino) +mk_ino_tree_nodes( + xfs_agino_t starting_ino) { - int i; - ino_tree_node_t *new; - avlnode_t *node; + int i; + ino_tree_node_t *ino_rec; + avlnode_t *node; PREPAIR_RW_WRITE_LOCK(&ino_flist_lock); if (ino_flist.cnt == 0) { ASSERT(ino_flist.list == NULL); - if ((new = malloc(sizeof(ino_tree_node_t[ALLOC_NUM_INOS]))) + if ((ino_rec = malloc(sizeof(ino_tree_node_t[ALLOC_NUM_INOS]))) == NULL) do_error(_("inode map malloc failed\n")); for (i = 0; i < ALLOC_NUM_INOS; i++) { - new->avl_node.avl_nextino = + ino_rec->avl_node.avl_nextino = (avlnode_t *) ino_flist.list; - ino_flist.list = new; + ino_flist.list = ino_rec; ino_flist.cnt++; - new++; + ino_rec++; } } ASSERT(ino_flist.list != NULL); - new = ino_flist.list; - ino_flist.list = (ino_tree_node_t *) new->avl_node.avl_nextino; + ino_rec = ino_flist.list; + ino_flist.list = (ino_tree_node_t *) ino_rec->avl_node.avl_nextino; ino_flist.cnt--; - node = &new->avl_node; + node = &ino_rec->avl_node; node->avl_nextino = node->avl_forw = node->avl_back = NULL; PREPAIR_RW_UNLOCK(&ino_flist_lock); /* initialize node */ - new->ino_startnum = 0; - new->ino_confirmed = 0; - new->ino_isa_dir = 0; - new->ir_free = (xfs_inofree_t) - 1; - new->ino_un.backptrs = NULL; + ino_rec->ino_startnum = 0; + ino_rec->ino_confirmed = 0; + ino_rec->ino_isa_dir = 0; + ino_rec->ir_free = (xfs_inofree_t) - 1; + ino_rec->ino_un.ex_data = NULL; + ino_rec->nlinkops = &nlinkops[0]; + ino_rec->disk_nlinks = calloc(1, nlinkops[0].nlink_size); + if (ino_rec->disk_nlinks == NULL) + do_error(_("could not allocate nlink array\n")); - return(new); + return(ino_rec); } /* @@ -131,11 +323,15 @@ free_ino_tree_node(ino_tree_node_t *ino_rec) ino_flist.list = ino_rec; ino_flist.cnt++; - if (ino_rec->ino_un.backptrs != NULL) { - if (full_backptrs && ino_rec->ino_un.backptrs->parents != NULL) - free(ino_rec->ino_un.backptrs->parents); - if (ino_rec->ino_un.plist != NULL) - free(ino_rec->ino_un.plist); + free(ino_rec->disk_nlinks); + + if (ino_rec->ino_un.ex_data != NULL) { + if (full_ino_ex_data) { + free(ino_rec->ino_un.ex_data->parents); + free(ino_rec->ino_un.ex_data->counted_nlinks); + } + free(ino_rec->ino_un.ex_data); + } PREPAIR_RW_UNLOCK(&ino_flist_lock); @@ -443,7 +639,7 @@ set_inode_parent(ino_tree_node_t *irec, int offset, xfs_ino_t parent) __uint64_t bitmask; parent_entry_t *tmp; - ASSERT(full_backptrs == 0); + ASSERT(full_ino_ex_data == 0); if (irec->ino_un.plist == NULL) { irec->ino_un.plist = @@ -532,8 +728,8 @@ get_inode_parent(ino_tree_node_t *irec, int offset) int i; int target; - if (full_backptrs) - ptbl = irec->ino_un.backptrs->parents; + if (full_ino_ex_data) + ptbl = irec->ino_un.ex_data->parents; else ptbl = irec->ino_un.plist; @@ -555,73 +751,38 @@ get_inode_parent(ino_tree_node_t *irec, int offset) return(0LL); } -backptrs_t * -get_backptr(void) +static void +alloc_ex_data(ino_tree_node_t *irec) { - backptrs_t *ptr; + parent_list_t *ptbl; - if ((ptr = malloc(sizeof(backptrs_t))) == NULL) - do_error(_("could not malloc back pointer table\n")); + ptbl = irec->ino_un.plist; + irec->ino_un.ex_data = (ino_ex_data_t *)calloc(1, sizeof(ino_ex_data_t)); + if (irec->ino_un.ex_data == NULL) + do_error(_("could not malloc inode extra data\n")); - bzero(ptr, sizeof(backptrs_t)); + irec->ino_un.ex_data->parents = ptbl; + irec->ino_un.ex_data->counted_nlinks = calloc(1, irec->nlinkops->nlink_size); - return(ptr); + if (irec->ino_un.ex_data->counted_nlinks == NULL) + do_error(_("could not malloc inode extra data\n")); } void -add_ino_backptrs(xfs_mount_t *mp) +add_ino_ex_data(xfs_mount_t *mp) { -#ifdef XR_BCKPTR_DBG - xfs_ino_t ino; - int j, k; -#endif /* XR_BCKPTR_DBG */ - ino_tree_node_t *ino_rec; - parent_list_t *tmp; - xfs_agnumber_t i; + ino_tree_node_t *ino_rec; + xfs_agnumber_t i; for (i = 0; i < mp->m_sb.sb_agcount; i++) { ino_rec = findfirst_inode_rec(i); while (ino_rec != NULL) { - tmp = ino_rec->ino_un.plist; - ino_rec->ino_un.backptrs = get_backptr(); - ino_rec->ino_un.backptrs->parents = tmp; - -#ifdef XR_BCKPTR_DBG - if (tmp != NULL) { - k = 0; - for (j = 0; j < XFS_INODES_PER_CHUNK; j++) { - ino = XFS_AGINO_TO_INO(mp, i, - ino_rec->ino_startnum + j); - if (ino == 25165846) { - do_warn("THERE 1 !!!\n"); - } - if (tmp->pentries[j] != 0) { - k++; - do_warn( - "inode %llu - parent %llu\n", - ino, - tmp->pentries[j]); - if (ino == 25165846) { - do_warn("THERE!!!\n"); - } - } - } - - if (k != tmp->cnt) { - do_warn( - "ERROR - count = %d, counted %d\n", - tmp->cnt, k); - } - } -#endif /* XR_BCKPTR_DBG */ + alloc_ex_data(ino_rec); ino_rec = next_ino_rec(ino_rec); } } - - full_backptrs = 1; - - return; + full_ino_ex_data = 1; } static __psunsigned_t @@ -680,7 +841,7 @@ incore_ino_init(xfs_mount_t *mp) bzero(last_rec, sizeof(ino_tree_node_t *) * agcount); - full_backptrs = 0; + full_ino_ex_data = 0; return; } diff --git a/repair/phase6.c b/repair/phase6.c index 3ad2bc196..743c455b8 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -94,7 +94,7 @@ typedef struct freetab { static int dir_hash_add( dir_hash_tab_t *hashtab, - __uint32_t addr, + __uint32_t addr, xfs_ino_t inum, int namelen, uchar_t *name) @@ -105,9 +105,9 @@ dir_hash_add( dir_hash_ent_t *p; int dup; short junk; - + ASSERT(!hashtab->names_duped); - + junk = name[0] == '/'; byaddr = DIR_HASH_FUNC(hashtab, addr); dup = 0; @@ -116,7 +116,7 @@ dir_hash_add( hash = libxfs_da_hashname(name, namelen); byhash = DIR_HASH_FUNC(hashtab, hash); - /* + /* * search hash bucket for existing name. */ for (p = hashtab->byhash[byhash]; p; p = p->nextbyhash) { @@ -129,20 +129,20 @@ dir_hash_add( } } } - + if ((p = malloc(sizeof(*p))) == NULL) do_error(_("malloc failed in dir_hash_add (%u bytes)\n"), sizeof(*p)); - + p->nextbyaddr = hashtab->byaddr[byaddr]; hashtab->byaddr[byaddr] = p; - if (hashtab->last) + if (hashtab->last) hashtab->last->nextbyorder = p; else hashtab->first = p; p->nextbyorder = NULL; hashtab->last = p; - + if (!(p->junkit = junk)) { p->hashval = hash; p->nextbyhash = hashtab->byhash[byhash]; @@ -153,12 +153,12 @@ dir_hash_add( p->seen = 0; p->namelen = namelen; p->name = name; - + return !dup; } /* - * checks to see if any data entries are not in the leaf blocks + * checks to see if any data entries are not in the leaf blocks */ static int dir_hash_unseen( @@ -242,9 +242,9 @@ dir_hash_init( if ((hashtab = calloc(DIR_HASH_TAB_SIZE(hsize), 1)) == NULL) do_error(_("calloc failed in dir_hash_init\n")); hashtab->size = hsize; - hashtab->byhash = (dir_hash_ent_t**)((char *)hashtab + + hashtab->byhash = (dir_hash_ent_t**)((char *)hashtab + sizeof(dir_hash_tab_t)); - hashtab->byaddr = (dir_hash_ent_t**)((char *)hashtab + + hashtab->byaddr = (dir_hash_ent_t**)((char *)hashtab + sizeof(dir_hash_tab_t) + sizeof(dir_hash_ent_t*) * hsize); return hashtab; } @@ -308,10 +308,10 @@ dir_hash_dup_names(dir_hash_tab_t *hashtab) { uchar_t *name; dir_hash_ent_t *p; - + if (hashtab->names_duped) return; - + for (p = hashtab->first; p; p = p->nextbyorder) { name = malloc(p->namelen); memcpy(name, p->name, p->namelen); @@ -1539,9 +1539,9 @@ lf_block_dir_entry_check(xfs_mount_t *mp, /* * check for duplicate names in directory. - */ - if (!dir_hash_add(hashtab, (da_bno << mp->m_sb.sb_blocklog) + - entry->nameidx, + */ + if (!dir_hash_add(hashtab, (da_bno << mp->m_sb.sb_blocklog) + + entry->nameidx, lino, entry->namelen, namest->name)) { do_warn( _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"), @@ -1694,8 +1694,8 @@ _("bad magic # (0x%x) for dir ino %llu leaf block (bno %u fsbno %llu)\n"), } if (!skipit) - lf_block_dir_entry_check(mp, ino, leaf, &dirty, - num_illegal, need_dot, stack, irec, + lf_block_dir_entry_check(mp, ino, leaf, &dirty, + num_illegal, need_dot, stack, irec, ino_offset, hashtab, da_bno); da_bno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT); @@ -1746,7 +1746,7 @@ _("can't map leaf block %d in dir %llu, xfs_bmapi returns %d, nmap = %d\n"), * lost+found on the next run */ -static void +static void longform_dir2_rebuild( xfs_mount_t *mp, xfs_ino_t ino, @@ -1765,17 +1765,17 @@ longform_dir2_rebuild( dir_hash_ent_t *p; int committed; int done; - - /* + + /* * trash directory completely and rebuild from scratch using the * name/inode pairs in the hash table */ - + do_warn(_("rebuilding directory inode %llu\n"), ino); - - /* + + /* * first attempt to locate the parent inode, if it can't be found, - * we'll use the lost+found inode + * we'll use the lost+found inode */ byhash = DIR_HASH_FUNC(hashtab, libxfs_da_hashname((uchar_t*)"..", 2)); parentino = orphanage_ino; @@ -1787,7 +1787,7 @@ longform_dir2_rebuild( } XFS_BMAP_INIT(&flist, &firstblock); - + tp = libxfs_trans_alloc(mp, 0); nres = XFS_REMOVE_SPACE_RES(mp); error = libxfs_trans_reserve(tp, nres, XFS_REMOVE_LOG_RES(mp), 0, @@ -1796,12 +1796,12 @@ longform_dir2_rebuild( res_failed(error); libxfs_trans_ijoin(tp, ip, 0); libxfs_trans_ihold(tp, ip); - - if ((error = libxfs_bmap_last_offset(tp, ip, &lastblock, + + if ((error = libxfs_bmap_last_offset(tp, ip, &lastblock, XFS_DATA_FORK))) - do_error(_("xfs_bmap_last_offset failed -- error - %d\n"), + do_error(_("xfs_bmap_last_offset failed -- error - %d\n"), error); - + /* re-init the directory to shortform */ if ((error = libxfs_trans_iget(mp, tp, parentino, 0, 0, &pip))) { do_warn( @@ -1816,8 +1816,8 @@ longform_dir2_rebuild( } /* free all data, leaf, node and freespace blocks */ - - if ((error = libxfs_bunmapi(tp, ip, 0, lastblock, + + if ((error = libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA, 0, &firstblock, &flist, &done))) { do_warn(_("xfs_bunmapi failed -- error - %d\n"), error); @@ -1825,27 +1825,27 @@ longform_dir2_rebuild( XFS_TRANS_ABORT); return; } - + ASSERT(done); libxfs_dir2_init(tp, ip, pip); - + error = libxfs_bmap_finish(&tp, &flist, firstblock, &committed); - - libxfs_trans_commit(tp, + + libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0); - + /* go through the hash list and re-add the inodes */ for (p = hashtab->first; p; p = p->nextbyorder) { - - if (p->name[0] == '/' || (p->name[0] == '.' && (p->namelen == 1 + + if (p->name[0] == '/' || (p->name[0] == '.' && (p->namelen == 1 || (p->namelen == 2 && p->name[1] == '.')))) continue; - + tp = libxfs_trans_alloc(mp, 0); nres = XFS_CREATE_SPACE_RES(mp, p->namelen); - if ((error = libxfs_trans_reserve(tp, nres, + if ((error = libxfs_trans_reserve(tp, nres, XFS_CREATE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT))) { do_warn( @@ -1859,7 +1859,7 @@ longform_dir2_rebuild( XFS_BMAP_INIT(&flist, &firstblock); if ((error = libxfs_dir2_createname(tp, ip, (uchar_t *)p->name, - p->namelen, p->inum, &firstblock, &flist, + p->namelen, p->inum, &firstblock, &flist, nres))) { do_warn( _("name create failed in ino %llu (%d), filesystem may be out of space\n"), @@ -1869,7 +1869,7 @@ _("name create failed in ino %llu (%d), filesystem may be out of space\n"), break; } - if ((error = libxfs_bmap_finish(&tp, &flist, firstblock, + if ((error = libxfs_bmap_finish(&tp, &flist, firstblock, &committed))) { do_warn( _("bmap finish failed (%d), filesystem may be out of space\n"), @@ -1879,9 +1879,9 @@ _("name create failed in ino %llu (%d), filesystem may be out of space\n"), XFS_TRANS_ABORT); break; } - - libxfs_trans_commit(tp, + + libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0); } } @@ -2155,7 +2155,7 @@ longform_dir2_entry_check_data( ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen); inum = INT_GET(dep->inumber, ARCH_CONVERT); lastfree = 0; - if (!dir_hash_add(hashtab, addr, inum, dep->namelen, + if (!dir_hash_add(hashtab, addr, inum, dep->namelen, dep->name)) { do_warn( _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"), @@ -2419,12 +2419,12 @@ longform_dir2_check_node( xfs_fileoff_t next_da_bno; int seeval = 0; int used; - + for (da_bno = mp->m_dirleafblk, next_da_bno = 0; next_da_bno != NULLFILEOFF && da_bno < mp->m_dirfreeblk; da_bno = (xfs_dablk_t)next_da_bno) { next_da_bno = da_bno + mp->m_dirblkfsbs - 1; - if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) + if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) break; if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bp, XFS_DATA_FORK)) { @@ -2461,17 +2461,17 @@ longform_dir2_check_node( seeval = dir_hash_see_all(hashtab, leaf->ents, INT_GET(leaf->hdr.count, ARCH_CONVERT), INT_GET(leaf->hdr.stale, ARCH_CONVERT)); libxfs_da_brelse(NULL, bp); - if (seeval != DIR_HASH_CK_OK) + if (seeval != DIR_HASH_CK_OK) return 1; } - if (dir_hash_check(hashtab, ip, seeval)) + if (dir_hash_check(hashtab, ip, seeval)) return 1; - + for (da_bno = mp->m_dirfreeblk, next_da_bno = 0; next_da_bno != NULLFILEOFF; da_bno = (xfs_dablk_t)next_da_bno) { next_da_bno = da_bno + mp->m_dirblkfsbs - 1; - if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) + if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) break; if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bp, XFS_DATA_FORK)) { @@ -2597,12 +2597,12 @@ longform_dir2_entry_check(xfs_mount_t *mp, /* more data blocks than expected */ num_bps = db + 1; bplist = realloc(bplist, num_bps * sizeof(xfs_dabuf_t*)); - if (!bplist) + if (!bplist) do_error( _("realloc failed in longform_dir2_entry_check (%u bytes)\n"), num_bps * sizeof(xfs_dabuf_t*)); } - if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bplist[db], + if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bplist[db], XFS_DATA_FORK)) { do_warn(_( "can't read data block %u for directory inode %llu\n"), @@ -2621,8 +2621,8 @@ longform_dir2_entry_check(xfs_mount_t *mp, block = bplist[0]->data; btp = XFS_DIR2_BLOCK_TAIL_P(mp, block); blp = XFS_DIR2_BLOCK_LEAF_P(btp); - seeval = dir_hash_see_all(hashtab, blp, - INT_GET(btp->count, ARCH_CONVERT), + seeval = dir_hash_see_all(hashtab, blp, + INT_GET(btp->count, ARCH_CONVERT), INT_GET(btp->stale, ARCH_CONVERT)); if (dir_hash_check(hashtab, ip, seeval)) fixit |= 1; @@ -2633,17 +2633,17 @@ longform_dir2_entry_check(xfs_mount_t *mp, } if (!no_modify && fixit) { dir_hash_dup_names(hashtab); - for (i = 0; i < freetab->naents; i++) + for (i = 0; i < freetab->naents; i++) if (bplist[i]) libxfs_da_brelse(NULL, bplist[i]); longform_dir2_rebuild(mp, ino, ip, hashtab); *num_illegal = 0; } else { - for (i = 0; i < freetab->naents; i++) + for (i = 0; i < freetab->naents; i++) if (bplist[i]) libxfs_da_brelse(NULL, bplist[i]); } - + free(bplist); free(freetab); } @@ -2798,7 +2798,7 @@ _("entry \"%s\" in shortform dir %llu references non-existent ino %llu\n"), ASSERT(irec != NULL); ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum; - + /* * if it's a free inode, blow out the entry. * by now, any inode that we think is free @@ -2820,12 +2820,12 @@ _("entry \"%s\" in shortform dir inode %llu points to free inode %llu\n"), do_warn(_("would junk entry \"%s\"\n"), fname); } - } else if (!dir_hash_add(hashtab, + } else if (!dir_hash_add(hashtab, (xfs_dir2_dataptr_t)(sf_entry - &sf->list[0]), lino, sf_entry->namelen, sf_entry->name)) { /* * check for duplicate names in directory. - */ + */ do_warn( _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"), fname, lino, ino); @@ -3244,7 +3244,7 @@ shortform_dir2_entry_check(xfs_mount_t *mp, lino, sfep->namelen, sfep->name)) { /* * check for duplicate names in directory. - */ + */ do_warn( _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"), fname, lino, ino); @@ -3890,7 +3890,7 @@ phase6(xfs_mount_t *mp) incore_ext_teardown(mp); - add_ino_backptrs(mp); + add_ino_ex_data(mp); /* * verify existence of root directory - if we have to @@ -4031,10 +4031,10 @@ _(" - skipping filesystem traversal from / ... \n")); } do_log(_(" - traversals finished ... \n")); - + /* flush all dirty data before doing lost+found search */ libxfs_bcache_flush(); - + do_log(_(" - moving disconnected inodes to lost+found ... \n")); /* diff --git a/repair/phase7.c b/repair/phase7.c index b656725e2..c66533270 100644 --- a/repair/phase7.c +++ b/repair/phase7.c @@ -30,91 +30,110 @@ #include "threads.h" /* dinoc is a pointer to the IN-CORE dinode core */ -void -set_nlinks(xfs_dinode_core_t *dinoc, - xfs_ino_t ino, - __uint32_t nrefs, - int *dirty) +static void +set_nlinks( + xfs_dinode_core_t *dinoc, + xfs_ino_t ino, + __uint32_t nrefs, + int *dirty) { - if (!no_modify) { - if (dinoc->di_nlink != nrefs) { - *dirty = 1; - do_warn( - _("resetting inode %llu nlinks from %d to %d\n"), - ino, dinoc->di_nlink, nrefs); + if (dinoc->di_nlink == nrefs) + return; - if (nrefs > XFS_MAXLINK_1) { - ASSERT(fs_inode_nlink); - do_warn( + if (!no_modify) { + *dirty = 1; + do_warn(_("resetting inode %llu nlinks from %d to %d\n"), + ino, dinoc->di_nlink, nrefs); + + if (nrefs > XFS_MAXLINK_1) { + ASSERT(fs_inode_nlink); + do_warn( _("nlinks %d will overflow v1 ino, ino %llu will be converted to version 2\n"), - nrefs, ino); + nrefs, ino); - } - dinoc->di_nlink = nrefs; } + dinoc->di_nlink = nrefs; } else { - if (dinoc->di_nlink != nrefs) + do_warn(_("would have reset inode %llu nlinks from %d to %d\n"), + ino, dinoc->di_nlink, nrefs); + } +} + +static void +update_inode_nlinks( + xfs_mount_t *mp, + xfs_ino_t ino, + __uint32_t nlinks) +{ + xfs_trans_t *tp; + xfs_inode_t *ip; + int error; + int dirty; + + tp = libxfs_trans_alloc(mp, XFS_TRANS_REMOVE); + + error = libxfs_trans_reserve(tp, (no_modify ? 0 : 10), + XFS_REMOVE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES, + XFS_REMOVE_LOG_COUNT); + + ASSERT(error == 0); + + error = libxfs_trans_iget(mp, tp, ino, 0, 0, &ip); + + if (error) { + if (!no_modify) + do_error(_("couldn't map inode %llu, err = %d\n"), + ino, error); + else { do_warn( - _("would have reset inode %llu nlinks from %d to %d\n"), - ino, dinoc->di_nlink, nrefs); + _("couldn't map inode %llu, err = %d, can't compare link counts\n"), + ino, error); + return; + } + } + + dirty = 0; + + /* + * compare and set links for all inodes + * but the lost+found inode. we keep + * that correct as we go. + */ + if (ino != orphanage_ino) + set_nlinks(&ip->i_d, ino, nlinks, &dirty); + + if (!dirty) { + libxfs_trans_iput(tp, ip, 0); + libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); + } else { + libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + /* + * no need to do a bmap finish since + * we're not allocating anything + */ + ASSERT(error == 0); + error = libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES | + XFS_TRANS_SYNC, NULL); + + ASSERT(error == 0); } } -void +static void phase7_alt_function(xfs_mount_t *mp, xfs_agnumber_t agno) { - register ino_tree_node_t *irec; + ino_tree_node_t *irec; int j; - int chunk_dirty; - int inode_dirty; - xfs_ino_t ino; __uint32_t nrefs; - xfs_agblock_t agbno; - xfs_dinode_t *dip; - ino_tree_node_t *ino_ra; - xfs_buf_t *bp; - - if (verbose) - do_log(_(" - agno = %d\n"), agno); - - ino_ra = prefetch_inode_chunks(mp, agno, NULL); /* - * read on-disk inodes in chunks. then, - * look at each on-disk inode 1 at a time. - * if the number of links is bad, reset it. + * using the nlink values memorised during phase3/4, compare to the + * nlink counted in phase 6, and if different, update on-disk. */ irec = findfirst_inode_rec(agno); while (irec != NULL) { - - if (ino_ra && (irec->ino_startnum >= ino_ra->ino_startnum)) - ino_ra = prefetch_inode_chunks(mp, agno, ino_ra); - - agbno = XFS_AGINO_TO_AGBNO(mp, irec->ino_startnum); - bp = libxfs_readbuf(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, agbno), - XFS_FSB_TO_BB(mp, XFS_IALLOC_BLOCKS(mp)), 0); - if (bp == NULL) { - if (!no_modify) { - do_error( - _("cannot read inode %llu, disk block %lld, cnt %d\n"), - XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum), - XFS_AGB_TO_DADDR(mp, agno, agbno), - (int)XFS_FSB_TO_BB(mp, XFS_IALLOC_BLOCKS(mp))); - /* NOT REACHED */ - } - do_warn( - _("cannot read inode %llu, disk block %lld, cnt %d\n"), - XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum), - XFS_AGB_TO_DADDR(mp, agno, agbno), - (int)XFS_FSB_TO_BB(mp, XFS_IALLOC_BLOCKS(mp))); - - irec = next_ino_rec(irec); - continue; /* while */ - } - chunk_dirty = 0; for (j = 0; j < XFS_INODES_PER_CHUNK; j++) { assert(is_inode_confirmed(irec, j)); @@ -122,110 +141,27 @@ phase7_alt_function(xfs_mount_t *mp, xfs_agnumber_t agno) continue; assert(no_modify || is_inode_reached(irec, j)); - assert(no_modify || - is_inode_referenced(irec, j)); + assert(no_modify || is_inode_referenced(irec, j)); nrefs = num_inode_references(irec, j); - ino = XFS_AGINO_TO_INO(mp, agno, - irec->ino_startnum + j); - - dip = (xfs_dinode_t *)(XFS_BUF_PTR(bp) + - (j << mp->m_sb.sb_inodelog)); - - inode_dirty = 0; - - /* Swap the fields we care about to native format */ - dip->di_core.di_magic = INT_GET(dip->di_core.di_magic, - ARCH_CONVERT); - dip->di_core.di_onlink = INT_GET(dip->di_core.di_onlink, - ARCH_CONVERT); - if (INT_GET(dip->di_core.di_version, ARCH_CONVERT) == - XFS_DINODE_VERSION_1) - dip->di_core.di_nlink = dip->di_core.di_onlink; - else - dip->di_core.di_nlink = - INT_GET(dip->di_core.di_nlink, - ARCH_CONVERT); - - if (dip->di_core.di_magic != XFS_DINODE_MAGIC) { - if (!no_modify) { - do_error( - _("ino: %llu, bad d_inode magic saw: (0x%x) expecting (0x%x)\n"), - ino, dip->di_core.di_magic, XFS_DINODE_MAGIC); - /* NOT REACHED */ - } - do_warn( - _("ino: %llu, bad d_inode magic saw: (0x%x) expecting (0x%x)\n"), - ino, dip->di_core.di_magic, XFS_DINODE_MAGIC); - continue; - } - /* - * compare and set links for all inodes - * but the lost+found inode. we keep - * that correct as we go. - */ - if (dip->di_core.di_nlink != nrefs) { - if (ino != orphanage_ino) { - set_nlinks(&dip->di_core, ino, - nrefs, &inode_dirty); - } - } - - /* Swap the fields back */ - dip->di_core.di_magic = INT_GET(dip->di_core.di_magic, - ARCH_CONVERT); - if (inode_dirty && INT_GET(dip->di_core.di_version, - ARCH_CONVERT) == XFS_DINODE_VERSION_1) { - if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) { - ASSERT(dip->di_core.di_nlink <= - XFS_MAXLINK_1); - INT_SET(dip->di_core.di_onlink, - ARCH_CONVERT, - dip->di_core.di_nlink); - dip->di_core.di_nlink = - INT_GET(dip->di_core.di_nlink, - ARCH_CONVERT); - } else { - /* superblock support v2 nlinks */ - INT_SET(dip->di_core.di_version, - ARCH_CONVERT, XFS_DINODE_VERSION_2); - dip->di_core.di_nlink = - INT_GET(dip->di_core.di_nlink, - ARCH_CONVERT); - dip->di_core.di_onlink = 0; - memset(&(dip->di_core.di_pad[0]), 0, - sizeof(dip->di_core.di_pad)); - } - } else { - dip->di_core.di_nlink = - INT_GET(dip->di_core.di_nlink, - ARCH_CONVERT); - dip->di_core.di_onlink = - INT_GET(dip->di_core.di_onlink, - ARCH_CONVERT); - } - chunk_dirty |= inode_dirty; + if (get_inode_disk_nlinks(irec, j) != nrefs) + update_inode_nlinks(mp, XFS_AGINO_TO_INO(mp, + agno, irec->ino_startnum + j), + nrefs); } - - if (chunk_dirty) - libxfs_writebuf(bp, 0); - else - libxfs_putbuf(bp); - irec = next_ino_rec(irec); PROG_RPT_INC(prog_rpt_done[agno], XFS_INODES_PER_CHUNK); } } -void +static void phase7_alt(xfs_mount_t *mp) { int i; set_progress_msg(no_modify ? PROGRESS_FMT_VRFY_LINK : PROGRESS_FMT_CORR_LINK, (__uint64_t) mp->m_sb.sb_icount); - libxfs_bcache_purge(); for (i = 0; i < glob_agcount; i++) { queue_work(phase7_alt_function, mp, i); @@ -238,13 +174,8 @@ void phase7(xfs_mount_t *mp) { ino_tree_node_t *irec; - xfs_inode_t *ip; - xfs_trans_t *tp; int i; int j; - int error; - int dirty; - xfs_ino_t ino; __uint32_t nrefs; if (!no_modify) @@ -252,25 +183,14 @@ phase7(xfs_mount_t *mp) else do_log(_("Phase 7 - verify link counts...\n")); - if (do_prefetch) { phase7_alt(mp); return; } - tp = libxfs_trans_alloc(mp, XFS_TRANS_REMOVE); - - error = libxfs_trans_reserve(tp, (no_modify ? 0 : 10), - XFS_REMOVE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES, - XFS_REMOVE_LOG_COUNT); - - ASSERT(error == 0); - /* - * for each ag, look at each inode 1 at a time using the - * sim code. if the number of links is bad, reset it, - * log the inode core, commit the transaction, and - * allocate a new transaction + * for each ag, look at each inode 1 at a time. If the number of + * links is bad, reset it, log the inode core, commit the transaction */ for (i = 0; i < glob_agcount; i++) { irec = findfirst_inode_rec(i); @@ -288,69 +208,13 @@ phase7(xfs_mount_t *mp) nrefs = num_inode_references(irec, j); - ino = XFS_AGINO_TO_INO(mp, i, - irec->ino_startnum + j); - - error = libxfs_trans_iget(mp, tp, ino, 0, 0, &ip); - - if (error) { - if (!no_modify) - do_error( - _("couldn't map inode %llu, err = %d\n"), - ino, error); - else { - do_warn( - _("couldn't map inode %llu, err = %d, can't compare link counts\n"), - ino, error); - continue; - } - } - - dirty = 0; - - /* - * compare and set links for all inodes - * but the lost+found inode. we keep - * that correct as we go. - */ - if (ino != orphanage_ino) - set_nlinks(&ip->i_d, ino, nrefs, - &dirty); - - if (!dirty) { - libxfs_trans_iput(tp, ip, 0); - } else { - libxfs_trans_log_inode(tp, ip, - XFS_ILOG_CORE); - /* - * no need to do a bmap finish since - * we're not allocating anything - */ - ASSERT(error == 0); - error = libxfs_trans_commit(tp, - XFS_TRANS_RELEASE_LOG_RES| - XFS_TRANS_SYNC, NULL); - - ASSERT(error == 0); - - tp = libxfs_trans_alloc(mp, - XFS_TRANS_REMOVE); - - error = libxfs_trans_reserve(tp, - (no_modify ? 0 : 10), - XFS_REMOVE_LOG_RES(mp), - 0, XFS_TRANS_PERM_LOG_RES, - XFS_REMOVE_LOG_COUNT); - ASSERT(error == 0); - } + if (get_inode_disk_nlinks(irec, j) != nrefs) + update_inode_nlinks(mp, + XFS_AGINO_TO_INO(mp, i, + irec->ino_startnum + j), + nrefs); } irec = next_ino_rec(irec); } } - - /* - * always have one unfinished transaction coming out - * of the loop. cancel it. - */ - libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); } diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index c5d82ad84..3f4f5cecb 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -169,7 +169,7 @@ process_args(int argc, char **argv) isa_file = 0; zap_log = 0; dumpcore = 0; - full_backptrs = 0; + full_ino_ex_data = 0; delete_attr_ok = 1; force_geo = 0; assume_xfs = 0; @@ -277,7 +277,7 @@ process_args(int argc, char **argv) case 't': report_interval = (int) strtol(optarg, 0, 0); break; - + case '?': usage(); } @@ -563,7 +563,7 @@ main(int argc, char **argv) /* XXX: nathans - something in phase4 ain't playing by */ /* the buffer cache rules.. why doesn't IRIX hit this? */ - libxfs_bcache_purge(); + libxfs_bcache_flush(); if (no_modify) printf(_("No modify flag set, skipping phase 5\n")); @@ -576,6 +576,8 @@ main(int argc, char **argv) phase6(mp); timestamp(PHASE_END, 6, NULL); + libxfs_bcache_flush(); + phase7(mp); timestamp(PHASE_END, 7, NULL); } else {