[PATCH 14/27] xfs_repair: flag suspect long-format btree blocks

Darrick J. Wong
2025-02-06T22:53:23Z

Pass a "suspect" counter through scan_lbtree just like we do for
short-format btree blocks, and increment its value when we encounter
blocks with bad CRCs or outright corruption. This makes it so that
repair actually catches bmbt blocks with bad crcs or other verifier
errors.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
repair/dinode.c | 2 +-
repair/scan.c | 15 ++++++++++++---
repair/scan.h | 3 +++
3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/repair/dinode.c b/repair/dinode.c
index 9ab193bc5fe973..4eafb2324909e1 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -923,7 +923,7 @@ _("bad bmap btree ptr 0x%" PRIx64 " in ino %" PRIu64 "\n"),

if (scan_lbtree(get_unaligned_be64(&pp[i]), level, scan_bmapbt,
type, whichfork, lino, tot, nex, blkmapp,
- &cursor, 1, check_dups, magic,
+ &cursor, 0, 1, check_dups, magic,
(void *)zap_metadata, &xfs_bmbt_buf_ops))
return(1);
/*
diff --git a/repair/scan.c b/repair/scan.c
index 88fbda6b83f61a..cd44a9b14f3a1c 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -136,6 +136,7 @@ scan_lbtree(
xfs_extnum_t *nex,
blkmap_t **blkmapp,
bmap_cursor_t *bm_cursor,
+ int suspect,
int isroot,
int check_dups,
int *dirty,
@@ -148,6 +149,7 @@ scan_lbtree(
xfs_extnum_t *nex,
blkmap_t **blkmapp,
bmap_cursor_t *bm_cursor,
+ int suspect,
int isroot,
int check_dups,
uint64_t magic,
@@ -167,6 +169,12 @@ scan_lbtree(
XFS_FSB_TO_AGBNO(mp, root));
return(1);
}
+ if (bp->b_error == -EFSBADCRC || bp->b_error == -EFSCORRUPTED) {
+ do_warn(_("btree block %d/%d is suspect, error %d\n"),
+ XFS_FSB_TO_AGNO(mp, root),
+ XFS_FSB_TO_AGBNO(mp, root), bp->b_error);
+ suspect++;
+ }

/*
* only check for bad CRC here - caller will determine if there
@@ -182,7 +190,7 @@ scan_lbtree(

err = (*func)(XFS_BUF_TO_BLOCK(bp), nlevels - 1,
type, whichfork, root, ino, tot, nex, blkmapp,
- bm_cursor, isroot, check_dups, &dirty,
+ bm_cursor, suspect, isroot, check_dups, &dirty,
magic, priv);

ASSERT(dirty == 0 || (dirty && !no_modify));
@@ -209,6 +217,7 @@ scan_bmapbt(
xfs_extnum_t *nex,
blkmap_t **blkmapp,
bmap_cursor_t *bm_cursor,
+ int suspect,
int isroot,
int check_dups,
int *dirty,
@@ -505,7 +514,7 @@ _("bad bmap btree ptr 0x%llx in ino %" PRIu64 "\n"),

err = scan_lbtree(be64_to_cpu(pp[i]), level, scan_bmapbt,
type, whichfork, ino, tot, nex, blkmapp,
- bm_cursor, 0, check_dups, magic, priv,
+ bm_cursor, suspect, 0, check_dups, magic, priv,
&xfs_bmbt_buf_ops);
if (err)
return(1);
@@ -573,7 +582,7 @@ _("bad fwd (right) sibling pointer (saw %" PRIu64 " should be NULLFSBLOCK)\n"
be64_to_cpu(pkey[numrecs - 1].br_startoff);
}

- return(0);
+ return suspect > 0 ? 1 : 0;
}

static void
diff --git a/repair/scan.h b/repair/scan.h
index 4da788becbef66..aeaf9f1a7f4ba9 100644
--- a/repair/scan.h
+++ b/repair/scan.h
@@ -23,6 +23,7 @@ int scan_lbtree(
xfs_extnum_t *nex,
struct blkmap **blkmapp,
bmap_cursor_t *bm_cursor,
+ int suspect,
int isroot,
int check_dups,
int *dirty,
@@ -35,6 +36,7 @@ int scan_lbtree(
xfs_extnum_t *nex,
struct blkmap **blkmapp,
bmap_cursor_t *bm_cursor,
+ int suspect,
int isroot,
int check_dups,
uint64_t magic,
@@ -52,6 +54,7 @@ int scan_bmapbt(
xfs_extnum_t *nex,
struct blkmap **blkmapp,
bmap_cursor_t *bm_cursor,
+ int suspect,
int isroot,
int check_dups,
int *dirty,