]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: walk the rt reference count tree when rebuilding rmap
authorDarrick J. Wong <djwong@kernel.org>
Wed, 29 May 2024 04:13:27 +0000 (21:13 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 16 Jul 2024 22:50:54 +0000 (15:50 -0700)
When we're rebuilding the data device rmap, if we encounter a "refcount"
format fork, we have to walk the (realtime) refcount btree inode to
build the appropriate mappings.

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

index 878ff2e005830a2f55790605520677928ef0ec81..8161277e9b4f5f44c2c991731dfca1e50e3c6d1b 100644 (file)
@@ -33,6 +33,7 @@
 #include "xfs_ag.h"
 #include "xfs_rtrmap_btree.h"
 #include "xfs_rtgroup.h"
+#include "xfs_rtrefcount_btree.h"
 #include "scrub/xfs_scrub.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
@@ -533,6 +534,39 @@ xrep_rmap_scan_rtrmapbt(
        return -EFSCORRUPTED;
 }
 
+static int
+xrep_rmap_scan_rtrefcountbt(
+       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_refcountip) {
+                       cur = xfs_rtrefcountbt_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 a refcount 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(
@@ -564,6 +598,8 @@ xrep_rmap_scan_ifork(
                        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_REFCOUNT) {
+               return xrep_rmap_scan_rtrefcountbt(&rf, ip);
        } else if (ifp->if_format != XFS_DINODE_FMT_EXTENTS) {
                return 0;
        }