]> 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>
Wed, 29 May 2024 04:12:55 +0000 (21:12 -0700)
committerChristoph Hellwig <hch@lst.de>
Sun, 11 Aug 2024 06:28:33 +0000 (08:28 +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 e8080eba37d29bf5a854e51547d6a2501d21bef6..9797c5a0617c1b69aeb5825cb22b38c9f5c6a8b3 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,38 @@ 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_btree_cur    *cur;
+       struct xfs_rtgroup      *rtg;
+       xfs_rgnumber_t          rgno;
+       int                     error;
+
+       if (rf->whichfork != XFS_DATA_FORK)
+               return -EFSCORRUPTED;
+
+       for_each_rtgroup(sc->mp, rgno, rtg) {
+               if (ip == rtg->rtg_inodes[XFS_RTG_RMAP]) {
+                       cur = xfs_rtrmapbt_init_cursor(sc->mp, sc->tp, rtg, ip);
+                       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 +562,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;
        }