]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: walk the rt reverse mapping tree when rebuilding rmap
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:20:38 +0000 (16:20 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 23 Dec 2024 21:06:08 +0000 (13:06 -0800)
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>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/scrub/rmap_repair.c

index 2a0b9e3d0fbaeeb7016e33776543223791192a3b..91c17feb49768bb5ad221e9e93eee1a6043dbfbf 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"
@@ -504,7 +506,56 @@ xrep_rmap_scan_meta_btree(
        struct xrep_rmap_ifork  *rf,
        struct xfs_inode        *ip)
 {
-       return -EFSCORRUPTED; /* XXX placeholder */
+       struct xfs_scrub        *sc = rf->rr->sc;
+       struct xfs_rtgroup      *rtg = NULL;
+       struct xfs_btree_cur    *cur = NULL;
+       enum xfs_rtg_inodes     type;
+       int                     error;
+
+       if (rf->whichfork != XFS_DATA_FORK)
+               return -EFSCORRUPTED;
+
+       switch (ip->i_metatype) {
+       case XFS_METAFILE_RTRMAP:
+               type = XFS_RTGI_RMAP;
+               break;
+       default:
+               ASSERT(0);
+               return -EFSCORRUPTED;
+       }
+
+       while ((rtg = xfs_rtgroup_next(sc->mp, rtg))) {
+               if (ip == rtg->rtg_inodes[type])
+                       goto found;
+       }
+
+       /*
+        * We should never find an rt metadata btree inode that isn't
+        * associated with an rtgroup yet has ondisk blocks allocated to it.
+        */
+       if (ip->i_nblocks) {
+               ASSERT(0);
+               return -EFSCORRUPTED;
+       }
+
+       return 0;
+
+found:
+       switch (ip->i_metatype) {
+       case XFS_METAFILE_RTRMAP:
+               cur = xfs_rtrmapbt_init_cursor(sc->tp, rtg);
+               break;
+       default:
+               ASSERT(0);
+               error = -EFSCORRUPTED;
+               goto out_rtg;
+       }
+
+       error = xrep_rmap_scan_iroot_btree(rf, cur);
+       xfs_btree_del_cursor(cur, error);
+out_rtg:
+       xfs_rtgroup_rele(rtg);
+       return error;
 }
 
 /* Find all the extents from a given AG in an inode fork. */