]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: walk the rt reverse mapping tree when rebuilding rmap
authorDarrick J. Wong <djwong@kernel.org>
Mon, 23 Sep 2024 20:42:13 +0000 (13:42 -0700)
committerChristoph Hellwig <hch@lst.de>
Wed, 9 Oct 2024 13:55:47 +0000 (15:55 +0200)
When we're rebuilding the data device rmap, if we encounter an "rmap"
format fork, we have to walk the (realtime) rmap btree inode to build
the appropriate mappings.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/scrub/rmap_repair.c

index 3ce0f2a442db173898f86fabbfae79f6b49a24a4..887601106de0dbd1a35d2f853a4883d839adb3c6 100644 (file)
@@ -31,6 +31,8 @@
 #include "xfs_refcount.h"
 #include "xfs_refcount_btree.h"
 #include "xfs_ag.h"
+#include "xfs_rtrmap_btree.h"
+#include "xfs_rtgroup.h"
 #include "scrub/xfs_scrub.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
@@ -499,6 +501,37 @@ xrep_rmap_scan_iext(
        return xrep_rmap_stash_accumulated(rf);
 }
 
+static int
+xrep_rmap_scan_rtrmapbt(
+       struct xrep_rmap_ifork  *rf,
+       struct xfs_inode        *ip)
+{
+       struct xfs_scrub        *sc = rf->rr->sc;
+       struct xfs_rtgroup      *rtg = NULL;
+       struct xfs_btree_cur    *cur;
+       int                     error;
+
+       if (rf->whichfork != XFS_DATA_FORK)
+               return -EFSCORRUPTED;
+
+       while ((rtg = xfs_rtgroup_next(sc->mp, rtg))) {
+               if (ip == rtg->rtg_inodes[XFS_RTGI_RMAP]) {
+                       cur = xfs_rtrmapbt_init_cursor(sc->tp, rtg);
+                       error = xrep_rmap_scan_iroot_btree(rf, cur);
+                       xfs_btree_del_cursor(cur, error);
+                       xfs_rtgroup_rele(rtg);
+                       return error;
+               }
+       }
+
+       /*
+        * We shouldn't find an rmap format inode that isn't associated with
+        * an rtgroup!
+        */
+       ASSERT(0);
+       return -EFSCORRUPTED;
+}
+
 /* Find all the extents from a given AG in an inode fork. */
 STATIC int
 xrep_rmap_scan_ifork(
@@ -528,6 +561,8 @@ xrep_rmap_scan_ifork(
                error = xrep_rmap_scan_bmbt(&rf, ip, &mappings_done);
                if (error || mappings_done)
                        return error;
+       } else if (ifp->if_format == XFS_DINODE_FMT_RMAP) {
+               return xrep_rmap_scan_rtrmapbt(&rf, ip);
        } else if (ifp->if_format != XFS_DINODE_FMT_EXTENTS) {
                return 0;
        }