]> git.apps.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_repair: reduce rmap bag memory usage when creating refcounts
authorDarrick J. Wong <djwong@kernel.org>
Mon, 22 Apr 2024 17:01:18 +0000 (10:01 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 3 Jun 2024 18:37:42 +0000 (11:37 -0700)
The algorithm that computes reference count records uses a "bag"
structure to remember the rmap records corresponding to the current
block.  In the previous patch we converted the bag structure to store
actual rmap records instead of pointers to rmap records owned by another
structure as part of preparing for converting this algorithm to use
in-memory rmap btrees.

However, the memory usage of the bag structure is now excessive -- we
only need the physical extent and inode owner information to generate
refcount records and mark inodes that require the reflink flag.  IOWs,
the flags and offset fields are unnecessary.  Create a custom structure
for the bag, which halves its memory usage.

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

index f58773cb335d3fd69bf58d9f19f9f9c930fb2060..f34e423005893b7ba6916548fcbb2116d51d7ee2 100644 (file)
@@ -46,6 +46,13 @@ struct xfs_ag_rmap {
        struct xfs_slab         *ar_refcount_items;
 };
 
+/* Only the parts of struct xfs_rmap_irec that we need to compute refcounts. */
+struct rmap_for_refcount {
+       xfs_agblock_t   rm_startblock;
+       xfs_extlen_t    rm_blockcount;
+       uint64_t        rm_owner;
+};
+
 static struct xfs_ag_rmap *ag_rmaps;
 bool rmapbt_suspect;
 static bool refcbt_suspect;
@@ -777,16 +784,14 @@ static void
 rmap_dump(
        const char              *msg,
        xfs_agnumber_t          agno,
-       struct xfs_rmap_irec    *rmap)
+       const struct rmap_for_refcount *rfr)
 {
-       printf("%s: %p agno=%u pblk=%llu own=%lld lblk=%llu len=%u flags=0x%x\n",
-               msg, rmap,
+       printf("%s: %p agno=%u agbno=%llu owner=%lld fsbcount=%u\n",
+               msg, rfr,
                (unsigned int)agno,
-               (unsigned long long)rmap->rm_startblock,
-               (unsigned long long)rmap->rm_owner,
-               (unsigned long long)rmap->rm_offset,
-               (unsigned int)rmap->rm_blockcount,
-               (unsigned int)rmap->rm_flags);
+               (unsigned long long)rfr->rm_startblock,
+               (unsigned long long)rfr->rm_owner,
+               (unsigned int)rfr->rm_blockcount);
 }
 #else
 # define rmap_dump(m, a, r)
@@ -865,30 +870,33 @@ rmap_dump(
  */
 static void
 mark_inode_rl(
-       struct xfs_mount                *mp,
+       struct xfs_mount        *mp,
        struct xfs_bag          *rmaps)
 {
-       xfs_agnumber_t          iagno;
-       struct xfs_rmap_irec    *rmap;
+       struct rmap_for_refcount *rfr;
        struct ino_tree_node    *irec;
        int                     off;
        uint64_t                idx;
-       xfs_agino_t             ino;
 
        if (bag_count(rmaps) < 2)
                return;
 
        /* Reflink flag accounting */
-       foreach_bag_ptr(rmaps, idx, rmap) {
-               ASSERT(!XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner));
-               iagno = XFS_INO_TO_AGNO(mp, rmap->rm_owner);
-               ino = XFS_INO_TO_AGINO(mp, rmap->rm_owner);
-               pthread_mutex_lock(&ag_locks[iagno].lock);
-               irec = find_inode_rec(mp, iagno, ino);
-               off = get_inode_offset(mp, rmap->rm_owner, irec);
+       foreach_bag_ptr(rmaps, idx, rfr) {
+               xfs_agnumber_t  agno;
+               xfs_agino_t     agino;
+
+               ASSERT(!XFS_RMAP_NON_INODE_OWNER(rfr->rm_owner));
+
+               agno = XFS_INO_TO_AGNO(mp, rfr->rm_owner);
+               agino = XFS_INO_TO_AGINO(mp, rfr->rm_owner);
+
+               pthread_mutex_lock(&ag_locks[agno].lock);
+               irec = find_inode_rec(mp, agno, agino);
+               off = get_inode_offset(mp, rfr->rm_owner, irec);
                /* lock here because we might go outside this ag */
                set_inode_is_rl(irec, off);
-               pthread_mutex_unlock(&ag_locks[iagno].lock);
+               pthread_mutex_unlock(&ag_locks[agno].lock);
        }
 }
 
@@ -996,15 +1004,15 @@ next_refcount_edge(
        bool                    next_valid,
        xfs_agblock_t           *nbnop)
 {
-       struct xfs_rmap_irec    *rmap;
+       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, rmap)
-               nbno = min(nbno, RMAP_NEXT(rmap));
+       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
@@ -1039,8 +1047,14 @@ refcount_push_rmaps_at(
        int                     error;
 
        while (*have && irec->rm_startblock == bno) {
-               rmap_dump(tag, agno, irec);
-               error = bag_add(stack_top, irec);
+               struct rmap_for_refcount        rfr = {
+                       .rm_startblock          = irec->rm_startblock,
+                       .rm_blockcount          = irec->rm_blockcount,
+                       .rm_owner               = irec->rm_owner,
+               };
+
+               rmap_dump(tag, agno, &rfr);
+               error = bag_add(stack_top, &rfr);
                if (error)
                        return error;
                error = refcount_walk_rmaps(rmcur, irec, have);
@@ -1069,7 +1083,7 @@ compute_refcounts(
        struct xfs_btree_cur    *rmcur;
        struct xfs_rmap_irec    irec;
        struct xfs_bag          *stack_top = NULL;
-       struct xfs_rmap_irec    *rmap;
+       struct rmap_for_refcount *rfr;
        uint64_t                idx;
        uint64_t                old_stack_nr;
        xfs_agblock_t           sbno;   /* first bno of this rmap set */
@@ -1085,7 +1099,7 @@ compute_refcounts(
        if (error)
                return error;
 
-       error = init_bag(&stack_top, sizeof(struct xfs_rmap_irec));
+       error = init_bag(&stack_top, sizeof(struct rmap_for_refcount));
        if (error)
                goto out_cur;
 
@@ -1122,10 +1136,10 @@ compute_refcounts(
                /* While stack isn't empty... */
                while (bag_count(stack_top)) {
                        /* Pop all rmaps that end at nbno */
-                       foreach_bag_ptr_reverse(stack_top, idx, rmap) {
-                               if (RMAP_NEXT(rmap) != nbno)
+                       foreach_bag_ptr_reverse(stack_top, idx, rfr) {
+                               if (RMAP_NEXT(rfr) != nbno)
                                        continue;
-                               rmap_dump("pop", agno, rmap);
+                               rmap_dump("pop", agno, rfr);
                                error = bag_remove(stack_top, idx);
                                if (error)
                                        goto out_bag;