[PATCH 2/4] xfs_repair: check low keys of rmap btrees

Darrick J. Wong
2022-12-30T22:53:43Z

For whatever reason, we only check the high keys in an rmapbt node
block. We should be checking the low keys and the high keys, so fix
this gap.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
repair/scan.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/repair/scan.c b/repair/scan.c
index 7b72013153d..d66ce60cbb3 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -992,6 +992,7 @@ scan_rmapbt(
uint64_t lastowner = 0;
uint64_t lastoffset = 0;
struct xfs_rmap_key *kp;
+ struct xfs_rmap_irec oldkey;
struct xfs_rmap_irec key = {0};
struct xfs_perag *pag;

@@ -1211,7 +1212,7 @@ _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
}

/* check the node's high keys */
- for (i = 0; !isroot && i < numrecs; i++) {
+ for (i = 0; i < numrecs; i++) {
kp = XFS_RMAP_HIGH_KEY_ADDR(block, i + 1);

key.rm_flags = 0;
@@ -1231,6 +1232,35 @@ _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
i, agno, bno, name);
}

+ /* check for in-order keys */
+ for (i = 0; i < numrecs; i++) {
+ kp = XFS_RMAP_KEY_ADDR(block, i + 1);
+
+ key.rm_flags = 0;
+ key.rm_startblock = be32_to_cpu(kp->rm_startblock);
+ key.rm_owner = be64_to_cpu(kp->rm_owner);
+ if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset),
+ &key)) {
+ /* Look for impossible flags. */
+ do_warn(
+_("invalid flags in key %u of %s btree block %u/%u\n"),
+ i, name, agno, bno);
+ suspect++;
+ continue;
+ }
+ if (i == 0) {
+ oldkey = key;
+ continue;
+ }
+ if (rmap_diffkeys(&oldkey, &key) > 0) {
+ do_warn(
+_("out of order key %u in %s btree block (%u/%u)\n"),
+ i, name, agno, bno);
+ suspect++;
+ }
+ oldkey = key;
+ }
+
pag = libxfs_perag_get(mp, agno);
for (i = 0; i < numrecs; i++) {
xfs_agblock_t agbno = be32_to_cpu(pp[i]);