Skip to content

Commit

Permalink
xfs: allow scanning ranges of the buffer cache for live buffers
Browse files Browse the repository at this point in the history
After an online repair, we need to invalidate buffers representing the
blocks from the old metadata that we're replacing.  It's possible that
parts of a tree that were previously cached in memory are no longer
accessible due to media failure or other corruption on interior nodes,
so repair figures out the old blocks from the reverse mapping data and
scans the buffer cache directly.

In other words, online fsck needs to find all the live (i.e. non-stale)
buffers for a range of fsblocks so that it can invalidate them.

Unfortunately, the current buffer cache code triggers asserts if the
rhashtable lookup finds a non-stale buffer of a different length than
the key we searched for.  For regular operation this is desirable, but
for this repair procedure, we don't care since we're going to forcibly
stale the buffer anyway.  Add an internal lookup flag to avoid the
assert.  Skip buffers that are already XBF_STALE.

Signed-off-by: Darrick J. Wong <[email protected]>
Reviewed-by: Dave Chinner <[email protected]>
  • Loading branch information
Darrick J. Wong committed Aug 10, 2023
1 parent 77a1396 commit 9ed851f
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 2 deletions.
2 changes: 1 addition & 1 deletion fs/xfs/scrub/reap.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ xrep_block_reap_binval(
*/
error = xfs_buf_incore(sc->mp->m_ddev_targp,
XFS_FSB_TO_DADDR(sc->mp, fsbno),
XFS_FSB_TO_BB(sc->mp, 1), 0, &bp);
XFS_FSB_TO_BB(sc->mp, 1), XBF_LIVESCAN, &bp);
if (error)
return;

Expand Down
9 changes: 8 additions & 1 deletion fs/xfs/xfs_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,8 @@ _xfs_buf_obj_cmp(
* reallocating a busy extent. Skip this buffer and
* continue searching for an exact match.
*/
ASSERT(bp->b_flags & XBF_STALE);
if (!(map->bm_flags & XBM_LIVESCAN))
ASSERT(bp->b_flags & XBF_STALE);
return 1;
}
return 0;
Expand Down Expand Up @@ -559,6 +560,10 @@ xfs_buf_find_lock(
* intact here.
*/
if (bp->b_flags & XBF_STALE) {
if (flags & XBF_LIVESCAN) {
xfs_buf_unlock(bp);
return -ENOENT;
}
ASSERT((bp->b_flags & _XBF_DELWRI_Q) == 0);
bp->b_flags &= _XBF_KMEM | _XBF_PAGES;
bp->b_ops = NULL;
Expand Down Expand Up @@ -682,6 +687,8 @@ xfs_buf_get_map(
int error;
int i;

if (flags & XBF_LIVESCAN)
cmap.bm_flags |= XBM_LIVESCAN;
for (i = 0; i < nmaps; i++)
cmap.bm_len += map[i].bm_len;

Expand Down
13 changes: 13 additions & 0 deletions fs/xfs/xfs_buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ struct xfs_buf;
#define _XBF_DELWRI_Q (1u << 22)/* buffer on a delwri queue */

/* flags used only as arguments to access routines */
/*
* Online fsck is scanning the buffer cache for live buffers. Do not warn
* about length mismatches during lookups and do not return stale buffers.
*/
#define XBF_LIVESCAN (1u << 28)
#define XBF_INCORE (1u << 29)/* lookup only, return if found in cache */
#define XBF_TRYLOCK (1u << 30)/* lock requested, but do not wait */
#define XBF_UNMAPPED (1u << 31)/* do not map the buffer */
Expand All @@ -67,6 +72,7 @@ typedef unsigned int xfs_buf_flags_t;
{ _XBF_KMEM, "KMEM" }, \
{ _XBF_DELWRI_Q, "DELWRI_Q" }, \
/* The following interface flags should never be set */ \
{ XBF_LIVESCAN, "LIVESCAN" }, \
{ XBF_INCORE, "INCORE" }, \
{ XBF_TRYLOCK, "TRYLOCK" }, \
{ XBF_UNMAPPED, "UNMAPPED" }
Expand Down Expand Up @@ -114,8 +120,15 @@ typedef struct xfs_buftarg {
struct xfs_buf_map {
xfs_daddr_t bm_bn; /* block number for I/O */
int bm_len; /* size of I/O */
unsigned int bm_flags;
};

/*
* Online fsck is scanning the buffer cache for live buffers. Do not warn
* about length mismatches during lookups and do not return stale buffers.
*/
#define XBM_LIVESCAN (1U << 0)

#define DEFINE_SINGLE_BUF_MAP(map, blkno, numblk) \
struct xfs_buf_map (map) = { .bm_bn = (blkno), .bm_len = (numblk) };

Expand Down

0 comments on commit 9ed851f

Please sign in to comment.