From 1e77098cf18c7a69534c7fab1a58ccd878810aca Mon Sep 17 00:00:00 2001 From: Madan Valluri Date: Fri, 12 May 2006 16:03:02 +0000 Subject: [PATCH] These changes fall into three categores which are: 1) Eliminate compiler warning (COMP) 2) Bug fixes (BUG) 3) Reduce CPU cycles. (CPU) 1) Supply cast to libxfs_da_hashname (COMP) --- repair/attr_repair.c | 4 +- repair/avl.c | 28 -------- repair/avl.h | 22 +++++- repair/bmap.c | 15 +++- repair/bmap.h | 3 +- repair/dinode.c | 167 +++++++++++++++++++++++++++++-------------- repair/dir.c | 2 +- repair/dir2.c | 52 +++++++++----- repair/incore.h | 94 +++++++++++++++++++++--- repair/incore_ext.c | 17 +---- repair/incore_ino.c | 22 +----- repair/phase4.c | 15 ++++ repair/phase5.c | 20 ++++++ repair/phase6.c | 2 +- 14 files changed, 312 insertions(+), 151 deletions(-) diff --git a/repair/attr_repair.c b/repair/attr_repair.c index ce98a2ef6..587c1dd34 100644 --- a/repair/attr_repair.c +++ b/repair/attr_repair.c @@ -476,7 +476,7 @@ process_leaf_attr_block( * hashvalue were wrong but matched. Unlikely, however. */ if (INT_GET(entry->hashval, ARCH_CONVERT) != - libxfs_da_hashname((char *)&local->nameval[0], + libxfs_da_hashname((uchar_t *)&local->nameval[0], INT_GET(local->namelen, ARCH_CONVERT)) || (INT_GET(entry->hashval, ARCH_CONVERT) < @@ -517,7 +517,7 @@ process_leaf_attr_block( INT_GET(remotep->namelen, ARCH_CONVERT))) || (INT_GET(entry->hashval, ARCH_CONVERT) != libxfs_da_hashname( - (char *)&remotep->name[0], + (uchar_t *)&remotep->name[0], INT_GET(remotep->namelen, ARCH_CONVERT))) || (INT_GET(entry->hashval, ARCH_CONVERT) < last_hashval) || diff --git a/repair/avl.c b/repair/avl.c index 8316dc466..169c85993 100644 --- a/repair/avl.c +++ b/repair/avl.c @@ -654,34 +654,6 @@ avl_findanyrange( return NULL; } - -/* - * Returns a pointer to range which contains value. - */ -avlnode_t * -avl_findrange( - register avltree_desc_t *tree, - register __psunsigned_t value) -{ - register avlnode_t *np = tree->avl_root; - - while (np) { - if (value < AVL_START(tree, np)) { - np = np->avl_back; - continue; - } - if (value >= AVL_END(tree, np)) { - np = np->avl_forw; - continue; - } - ASSERT(AVL_START(tree, np) <= value && - value < AVL_END(tree, np)); - return np; - } - return NULL; -} - - /* * Returns a pointer to node which contains exact value. */ diff --git a/repair/avl.h b/repair/avl.h index e5f9a0601..d65a76ff6 100644 --- a/repair/avl.h +++ b/repair/avl.h @@ -84,10 +84,28 @@ avl_init_tree( avltree_desc_t *tree, avlops_t *ops); -avlnode_t * +__inline avlnode_t * avl_findrange( avltree_desc_t *tree, - __psunsigned_t value); + __psunsigned_t value) +{ + register avlnode_t *np = tree->avl_root; + + while (np) { + if (value < AVL_START(tree, np)) { + np = np->avl_back; + continue; + } + if (value >= AVL_END(tree, np)) { + np = np->avl_forw; + continue; + } + ASSERT(AVL_START(tree, np) <= value && + value < AVL_END(tree, np)); + return np; + } + return NULL; +} avlnode_t * avl_find( diff --git a/repair/bmap.c b/repair/bmap.c index c82219cff..05d5da89b 100644 --- a/repair/bmap.c +++ b/repair/bmap.c @@ -169,7 +169,8 @@ blkmap_getn( blkmap_t *blkmap, xfs_dfiloff_t o, xfs_dfilblks_t nb, - bmap_ext_t **bmpp) + bmap_ext_t **bmpp, + bmap_ext_t *bmpp_single) { bmap_ext_t *bmp; blkent_t *ent; @@ -178,6 +179,18 @@ blkmap_getn( int i; int nex; + if (nb == 1) { + /* + * in the common case, when mp->m_dirblkfsbs == 1, + * avoid additional malloc/free overhead + */ + bmpp_single->startblock = blkmap_get(blkmap, o); + bmpp_single->blockcount = 1; + bmpp_single->startoff = 0; + bmpp_single->flag = 0; + *bmpp = bmpp_single; + return (bmpp_single->startblock != NULLDFSBNO) ? 1 : 0; + } for (i = nex = 0, bmp = NULL, entp = blkmap->ents; i < blkmap->nents; i++, entp++) { diff --git a/repair/bmap.h b/repair/bmap.h index 1f400e774..eba1799f5 100644 --- a/repair/bmap.h +++ b/repair/bmap.h @@ -61,7 +61,8 @@ blkmap_t *blkmap_alloc(xfs_extnum_t); void blkmap_free(blkmap_t *blkmap); xfs_dfsbno_t blkmap_get(blkmap_t *blkmap, xfs_dfiloff_t o); int blkmap_getn(blkmap_t *blkmap, xfs_dfiloff_t o, - xfs_dfilblks_t nb, bmap_ext_t **bmpp); + xfs_dfilblks_t nb, bmap_ext_t **bmpp, + bmap_ext_t *bmpp_single); void blkmap_grow(blkmap_t **blkmapp, blkent_t **entp, blkent_t *newent); xfs_dfiloff_t blkmap_last_off(blkmap_t *blkmap); diff --git a/repair/dinode.c b/repair/dinode.c index a475f159e..4395aa077 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -306,6 +306,33 @@ clear_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num) * misc. inode-related utility routines */ +/* + * verify_ag_bno is heavily used. In the common case, it + * performs just two number of compares + */ +static __inline int +verify_ag_bno(xfs_sb_t *sbp, + xfs_agnumber_t agno, + xfs_agblock_t agbno) +{ + if (agno < sbp->sb_agcount) { + if (agbno >= sbp->sb_agblocks) { + return 1; /* bad */ + } + return 0; /* good */ + } + if (agno == sbp->sb_agcount) { + if (agbno >= + (sbp->sb_dblocks - + (sbp->sb_agcount-1) * + sbp->sb_agblocks)) { + return 1; /* bad */ + } + return 0; /* good */ + } + return 1; /* bad */ +} + /* * returns 0 if inode number is valid, 1 if bogus */ @@ -323,6 +350,8 @@ verify_inum(xfs_mount_t *mp, agno = XFS_INO_TO_AGNO(mp, ino); agino = XFS_INO_TO_AGINO(mp, ino); agbno = XFS_AGINO_TO_AGBNO(mp, agino); + if (agbno == 0) + return 1; if (ino == 0 || ino == NULLFSINO) return(1); @@ -330,14 +359,7 @@ verify_inum(xfs_mount_t *mp, if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) return(1); - if (agno >= sbp->sb_agcount || - (agno < sbp->sb_agcount && agbno >= sbp->sb_agblocks) || - (agno == sbp->sb_agcount && agbno >= sbp->sb_dblocks - - (sbp->sb_agcount-1) * sbp->sb_agblocks) || - (agbno == 0)) - return(1); - - return(0); + return verify_ag_bno(sbp, agno, agbno); } /* @@ -366,15 +388,10 @@ verify_aginum(xfs_mount_t *mp, * will be extra bits set at the top that shouldn't be set. */ agbno = XFS_AGINO_TO_AGBNO(mp, agino); + if (agbno == 0) + return 1; - if (agno >= sbp->sb_agcount || - (agno < sbp->sb_agcount && agbno >= sbp->sb_agblocks) || - (agno == sbp->sb_agcount && agbno >= sbp->sb_dblocks - - (sbp->sb_agcount-1) * sbp->sb_agblocks) || - (agbno == 0)) - return(1); - - return(0); + return verify_ag_bno(sbp, agno, agbno); } /* @@ -393,13 +410,40 @@ verify_dfsbno(xfs_mount_t *mp, agno = XFS_FSB_TO_AGNO(mp, fsbno); agbno = XFS_FSB_TO_AGBNO(mp, fsbno); - if (agno >= sbp->sb_agcount || - (agno < sbp->sb_agcount && agbno >= sbp->sb_agblocks) || - (agno == sbp->sb_agcount && agbno >= sbp->sb_dblocks - - (sbp->sb_agcount-1) * sbp->sb_agblocks)) - return(0); + return verify_ag_bno(sbp, agno, agbno) == 0; +} - return(1); +#define XR_DFSBNORANGE_VALID 0 +#define XR_DFSBNORANGE_BADSTART 1 +#define XR_DFSBNORANGE_BADEND 2 +#define XR_DFSBNORANGE_OVERFLOW 3 + +static __inline int +verify_dfsbno_range(xfs_mount_t *mp, + xfs_dfsbno_t fsbno, + xfs_dfilblks_t count) +{ + xfs_agnumber_t agno; + xfs_agblock_t agbno; + xfs_sb_t *sbp = &mp->m_sb;; + + /* the start and end blocks better be in the same allocation group */ + agno = XFS_FSB_TO_AGNO(mp, fsbno); + if (agno != XFS_FSB_TO_AGNO(mp, fsbno + count - 1)) { + return XR_DFSBNORANGE_OVERFLOW; + } + + agbno = XFS_FSB_TO_AGBNO(mp, fsbno); + if (verify_ag_bno(sbp, agno, agbno)) { + return XR_DFSBNORANGE_BADSTART; + } + + agbno = XFS_FSB_TO_AGBNO(mp, fsbno + count - 1); + if (verify_ag_bno(sbp, agno, agbno)) { + return XR_DFSBNORANGE_BADEND; + } + + return (XR_DFSBNORANGE_VALID); } int @@ -410,14 +454,7 @@ verify_agbno(xfs_mount_t *mp, xfs_sb_t *sbp = &mp->m_sb;; /* range check ag #, ag block. range-checking offset is pointless */ - - if (agno >= sbp->sb_agcount || - (agno < sbp->sb_agcount && agbno >= sbp->sb_agblocks) || - (agno == sbp->sb_agcount && agbno >= sbp->sb_dblocks - - (sbp->sb_agcount-1) * sbp->sb_agblocks)) - return(0); - - return(1); + return verify_ag_bno(sbp, agno, agbno) == 0; } void @@ -512,6 +549,9 @@ process_bmbt_reclist_int( int state; int flag; /* extent flag */ int pwe; /* partially-written extent */ + xfs_dfsbno_t e; + xfs_agnumber_t agno; + xfs_agblock_t agbno; if (whichfork == XFS_DATA_FORK) forkname = _("data"); @@ -570,20 +610,22 @@ process_bmbt_reclist_int( return(1); } } else { - if (!verify_dfsbno(mp, s)) { + switch (verify_dfsbno_range(mp, s, c)) { + case XR_DFSBNORANGE_VALID: + break; + case XR_DFSBNORANGE_BADSTART: do_warn( _("inode %llu - bad extent starting block number %llu, offset %llu\n"), ino, s, o); return(1); - } - if (!verify_dfsbno(mp, s + c - 1)) { + case XR_DFSBNORANGE_BADEND: do_warn( _("inode %llu - bad extent last block number %llu, offset %llu\n"), ino, s + c - 1, o); return(1); - } - if (s + c - 1 < s) { + case XR_DFSBNORANGE_OVERFLOW: do_warn( + _("inode %llu - bad extent overflows - start %llu, end %llu, " "offset %llu\n"), ino, s, s + c - 1, o); @@ -699,7 +741,14 @@ process_bmbt_reclist_int( */ if (blkmapp && *blkmapp) blkmap_set_ext(blkmapp, o, s, c); - for (b = s; b < s + c; b++) { + /* + * Profiling shows that the following loop takes the + * most time in all of xfs_repair. + */ + agno = XFS_FSB_TO_AGNO(mp, s); + agbno = XFS_FSB_TO_AGBNO(mp, s); + e = s + c; + for (b = s; b < e; b++, agbno++) { if (check_dups == 1) { /* * if we're just checking the bmap for dups, @@ -707,9 +756,7 @@ process_bmbt_reclist_int( * checking each entry without setting the * block bitmap */ - if (search_dup_extent(mp, - XFS_FSB_TO_AGNO(mp, b), - XFS_FSB_TO_AGBNO(mp, b))) { + if (search_dup_extent(mp, agno, agbno)) { do_warn( _("%s fork in ino %llu claims dup extent, off - %llu, " "start - %llu, cnt %llu\n"), @@ -724,11 +771,24 @@ process_bmbt_reclist_int( * in regular data space, not realtime partion. */ if (type == XR_INO_RTDATA && whichfork == XFS_ATTR_FORK) { - if (mp->m_sb.sb_agcount < XFS_FSB_TO_AGNO(mp, b)) + if (mp->m_sb.sb_agcount < agno) return(1); } - state = get_fsbno_state(mp, b); + /* Process in chunks of 16 (XR_BB_UNIT/XR_BB) + * for common XR_E_UNKNOWN to XR_E_INUSE transition + */ + if (((agbno & XR_BB_MASK) == 0) && ((s + c - b) >= (XR_BB_UNIT/XR_BB))) { + if (ba_bmap[agno][agbno>>XR_BB] == XR_E_UNKNOWN_LL) { + ba_bmap[agno][agbno>>XR_BB] = XR_E_INUSE_LL; + agbno += (XR_BB_UNIT/XR_BB) - 1; + b += (XR_BB_UNIT/XR_BB) - 1; + continue; + } + + } + + state = get_agbno_state(mp, agno, agbno); switch (state) { case XR_E_FREE: case XR_E_FREE1: @@ -737,7 +797,7 @@ process_bmbt_reclist_int( forkname, ino, (__uint64_t) b); /* fall through ... */ case XR_E_UNKNOWN: - set_fsbno_state(mp, b, XR_E_INUSE); + set_agbno_state(mp, agno, agbno, XR_E_INUSE); break; case XR_E_BAD_STATE: do_error(_("bad state in block map %llu\n"), b); @@ -752,7 +812,7 @@ process_bmbt_reclist_int( return(1); case XR_E_INUSE: case XR_E_MULT: - set_fsbno_state(mp, b, XR_E_MULT); + set_agbno_state(mp, agno, agbno, XR_E_MULT); do_warn( _("%s fork in %s inode %llu claims used block %llu\n"), forkname, ftype, ino, (__uint64_t) b); @@ -898,7 +958,9 @@ getfunc_btree(xfs_mount_t *mp, int whichfork) { int i; +#ifdef DEBUG int prev_level; +#endif int flag; int found; xfs_bmbt_rec_32_t *rec; @@ -961,12 +1023,16 @@ getfunc_btree(xfs_mount_t *mp, /* * ok, now traverse any interior btree nodes */ - prev_level = rootblock->bb_level; +#ifdef DEBUG + prev_level = INT_GET(block->bb_level, ARCH_CONVERT); +#endif while (INT_GET(block->bb_level, ARCH_CONVERT) > 0) { +#ifdef DEBUG ASSERT(INT_GET(block->bb_level, ARCH_CONVERT) < prev_level); prev_level = INT_GET(block->bb_level, ARCH_CONVERT); +#endif if (INT_GET(block->bb_numrecs, ARCH_CONVERT) > mp->m_bmap_dmxr[1]) { @@ -1647,7 +1713,7 @@ process_misc_ino_types(xfs_mount_t *mp, return(0); } -int +static __inline int process_misc_ino_types_blocks(xfs_drfsbno_t totblocks, xfs_ino_t lino, int type) { /* @@ -1901,8 +1967,7 @@ process_dinode_int(xfs_mount_t *mp, */ if (INT_GET(dinoc->di_mode, ARCH_CONVERT) != 0 && ((((INT_GET(dinoc->di_mode, ARCH_CONVERT) & S_IFMT) >> 12) > 15) || - dinoc->di_format < XFS_DINODE_FMT_DEV || - dinoc->di_format > XFS_DINODE_FMT_UUID || + (uchar_t) dinoc->di_format > XFS_DINODE_FMT_UUID || (!(okfmts[(INT_GET(dinoc->di_mode, ARCH_CONVERT) & S_IFMT) >> 12] & (1 << dinoc->di_format))))) { /* bad inode format */ @@ -2385,7 +2450,6 @@ _("mismatch between format (%d) and size (%lld) in directory ino %llu\n"), *used = is_free; *isa_dir = 0; blkmap_free(dblkmap); - return(1); } @@ -2426,7 +2490,6 @@ _("mismatch between format (%d) and size (%lld) in directory ino %llu\n"), *used = is_free; *isa_dir = 0; blkmap_free(dblkmap); - return(1); } @@ -2549,7 +2612,6 @@ _("mismatch between format (%d) and size (%lld) in directory ino %llu\n"), *isa_dir = 0; blkmap_free(dblkmap); blkmap_free(ablkmap); - return(1); } @@ -2602,7 +2664,6 @@ _("mismatch between format (%d) and size (%lld) in directory ino %llu\n"), *used = is_free; *isa_dir = 0; blkmap_free(dblkmap); - return(1); } @@ -2669,7 +2730,6 @@ _("mismatch between format (%d) and size (%lld) in directory ino %llu\n"), *used = is_free; *isa_dir = 0; blkmap_free(dblkmap); - return(1); } if (anextents != INT_GET(dinoc->di_anextents, ARCH_CONVERT)) { @@ -2732,7 +2792,8 @@ _("mismatch between format (%d) and size (%lld) in directory ino %llu\n"), abort(); } - blkmap_free(dblkmap); + if (dblkmap) + blkmap_free(dblkmap); if (err) { /* diff --git a/repair/dir.c b/repair/dir.c index d37693b79..011cacfea 100644 --- a/repair/dir.c +++ b/repair/dir.c @@ -2138,7 +2138,7 @@ _("dir entry slot %d in block %u conflicts with used space in dir inode %llu\n") */ bcopy(namest->name, fname, entry->namelen); fname[entry->namelen] = '\0'; - hashval = libxfs_da_hashname(fname, entry->namelen); + hashval = libxfs_da_hashname((uchar_t *) fname, entry->namelen); /* * only complain about illegal names in phase 3 (when diff --git a/repair/dir2.c b/repair/dir2.c index 401d4b62d..0dc82ae44 100644 --- a/repair/dir2.c +++ b/repair/dir2.c @@ -83,15 +83,22 @@ da_read_buf( bmap_ext_t *bmp) { xfs_buf_t *bp; + xfs_buf_t *bparray[4]; xfs_buf_t **bplist; xfs_dabuf_t *dabuf; int i; int off; - bplist = calloc(nex, sizeof(*bplist)); - if (bplist == NULL) { - do_error(_("couldn't malloc dir2 buffer list\n")); - exit(1); + if (nex > (sizeof(bparray)/sizeof(xfs_buf_t *))) { + bplist = calloc(nex, sizeof(*bplist)); + if (bplist == NULL) { + do_error(_("couldn't malloc dir2 buffer list\n")); + exit(1); + } + } + else { + /* common case avoids calloc/free */ + bplist = bparray; } for (i = 0; i < nex; i++) { bplist[i] = libxfs_readbuf(mp->m_dev, @@ -128,12 +135,14 @@ da_read_buf( XFS_BUF_COUNT(bp)); } } - free(bplist); + if (bplist != bparray) + free(bplist); return dabuf; failed: for (i = 0; i < nex; i++) libxfs_putbuf(bplist[i]); - free(bplist); + if (bplist != bparray) + free(bplist); return NULL; } @@ -249,6 +258,7 @@ traverse_int_dir2block(xfs_mount_t *mp, int i; int nex; xfs_da_intnode_t *node; + bmap_ext_t lbmp; /* * traverse down left-side of tree until we hit the @@ -265,13 +275,14 @@ traverse_int_dir2block(xfs_mount_t *mp, * read in each block along the way and set up cursor */ nex = blkmap_getn(da_cursor->blkmap, bno, mp->m_dirblkfsbs, - &bmp); + &bmp, &lbmp); if (nex == 0) goto error_out; bp = da_read_buf(mp, nex, bmp); - free(bmp); + if (bmp != &lbmp) + free(bmp); if (bp == NULL) { do_warn(_("can't read block %u for directory inode " "%llu\n"), @@ -578,6 +589,7 @@ verify_dir2_path(xfs_mount_t *mp, int this_level = p_level + 1; bmap_ext_t *bmp; int nex; + bmap_ext_t lbmp; /* * index is currently set to point to the entry that @@ -619,7 +631,7 @@ verify_dir2_path(xfs_mount_t *mp, dabno = INT_GET(node->hdr.info.forw, ARCH_CONVERT); ASSERT(dabno != 0); nex = blkmap_getn(cursor->blkmap, dabno, mp->m_dirblkfsbs, - &bmp); + &bmp, &lbmp); if (nex == 0) { do_warn(_("can't get map info for block %u of " "directory inode %llu\n"), @@ -628,6 +640,8 @@ verify_dir2_path(xfs_mount_t *mp, } bp = da_read_buf(mp, nex, bmp); + if (bmp != &lbmp) + free(bmp); if (bp == NULL) { do_warn(_("can't read block %u for directory inode " @@ -1674,17 +1688,19 @@ process_block_dir2( xfs_dir2_block_tail_t *btp; int nex; int rval; + bmap_ext_t lbmp; *repair = *dot = *dotdot = 0; *parent = NULLFSINO; - nex = blkmap_getn(blkmap, mp->m_dirdatablk, mp->m_dirblkfsbs, &bmp); + nex = blkmap_getn(blkmap, mp->m_dirdatablk, mp->m_dirblkfsbs, &bmp, &lbmp); if (nex == 0) { do_warn(_("block %u for directory inode %llu is missing\n"), mp->m_dirdatablk, ino); return 1; } bp = da_read_buf(mp, nex, bmp); - free(bmp); + if (bmp != &lbmp) + free(bmp); if (bp == NULL) { do_warn(_("can't read block %u for directory inode %llu\n"), mp->m_dirdatablk, ino); @@ -1786,6 +1802,7 @@ process_leaf_level_dir2( xfs_dir2_leaf_t *leaf; int nex; xfs_dablk_t prev_bno; + bmap_ext_t lbmp; da_bno = da_cursor->level[0].bno; ino = da_cursor->ino; @@ -1796,7 +1813,7 @@ process_leaf_level_dir2( do { nex = blkmap_getn(da_cursor->blkmap, da_bno, mp->m_dirblkfsbs, - &bmp); + &bmp, &lbmp); /* * Directory code uses 0 as the NULL block pointer since 0 * is the root block and no directory block pointer can point @@ -1811,7 +1828,8 @@ process_leaf_level_dir2( goto error_out; } bp = da_read_buf(mp, nex, bmp); - free(bmp); + if (bmp != &lbmp) + free(bmp); bmp = NULL; if (bp == NULL) { do_warn(_("can't read file block %u for directory " @@ -1895,7 +1913,7 @@ error_out: * Release all buffers holding interior btree blocks. */ err_release_dir2_cursor(mp, da_cursor, 0); - if (bmp) + if (bmp && (bmp != &lbmp)) free(bmp); return 1; } @@ -1976,12 +1994,13 @@ process_leaf_node_dir2( xfs_dfiloff_t ndbno; int nex; int t; + bmap_ext_t lbmp; *repair = *dot = *dotdot = good = 0; *parent = NULLFSINO; ndbno = NULLDFILOFF; while ((dbno = blkmap_next_off(blkmap, ndbno, &t)) < mp->m_dirleafblk) { - nex = blkmap_getn(blkmap, dbno, mp->m_dirblkfsbs, &bmp); + nex = blkmap_getn(blkmap, dbno, mp->m_dirblkfsbs, &bmp, &lbmp); ndbno = dbno + mp->m_dirblkfsbs - 1; if (nex == 0) { do_warn(_("block %llu for directory inode %llu is " @@ -1990,7 +2009,8 @@ process_leaf_node_dir2( continue; } bp = da_read_buf(mp, nex, bmp); - free(bmp); + if (bmp != &lbmp) + free(bmp); if (bp == NULL) { do_warn(_("can't read block %llu for directory inode " "%llu\n"), diff --git a/repair/incore.h b/repair/incore.h index eef8f6cd6..25eabdc19 100644 --- a/repair/incore.h +++ b/repair/incore.h @@ -167,6 +167,16 @@ typedef struct rt_extent_tree_node { #define XR_E_FS_MAP 7 /* extent used by fs space/inode maps */ #define XR_E_BAD_STATE 8 +/* extent states, in 64 bit word chunks */ +#define XR_E_UNKNOWN_LL 0x0000000000000000LL +#define XR_E_FREE1_LL 0x1111111111111111LL +#define XR_E_FREE_LL 0x2222222222222222LL +#define XR_E_INUSE_LL 0x3333333333333333LL +#define XR_E_INUSE_FS_LL 0x4444444444444444LL +#define XR_E_MULT_LL 0x5555555555555555LL +#define XR_E_INO_LL 0x6666666666666666LL +#define XR_E_FS_MAP_LL 0x7777777777777777LL + /* separate state bit, OR'ed into high (4th) bit of ex_state field */ #define XR_E_WRITTEN 0x8 /* extent has been written out, can't reclaim */ @@ -227,9 +237,18 @@ void add_dup_extent(xfs_agnumber_t agno, xfs_agblock_t startblock, xfs_extlen_t blockcount); -int search_dup_extent(xfs_mount_t *mp, - xfs_agnumber_t agno, - xfs_agblock_t agbno); +extern avltree_desc_t **extent_tree_ptrs; +/* ARGSUSED */ +static __inline int +search_dup_extent(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agblock_t agbno) +{ + ASSERT(agno < glob_agcount); + + if (avl_findrange(extent_tree_ptrs[agno], agbno) != NULL) + return(1); + + return(0); +} void add_rt_dup_extent(xfs_drtbno_t startblock, xfs_extlen_t blockcount); @@ -348,8 +367,18 @@ void free_inode_rec(xfs_agnumber_t agno, ino_tree_node_t *ino_rec); */ void get_inode_rec(xfs_agnumber_t agno, ino_tree_node_t *ino_rec); -ino_tree_node_t *findfirst_inode_rec(xfs_agnumber_t agno); -ino_tree_node_t *find_inode_rec(xfs_agnumber_t agno, xfs_agino_t ino); +extern avltree_desc_t **inode_tree_ptrs; +static __inline ino_tree_node_t * +findfirst_inode_rec(xfs_agnumber_t agno) +{ + return((ino_tree_node_t *) inode_tree_ptrs[agno]->avl_firstino); +} +static __inline ino_tree_node_t * +find_inode_rec(xfs_agnumber_t agno, xfs_agino_t ino) +{ + return((ino_tree_node_t *) + avl_findrange(inode_tree_ptrs[agno], ino)); +} void find_inode_rec_range(xfs_agnumber_t agno, xfs_agino_t start_ino, xfs_agino_t end_ino, ino_tree_node_t **first, ino_tree_node_t **last); @@ -486,12 +515,55 @@ void clear_uncertain_ino_cache(xfs_agnumber_t agno); * an inode that we've counted is removed. */ -void add_inode_reached(ino_tree_node_t *ino_rec, int ino_offset); -void add_inode_ref(ino_tree_node_t *ino_rec, int ino_offset); -void drop_inode_ref(ino_tree_node_t *ino_rec, int ino_offset); -int is_inode_reached(ino_tree_node_t *ino_rec, int ino_offset); -int is_inode_referenced(ino_tree_node_t *ino_rec, int ino_offset); -__uint32_t num_inode_references(ino_tree_node_t *ino_rec, int ino_offset); +static __inline int +is_inode_reached(ino_tree_node_t *ino_rec, int ino_offset) +{ + ASSERT(ino_rec->ino_un.backptrs != 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); + + ino_rec->ino_un.backptrs->nlinks[ino_offset]++; + XFS_INO_RCHD_SET_RCHD(ino_rec, ino_offset); + + ASSERT(is_inode_reached(ino_rec, ino_offset)); +} + +static __inline void +add_inode_ref(ino_tree_node_t *ino_rec, int ino_offset) +{ + ASSERT(ino_rec->ino_un.backptrs != NULL); + + ino_rec->ino_un.backptrs->nlinks[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); + + if (--ino_rec->ino_un.backptrs->nlinks[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); +} + +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]); +} /* * has an inode been processed for phase 6 (reference count checking)? diff --git a/repair/incore_ext.c b/repair/incore_ext.c index de0154ccf..d98f246e9 100644 --- a/repair/incore_ext.c +++ b/repair/incore_ext.c @@ -71,7 +71,7 @@ static rt_ext_flist_t rt_ext_flist; static avl64tree_desc_t *rt_ext_tree_ptr; /* dup extent tree for rt */ -static avltree_desc_t **extent_tree_ptrs; /* array of extent tree ptrs */ +avltree_desc_t **extent_tree_ptrs; /* array of extent tree ptrs */ /* one per ag for dups */ static avltree_desc_t **extent_bno_ptrs; /* * array of extent tree ptrs @@ -573,21 +573,6 @@ add_dup_extent(xfs_agnumber_t agno, xfs_agblock_t startblock, return; } -/* - * returns 1 if block is a dup, 0 if not - */ -/* ARGSUSED */ -int -search_dup_extent(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agblock_t agbno) -{ - ASSERT(agno < glob_agcount); - - if (avl_findrange(extent_tree_ptrs[agno], agbno) != NULL) - return(1); - - return(0); -} - static __psunsigned_t avl_ext_start(avlnode_t *node) { diff --git a/repair/incore_ino.c b/repair/incore_ino.c index 08f0eef56..39093fc19 100644 --- a/repair/incore_ino.c +++ b/repair/incore_ino.c @@ -29,7 +29,7 @@ extern avlnode_t *avl_firstino(avlnode_t *root); /* * array of inode tree ptrs, one per ag */ -static avltree_desc_t **inode_tree_ptrs; +avltree_desc_t **inode_tree_ptrs; /* * ditto for uncertain inodes @@ -323,18 +323,6 @@ free_inode_rec(xfs_agnumber_t agno, ino_tree_node_t *ino_rec) return; } -/* - * returns the inode record desired containing the inode - * returns NULL if inode doesn't exist. The tree-based find - * routines do NOT pull records out of the tree. - */ -ino_tree_node_t * -find_inode_rec(xfs_agnumber_t agno, xfs_agino_t ino) -{ - return((ino_tree_node_t *) - avl_findrange(inode_tree_ptrs[agno], ino)); -} - void find_inode_rec_range(xfs_agnumber_t agno, xfs_agino_t start_ino, xfs_agino_t end_ino, ino_tree_node_t **first, @@ -389,12 +377,6 @@ set_inode_free_alloc(xfs_agnumber_t agno, xfs_agino_t ino) return(ino_rec); } -ino_tree_node_t * -findfirst_inode_rec(xfs_agnumber_t agno) -{ - return((ino_tree_node_t *) inode_tree_ptrs[agno]->avl_firstino); -} - void print_inode_list_int(xfs_agnumber_t agno, int uncertain) { @@ -589,6 +571,7 @@ get_inode_parent(ino_tree_node_t *irec, int offset) * pointers, link counts and reached bits for phase 6 and phase 7. */ +#ifdef DEBUG void add_inode_reached(ino_tree_node_t *ino_rec, int ino_offset) { @@ -644,6 +627,7 @@ 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]); } +#endif /* DEBUG */ #if 0 static backptrs_t *bptrs; diff --git a/repair/phase4.c b/repair/phase4.c index cfc286bc8..492bd86a7 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -1176,6 +1176,21 @@ phase4(xfs_mount_t *mp) */ for (j = ag_hdr_block; j < ag_end; j++) { + /* Process in chunks of 16 (XR_BB_UNIT/XR_BB) */ + if ((extent_start == 0) && ((j & XR_BB_MASK) == 0)) { + switch(ba_bmap[i][j>>XR_BB]) { + case XR_E_UNKNOWN_LL: + case XR_E_FREE1_LL: + case XR_E_FREE_LL: + case XR_E_INUSE_LL: + case XR_E_INUSE_FS_LL: + case XR_E_INO_LL: + case XR_E_FS_MAP_LL: + j += (XR_BB_UNIT/XR_BB) - 1; + continue; + } + } + bstate = get_agbno_state(mp, i, j); switch (bstate) { diff --git a/repair/phase5.c b/repair/phase5.c index f96b773e8..6c79162d2 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -123,6 +123,19 @@ mk_incore_fstree(xfs_mount_t *mp, xfs_agnumber_t agno) agbno, state); } #endif + /* Process in chunks of 16 (XR_BB_UNIT/XR_BB) */ + if ((in_extent == 0) && ((agbno & XR_BB_MASK) == 0)) { + /* testing >= XR_E_INUSE */ + switch (ba_bmap[agno][agbno>>XR_BB]) { + case XR_E_INUSE_LL: + case XR_E_INUSE_FS_LL: + case XR_E_INO_LL: + case XR_E_FS_MAP_LL: + agbno += (XR_BB_UNIT/XR_BB) - 1; + continue; + } + + } if (get_agbno_state(mp, agno, agbno) < XR_E_INUSE) { free_blocks++; if (in_extent == 0) { @@ -1413,7 +1426,9 @@ phase5(xfs_mount_t *mp) int extra_blocks = 0; uint num_freeblocks; xfs_extlen_t freeblks1; +#ifdef DEBUG xfs_extlen_t freeblks2; +#endif xfs_agblock_t num_extents; extern int count_bno_extents(xfs_agnumber_t); extern int count_bno_extents_blocks(xfs_agnumber_t, uint *); @@ -1564,8 +1579,13 @@ phase5(xfs_mount_t *mp) #endif write_cursor(&bno_btree_curs); +#ifdef DEBUG freeblks2 = build_freespace_tree(mp, agno, &bcnt_btree_curs, XFS_ABTC_MAGIC); +#else + (void) build_freespace_tree(mp, agno, + &bcnt_btree_curs, XFS_ABTC_MAGIC); +#endif write_cursor(&bcnt_btree_curs); ASSERT(freeblks1 == freeblks2); diff --git a/repair/phase6.c b/repair/phase6.c index 6acc148d2..5134282d3 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -1896,7 +1896,7 @@ longform_dir2_entry_check_data( ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen); lastfree = 0; dir_hash_add(hashtab, - libxfs_da_hashname((char *)dep->name, dep->namelen), + libxfs_da_hashname((uchar_t *)dep->name, dep->namelen), addr, dep->name[0] == '/'); /* * skip bogus entries (leading '/'). they'll be deleted -- 2.47.2