From: Darrick J. Wong <djwong@xxxxxxxxxx> Port the refcount record generating code to use the new refcount bag data structure. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> --- repair/rmap.c | 150 +++++++++++++++------------------------------------ repair/xfs_repair.c | 6 ++ 2 files changed, 51 insertions(+), 105 deletions(-) diff --git a/repair/rmap.c b/repair/rmap.c index 519633278..7cb3a315a 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -14,6 +14,7 @@ #include "rmap.h" #include "libfrog/bitmap.h" #include "libfrog/platform.h" +#include "rcbag.h" #undef RMAP_DEBUG @@ -749,35 +750,32 @@ rmap_dump( * reflink inode flag, if the stack depth is greater than 1. */ static void -mark_inode_rl( +mark_reflink_inodes( struct xfs_mount *mp, - struct xfs_bag *rmaps) + struct rcbag *rcstack) { - struct rmap_for_refcount *rfr; + struct rcbag_iter rciter; struct ino_tree_node *irec; - int off; - uint64_t idx; - if (bag_count(rmaps) < 2) - return; - - /* Reflink flag accounting */ - foreach_bag_ptr(rmaps, idx, rfr) { + rcbag_ino_iter_start(rcstack, &rciter); + while (rcbag_ino_iter(rcstack, &rciter) == 1) { xfs_agnumber_t agno; xfs_agino_t agino; + int off; - ASSERT(!XFS_RMAP_NON_INODE_OWNER(rfr->rm_owner)); + ASSERT(!XFS_RMAP_NON_INODE_OWNER(rciter.ino)); - agno = XFS_INO_TO_AGNO(mp, rfr->rm_owner); - agino = XFS_INO_TO_AGINO(mp, rfr->rm_owner); + agno = XFS_INO_TO_AGNO(mp, rciter.ino); + agino = XFS_INO_TO_AGINO(mp, rciter.ino); pthread_mutex_lock(&ag_locks[agno].lock); irec = find_inode_rec(mp, agno, agino); - off = get_inode_offset(mp, rfr->rm_owner, irec); + off = get_inode_offset(mp, rciter.ino, irec); /* lock here because we might go outside this ag */ set_inode_is_rl(irec, off); pthread_mutex_unlock(&ag_locks[agno].lock); } + rcbag_ino_iter_stop(rcstack, &rciter); } /* @@ -812,8 +810,6 @@ refcount_emit( _("Insufficient memory while recreating refcount tree.")); } -#define RMAP_NEXT(r) ((r)->rm_startblock + (r)->rm_blockcount) - /* Decide if an rmap could describe a shared extent. */ static inline bool rmap_shareable( @@ -873,40 +869,6 @@ refcount_walk_rmaps( return 0; } -/* - * Find the next block where the refcount changes, given the next rmap we - * looked at and the ones we're already tracking. - */ -static inline int -next_refcount_edge( - struct xfs_bag *stack_top, - struct xfs_rmap_irec *next_rmap, - bool next_valid, - xfs_agblock_t *nbnop) -{ - struct rmap_for_refcount *rfr; - uint64_t idx; - xfs_agblock_t nbno = NULLAGBLOCK; - - if (next_valid) - nbno = next_rmap->rm_startblock; - - foreach_bag_ptr(stack_top, idx, rfr) - nbno = min(nbno, RMAP_NEXT(rfr)); - - /* - * We should have found /something/ because either next_rrm is the next - * interesting rmap to look at after emitting this refcount extent, or - * there are other rmaps in rmap_bag contributing to the current - * sharing count. But if something is seriously wrong, bail out. - */ - if (nbno == NULLAGBLOCK) - return EFSCORRUPTED; - - *nbnop = nbno; - return 0; -} - /* * Walk forward through the rmap btree to collect all rmaps starting at * @bno in @rmap_bag. These represent the file(s) that share ownership of @@ -916,28 +878,19 @@ next_refcount_edge( static int refcount_push_rmaps_at( struct xfs_btree_cur *rmcur, - xfs_agnumber_t agno, - struct xfs_bag *stack_top, + struct rcbag *stack, xfs_agblock_t bno, - struct xfs_rmap_irec *irec, + struct xfs_rmap_irec *rmap, bool *have, const char *tag) { int have_gt; int error; - while (*have && irec->rm_startblock == bno) { - struct rmap_for_refcount rfr = { - .rm_startblock = irec->rm_startblock, - .rm_blockcount = irec->rm_blockcount, - .rm_owner = irec->rm_owner, - }; + while (*have && rmap->rm_startblock == bno) { + rcbag_add(stack, rmap); - rmap_dump(tag, agno, &rfr); - error = bag_add(stack_top, &rfr); - if (error) - return error; - error = refcount_walk_rmaps(rmcur, irec, have); + error = refcount_walk_rmaps(rmcur, rmap, have); if (error) return error; } @@ -961,11 +914,10 @@ compute_refcounts( xfs_agnumber_t agno) { struct xfs_btree_cur *rmcur; - struct xfs_rmap_irec irec; - struct xfs_bag *stack_top = NULL; - struct rmap_for_refcount *rfr; - uint64_t idx; - uint64_t old_stack_nr; + struct rcbag *rcstack; + struct xfs_rmap_irec rmap; + uint64_t nr_rmaps; + uint64_t old_stack_height; xfs_agblock_t sbno; /* first bno of this rmap set */ xfs_agblock_t cbno; /* first bno of this refcount set */ xfs_agblock_t nbno; /* next bno where rmap set changes */ @@ -977,11 +929,13 @@ compute_refcounts( if (!rmaps_has_observations(&ag_rmaps[agno])) return 0; + nr_rmaps = rmap_record_count(mp, agno); + error = rmap_init_mem_cursor(mp, NULL, agno, &rmcur); if (error) return error; - error = init_bag(&stack_top, sizeof(struct rmap_for_refcount)); + error = rcbag_init(mp, nr_rmaps, &rcstack); if (error) goto out_cur; @@ -994,86 +948,72 @@ compute_refcounts( /* Process reverse mappings into refcount data. */ while (libxfs_btree_has_more_records(rmcur)) { /* Push all rmaps with pblk == sbno onto the stack */ - error = refcount_walk_rmaps(rmcur, &irec, &have); + error = refcount_walk_rmaps(rmcur, &rmap, &have); if (error) goto out_bag; if (!have) break; - sbno = cbno = irec.rm_startblock; - error = refcount_push_rmaps_at(rmcur, agno, stack_top, sbno, - &irec, &have, "push0"); + sbno = cbno = rmap.rm_startblock; + error = refcount_push_rmaps_at(rmcur, rcstack, sbno, &rmap, + &have, "push0"); if (error) goto out_bag; - mark_inode_rl(mp, stack_top); + mark_reflink_inodes(mp, rcstack); /* Set nbno to the bno of the next refcount change */ - error = next_refcount_edge(stack_top, &irec, have, &nbno); - if (error) - goto out_bag; + rcbag_next_edge(rcstack, &rmap, have, &nbno); /* Emit reverse mappings, if needed */ ASSERT(nbno > sbno); - old_stack_nr = bag_count(stack_top); + old_stack_height = rcbag_count(rcstack); /* While stack isn't empty... */ - while (bag_count(stack_top)) { + while (rcbag_count(rcstack) > 0) { /* Pop all rmaps that end at nbno */ - foreach_bag_ptr_reverse(stack_top, idx, rfr) { - if (RMAP_NEXT(rfr) != nbno) - continue; - rmap_dump("pop", agno, rfr); - error = bag_remove(stack_top, idx); - if (error) - goto out_bag; - } + rcbag_remove_ending_at(rcstack, nbno); /* Push array items that start at nbno */ - error = refcount_walk_rmaps(rmcur, &irec, &have); + error = refcount_walk_rmaps(rmcur, &rmap, &have); if (error) goto out_bag; if (have) { - error = refcount_push_rmaps_at(rmcur, agno, - stack_top, nbno, &irec, &have, - "push1"); + error = refcount_push_rmaps_at(rmcur, rcstack, + nbno, &rmap, &have, "push1"); if (error) goto out_bag; } - mark_inode_rl(mp, stack_top); + mark_reflink_inodes(mp, rcstack); /* Emit refcount if necessary */ ASSERT(nbno > cbno); - if (bag_count(stack_top) != old_stack_nr) { - if (old_stack_nr > 1) { + if (rcbag_count(rcstack) != old_stack_height) { + if (old_stack_height > 1) { refcount_emit(mp, agno, cbno, - nbno - cbno, - old_stack_nr); + nbno - cbno, + old_stack_height); } cbno = nbno; } /* Stack empty, go find the next rmap */ - if (bag_count(stack_top) == 0) + if (rcbag_count(rcstack) == 0) break; - old_stack_nr = bag_count(stack_top); + old_stack_height = rcbag_count(rcstack); sbno = nbno; /* Set nbno to the bno of the next refcount change */ - error = next_refcount_edge(stack_top, &irec, have, - &nbno); - if (error) - goto out_bag; + rcbag_next_edge(rcstack, &rmap, have, &nbno); /* Emit reverse mappings, if needed */ ASSERT(nbno > sbno); } } out_bag: - free_bag(&stack_top); + rcbag_free(&rcstack); out_cur: libxfs_btree_del_cursor(rmcur, error); return error; } -#undef RMAP_NEXT static int count_btree_records( diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index f8c37c632..cf7749643 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -26,6 +26,7 @@ #include "libfrog/platform.h" #include "bulkload.h" #include "quotacheck.h" +#include "rcbag_btree.h" /* * option tables for getsubopt calls @@ -1297,6 +1298,10 @@ main(int argc, char **argv) phase3(mp, phase2_threads); phase_end(mp, 3); + error = rcbagbt_init_cur_cache(); + if (error) + do_error(_("could not allocate btree cursor memory\n")); + phase4(mp); phase_end(mp, 4); @@ -1309,6 +1314,7 @@ main(int argc, char **argv) phase5(mp); } phase_end(mp, 5); + rcbagbt_destroy_cur_cache(); /* * Done with the block usage maps, toss them...