]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: port to the new refcount bag structure
authorDarrick J. Wong <djwong@kernel.org>
Mon, 22 Apr 2024 17:01:19 +0000 (10:01 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 3 Jun 2024 18:37:42 +0000 (11:37 -0700)
Port the refcount record generating code to use the new refcount bag
data structure.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
repair/rmap.c
repair/xfs_repair.c

index 51963327858aa06a7855df87c729c001a6afa22c..7cb3a315a5b3654e22ec342474a09b73b671fed9 100644 (file)
@@ -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(
index f8c37c6322323ac50d0e9874bdbebe234a1ea0ab..cf774964381e940d956ae8e08b0fb1ebb2772185 100644 (file)
@@ -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...