diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-10-01 13:30:50 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-12-15 17:29:25 -0800 |
commit | fff27f913157bbf72ca0e09e508afab2c2272d3e (patch) | |
tree | 172234fe49e01baaf45045c3f3f6295122b60ce3 /fs/xfs/scrub | |
parent | d398ef54ce57dfa6305ece02b40e0a9931d3bfaa (diff) |
xfs: capture realtime CoW staging extents when rebuilding rt rmapbt
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>
Diffstat (limited to 'fs/xfs/scrub')
-rw-r--r-- | fs/xfs/scrub/rtrmap_repair.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/fs/xfs/scrub/rtrmap_repair.c b/fs/xfs/scrub/rtrmap_repair.c index 71e8095c5808..e0f83af104de 100644 --- a/fs/xfs/scrub/rtrmap_repair.c +++ b/fs/xfs/scrub/rtrmap_repair.c @@ -26,6 +26,7 @@ #include "xfs_quota.h" #include "xfs_rtalloc.h" #include "xfs_ag.h" +#include "xfs_refcount.h" #include "scrub/xfs_scrub.h" #include "scrub/scrub.h" #include "scrub/common.h" @@ -420,6 +421,98 @@ xrep_rtrmap_scan_ag( return error; } +struct xrep_rtrmap_stash_run { + struct xrep_rtrmap *rr; + uint64_t owner; +}; + +static int +xrep_rtrmap_stash_run( + uint64_t start, + uint64_t len, + void *priv) +{ + struct xrep_rtrmap_stash_run *rsr = priv; + struct xrep_rtrmap *rr = rsr->rr; + + return xrep_rtrmap_stash(rr, start, 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 xbitmap *bitmap, + const struct xfs_owner_info *oinfo) +{ + struct xrep_rtrmap_stash_run rsr = { + .rr = rr, + .owner = oinfo->oi_owner, + }; + + return xbitmap_walk(bitmap, xrep_rtrmap_stash_run, &rsr); +} + +/* Record a CoW staging extent. */ +STATIC int +xrep_rtrmap_walk_cowblocks( + struct xfs_btree_cur *cur, + const union xfs_btree_rec *rec, + void *priv) +{ + struct xbitmap *bitmap = priv; + struct xfs_refcount_irec refc; + xfs_fsblock_t fsbno; + + xfs_refcount_btrec_to_irec(cur, rec, &refc); + if (refc.rc_refcount != 1) + return -EFSCORRUPTED; + + fsbno = refc.rc_startblock - XFS_RTREFC_COW_START; + return xbitmap_set(bitmap, fsbno, refc.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 xbitmap cow_blocks; /* COWBIT */ + union xfs_btree_irec low; + union xfs_btree_irec high; + struct xfs_scrub *sc = rr->sc; + int error; + + if (!xfs_has_rtreflink(sc->mp)) + return 0; + + xbitmap_init(&cow_blocks); + + /* Collect rmaps for CoW staging extents. */ + memset(&low, 0, sizeof(low)); + low.rc.rc_startblock = XFS_RTREFC_COW_START; + memset(&high, 0xFF, sizeof(high)); + error = xfs_btree_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: + xbitmap_destroy(&cow_blocks); + return error; +} + /* Generate all the reverse-mappings for the realtime device. */ STATIC int xrep_rtrmap_find_rmaps( @@ -431,6 +524,13 @@ xrep_rtrmap_find_rmaps( xfs_agnumber_t agno; int error; + /* Find CoW staging extents. */ + xrep_rt_btcur_init(sc, &sc->sr); + error = xrep_rtrmap_find_refcount_rmaps(rr); + xchk_rt_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: |