]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: capture realtime CoW staging extents when rebuilding rt rmapbt
authorDarrick J. Wong <djwong@kernel.org>
Mon, 23 Sep 2024 20:42:51 +0000 (13:42 -0700)
committerChristoph Hellwig <hch@lst.de>
Wed, 9 Oct 2024 13:55:51 +0000 (15:55 +0200)
Walk the realtime refcount btree to find the CoW staging extents when
we're rebuilding the realtime rmap btree.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/scrub/repair.h
fs/xfs/scrub/rgb_bitmap.h [new file with mode: 0644]
fs/xfs/scrub/rtrmap_repair.c

index ac5962732d269dc808e78cae170c04a5e3c4568b..773438132053751c38bd58b093f24c466da2945f 100644 (file)
@@ -50,6 +50,7 @@ xrep_trans_commit(
 
 struct xbitmap;
 struct xagb_bitmap;
+struct xrgb_bitmap;
 struct xfsb_bitmap;
 
 int xrep_fix_freelist(struct xfs_scrub *sc, int alloc_flags);
diff --git a/fs/xfs/scrub/rgb_bitmap.h b/fs/xfs/scrub/rgb_bitmap.h
new file mode 100644 (file)
index 0000000..47a5caf
--- /dev/null
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020-2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#ifndef __XFS_SCRUB_RGB_BITMAP_H__
+#define __XFS_SCRUB_RGB_BITMAP_H__
+
+/* Bitmaps, but for type-checked for xfs_rgblock_t */
+
+struct xrgb_bitmap {
+       struct xbitmap32        rgbitmap;
+};
+
+static inline void xrgb_bitmap_init(struct xrgb_bitmap *bitmap)
+{
+       xbitmap32_init(&bitmap->rgbitmap);
+}
+
+static inline void xrgb_bitmap_destroy(struct xrgb_bitmap *bitmap)
+{
+       xbitmap32_destroy(&bitmap->rgbitmap);
+}
+
+static inline int xrgb_bitmap_set(struct xrgb_bitmap *bitmap,
+               xfs_rgblock_t start, xfs_extlen_t len)
+{
+       return xbitmap32_set(&bitmap->rgbitmap, start, len);
+}
+
+static inline int xrgb_bitmap_walk(struct xrgb_bitmap *bitmap,
+               xbitmap32_walk_fn fn, void *priv)
+{
+       return xbitmap32_walk(&bitmap->rgbitmap, fn, priv);
+}
+
+#endif /* __XFS_SCRUB_RGB_BITMAP_H__ */
index db194deb0feeed75347127a992aed914cf88d97b..a688e0c24fb5d759ab204c3de3616d55e2e36d87 100644 (file)
@@ -30,6 +30,7 @@
 #include "xfs_rtalloc.h"
 #include "xfs_ag.h"
 #include "xfs_rtgroup.h"
+#include "xfs_refcount.h"
 #include "scrub/xfs_scrub.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
@@ -38,6 +39,7 @@
 #include "scrub/repair.h"
 #include "scrub/bitmap.h"
 #include "scrub/fsb_bitmap.h"
+#include "scrub/rgb_bitmap.h"
 #include "scrub/xfile.h"
 #include "scrub/xfarray.h"
 #include "scrub/iscan.h"
@@ -423,6 +425,100 @@ xrep_rtrmap_scan_ag(
        return error;
 }
 
+struct xrep_rtrmap_stash_run {
+       struct xrep_rtrmap      *rr;
+       uint64_t                owner;
+};
+
+static int
+xrep_rtrmap_stash_run(
+       uint32_t                        start,
+       uint32_t                        len,
+       void                            *priv)
+{
+       struct xrep_rtrmap_stash_run    *rsr = priv;
+       struct xrep_rtrmap              *rr = rsr->rr;
+       xfs_rgblock_t                   rgbno = start;
+
+       return xrep_rtrmap_stash(rr, rgbno, len, rsr->owner, 0, 0);
+}
+
+/*
+ * Emit rmaps for every extent of bits set in the bitmap.  Caller must ensure
+ * that the ranges are in units of FS blocks.
+ */
+STATIC int
+xrep_rtrmap_stash_bitmap(
+       struct xrep_rtrmap              *rr,
+       struct xrgb_bitmap              *bitmap,
+       const struct xfs_owner_info     *oinfo)
+{
+       struct xrep_rtrmap_stash_run    rsr = {
+               .rr                     = rr,
+               .owner                  = oinfo->oi_owner,
+       };
+
+       return xrgb_bitmap_walk(bitmap, xrep_rtrmap_stash_run, &rsr);
+}
+
+/* Record a CoW staging extent. */
+STATIC int
+xrep_rtrmap_walk_cowblocks(
+       struct xfs_btree_cur            *cur,
+       const struct xfs_refcount_irec  *irec,
+       void                            *priv)
+{
+       struct xrgb_bitmap              *bitmap = priv;
+
+       if (!xfs_refcount_check_domain(irec) ||
+           irec->rc_domain != XFS_REFC_DOMAIN_COW)
+               return -EFSCORRUPTED;
+
+       return xrgb_bitmap_set(bitmap, irec->rc_startblock,
+                       irec->rc_blockcount);
+}
+
+/*
+ * Collect rmaps for the blocks containing the refcount btree, and all CoW
+ * staging extents.
+ */
+STATIC int
+xrep_rtrmap_find_refcount_rmaps(
+       struct xrep_rtrmap      *rr)
+{
+       struct xrgb_bitmap      cow_blocks;             /* COWBIT */
+       struct xfs_refcount_irec low = {
+               .rc_startblock  = 0,
+               .rc_domain      = XFS_REFC_DOMAIN_COW,
+       };
+       struct xfs_refcount_irec high = {
+               .rc_startblock  = -1U,
+               .rc_domain      = XFS_REFC_DOMAIN_COW,
+       };
+       struct xfs_scrub        *sc = rr->sc;
+       int                     error;
+
+       if (!xfs_has_rtreflink(sc->mp))
+               return 0;
+
+       xrgb_bitmap_init(&cow_blocks);
+
+       /* Collect rmaps for CoW staging extents. */
+       error = xfs_refcount_query_range(sc->sr.refc_cur, &low, &high,
+                       xrep_rtrmap_walk_cowblocks, &cow_blocks);
+       if (error)
+               goto out_bitmap;
+
+       /* Generate rmaps for everything. */
+       error = xrep_rtrmap_stash_bitmap(rr, &cow_blocks, &XFS_RMAP_OINFO_COW);
+       if (error)
+               goto out_bitmap;
+
+out_bitmap:
+       xrgb_bitmap_destroy(&cow_blocks);
+       return error;
+}
+
 /* Count and check all collected records. */
 STATIC int
 xrep_rtrmap_check_record(
@@ -460,6 +556,13 @@ xrep_rtrmap_find_rmaps(
                        return error;
        }
 
+       /* Find CoW staging extents. */
+       xrep_rtgroup_btcur_init(sc, &sc->sr);
+       error = xrep_rtrmap_find_refcount_rmaps(rr);
+       xchk_rtgroup_btcur_free(&sc->sr);
+       if (error)
+               return error;
+
        /*
         * Set up for a potentially lengthy filesystem scan by reducing our
         * transaction resource usage for the duration.  Specifically: