mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 11:06:41 -05:00
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> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
@@ -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);
|
||||
|
||||
37
fs/xfs/scrub/rgb_bitmap.h
Normal file
37
fs/xfs/scrub/rgb_bitmap.h
Normal file
@@ -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__ */
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user