All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Chinner <dgc@kernel.org>
To: linux-xfs@vger.kernel.org
Cc: cem@kernel.org
Subject: [PATCH 40/48] xfs: allow a long format btree root to be checked without a cursor
Date: Tue, 13 Oct 2026 17:01:30 +1100	[thread overview]
Message-ID: <20261013060204.3138690-41-dgc@kernel.org> (raw)
In-Reply-To: <20261013060204.3138690-1-dgc@kernel.org>

The long format btree block header check derives the block magic and the
maximum record count from a btree cursor. An inode rooted btree logged to the
journal has no cursor available during recovery, so this check cannot be used to
validate a logged btree root.

Rework the header check to take the magic and maximum records as arguments
rather than reading them from a cursor. The cursor based callers derive both
from the cursor and pass them in, so their behaviour is unchanged.

Add xfs_btree_check_fsblock_root_hdr() for callers that hold a long format btree
root but no cursor. It checks the root against the supplied magic, maximum
records and level range, and confirms the root has no siblings.

Assisted-by: LLM
Signed-off-by: Dave Chinner <dgc@kernel.org>
---
 fs/xfs/libxfs/xfs_btree.c | 50 ++++++++++++++++++++++++++++++---------
 fs/xfs/libxfs/xfs_btree.h |  4 ++++
 2 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 7effebe297ea..8e56c948ae6d 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -123,13 +123,13 @@ xfs_btree_check_agblock_siblings(
 
 static xfs_failaddr_t
 __xfs_btree_check_lblock_hdr(
-	struct xfs_btree_cur	*cur,
+	struct xfs_mount	*mp,
+	uint32_t		magic,
+	unsigned int		maxrecs,
 	struct xfs_btree_block	*block,
 	int			level,
 	struct xfs_buf		*bp)
 {
-	struct xfs_mount	*mp = cur->bc_mp;
-
 	if (xfs_has_crc(mp)) {
 		if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid))
 			return __this_address;
@@ -140,12 +140,11 @@ __xfs_btree_check_lblock_hdr(
 			return __this_address;
 	}
 
-	if (be32_to_cpu(block->bb_magic) != xfs_btree_magic(mp, cur->bc_ops))
+	if (be32_to_cpu(block->bb_magic) != magic)
 		return __this_address;
 	if (be16_to_cpu(block->bb_level) != level)
 		return __this_address;
-	if (be16_to_cpu(block->bb_numrecs) >
-	    cur->bc_ops->get_maxrecs(cur, level))
+	if (be16_to_cpu(block->bb_numrecs) > maxrecs)
 		return __this_address;
 
 	return NULL;
@@ -157,16 +156,17 @@ __xfs_btree_check_lblock_hdr(
  */
 static xfs_failaddr_t
 __xfs_btree_check_fsblock(
-	struct xfs_btree_cur	*cur,
+	struct xfs_mount	*mp,
+	uint32_t		magic,
+	unsigned int		maxrecs,
 	struct xfs_btree_block	*block,
 	int			level,
 	struct xfs_buf		*bp)
 {
-	struct xfs_mount	*mp = cur->bc_mp;
 	xfs_failaddr_t		fa;
 	xfs_fsblock_t		fsb;
 
-	fa = __xfs_btree_check_lblock_hdr(cur, block, level, bp);
+	fa = __xfs_btree_check_lblock_hdr(mp, magic, maxrecs, block, level, bp);
 	if (fa)
 		return fa;
 
@@ -191,6 +191,29 @@ __xfs_btree_check_fsblock(
 	return fa;
 }
 
+/*
+ * Check the header of a long format btree root that sits in an inode fork,
+ * without needing a btree cursor. The block is a root, so it has no siblings.
+ * The caller supplies the block magic, the maximum records for the block, and
+ * the valid level range for the btree.
+ */
+xfs_failaddr_t
+xfs_btree_check_fsblock_root_hdr(
+	struct xfs_mount	*mp,
+	uint32_t		magic,
+	unsigned int		maxrecs,
+	struct xfs_btree_block	*block,
+	unsigned int		minlevel,
+	unsigned int		maxlevel)
+{
+	unsigned int		level = be16_to_cpu(block->bb_level);
+
+	if (level < minlevel || level > maxlevel)
+		return __this_address;
+
+	return __xfs_btree_check_fsblock(mp, magic, maxrecs, block, level, NULL);
+}
+
 /*
  * Check an in-memory btree block header.  Return the address of the failing
  * check, or NULL if everything is ok.
@@ -202,11 +225,13 @@ __xfs_btree_check_memblock(
 	int			level,
 	struct xfs_buf		*bp)
 {
+	struct xfs_mount	*mp = cur->bc_mp;
 	struct xfs_buftarg	*btp = cur->bc_mem.xfbtree->target;
 	xfs_failaddr_t		fa;
 	xfbno_t			bno;
 
-	fa = __xfs_btree_check_lblock_hdr(cur, block, level, bp);
+	fa = __xfs_btree_check_lblock_hdr(mp, xfs_btree_magic(mp, cur->bc_ops),
+			cur->bc_ops->get_maxrecs(cur, level), block, level, bp);
 	if (fa)
 		return fa;
 
@@ -277,7 +302,10 @@ __xfs_btree_check_block(
 	case XFS_BTREE_TYPE_AG:
 		return __xfs_btree_check_agblock(cur, block, level, bp);
 	case XFS_BTREE_TYPE_INODE:
-		return __xfs_btree_check_fsblock(cur, block, level, bp);
+		return __xfs_btree_check_fsblock(cur->bc_mp,
+				xfs_btree_magic(cur->bc_mp, cur->bc_ops),
+				cur->bc_ops->get_maxrecs(cur, level),
+				block, level, bp);
 	default:
 		ASSERT(0);
 		return __this_address;
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index 60e78572e725..c9ae26454372 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -345,6 +345,10 @@ xfs_btree_cur_sizeof(unsigned int nlevels)
 
 xfs_failaddr_t __xfs_btree_check_block(struct xfs_btree_cur *cur,
 		struct xfs_btree_block *block, int level, struct xfs_buf *bp);
+xfs_failaddr_t xfs_btree_check_fsblock_root_hdr(struct xfs_mount *mp,
+		uint32_t magic, unsigned int maxrecs,
+		struct xfs_btree_block *block, unsigned int minlevel,
+		unsigned int maxlevel);
 int __xfs_btree_check_ptr(struct xfs_btree_cur *cur,
 		const union xfs_btree_ptr *ptr, int index, int level);
 
-- 
2.55.0


  parent reply	other threads:[~2026-10-13  6:02 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-13  6:00 [RFC] [PATCH 00/48] Validate journal log items during log recovery Dave Chinner
2026-10-13  6:00 ` [PATCH 01/48] xfs: set the unmount record operation header length Dave Chinner
2026-10-13  6:00 ` [PATCH 02/48] xfs: add log recovery item validation design document Dave Chinner
2026-10-13  6:00 ` [PATCH 03/48] xfs: lift transaction header parsing out of the region assembly Dave Chinner
2026-10-13  6:00 ` [PATCH 04/48] xfs: track transaction header decode state explicitly Dave Chinner
2026-10-13  6:00 ` [PATCH 05/48] xfs: track the log item being rebuilt with an explicit pointer Dave Chinner
2026-10-13  6:00 ` [PATCH 06/48] xfs: complete log items explicitly during recovery Dave Chinner
2026-10-13  6:00 ` [PATCH 07/48] xfs: add log item validation infrastructure to log recovery Dave Chinner
2026-10-13  6:00 ` [PATCH 08/48] xfs: recover the transaction header as a validated item type Dave Chinner
2026-10-13  6:00 ` [PATCH 09/48] xfs: factor out xlog_recover_validate_ophdr() Dave Chinner
2026-10-13  6:01 ` [PATCH 10/48] xfs: validate operation header length and alignment during recovery Dave Chinner
2026-10-13  6:01 ` [PATCH 11/48] xfs: validate the operation header padding " Dave Chinner
2026-10-13  6:01 ` [PATCH 12/48] xfs: validate the operation header flags " Dave Chinner
2026-10-13  6:01 ` [PATCH 13/48] xfs: enforce zero length control records " Dave Chinner
2026-10-13  6:01 ` [PATCH 14/48] xfs: validate the unmount record " Dave Chinner
2026-10-13  6:01 ` [PATCH 15/48] xfs: handle zero length continuation op headers " Dave Chinner
2026-10-13  6:01 ` [PATCH 16/48] xfs: bound the assembled region size " Dave Chinner
2026-10-13  6:01 ` [PATCH 17/48] xfs: dump the corrupt region when log item validation fails Dave Chinner
2026-10-13  6:01 ` [PATCH 18/48] xfs: validate fixed size log items during recovery Dave Chinner
2026-10-13  6:01 ` [PATCH 19/48] xfs: validate extent free " Dave Chinner
2026-10-13  6:01 ` [PATCH 20/48] xfs: validate and convert extent free intents " Dave Chinner
2026-10-13  6:01 ` [PATCH 21/48] xfs: validate and convert extent free done items " Dave Chinner
2026-10-13  6:01 ` [PATCH 22/48] xfs: validate rmap update intents " Dave Chinner
2026-10-13  6:01 ` [PATCH 23/48] xfs: validate rmap update done items " Dave Chinner
2026-10-13  6:01 ` [PATCH 24/48] xfs: validate refcount update intents " Dave Chinner
2026-10-13  6:01 ` [PATCH 25/48] xfs: validate refcount update done items " Dave Chinner
2026-10-13  6:01 ` [PATCH 26/48] xfs: validate bmap update intents " Dave Chinner
2026-10-13  6:01 ` [PATCH 27/48] xfs: validate bmap update done items " Dave Chinner
2026-10-13  6:01 ` [PATCH 28/48] xfs: validate mapping exchange intents " Dave Chinner
2026-10-13  6:01 ` [PATCH 29/48] xfs: validate mapping exchange done items " Dave Chinner
2026-10-13  6:01 ` [PATCH 30/48] xfs: validate dquot " Dave Chinner
2026-10-13  6:01 ` [PATCH 31/48] xfs: validate attr done " Dave Chinner
2026-10-13  6:01 ` [PATCH 32/48] xfs: validate attr intents " Dave Chinner
2026-10-13  6:01 ` [PATCH 33/48] xfs: convert inode items to host format " Dave Chinner
2026-10-13  6:01 ` [PATCH 34/48] xfs: allow xfs_imap() to map without an inode btree lookup Dave Chinner
2026-10-13  6:01 ` [PATCH 35/48] xfs: validate the inode item format header during recovery Dave Chinner
2026-10-13  6:01 ` [PATCH 36/48] xfs: validate the logged inode core " Dave Chinner
2026-10-13  6:01 ` [PATCH 37/48] xfs: validate the logged inode forks " Dave Chinner
2026-10-13  6:01 ` [PATCH 38/48] xfs: validate logged local fork contents " Dave Chinner
2026-10-13  6:01 ` [PATCH 39/48] xfs: validate logged extent " Dave Chinner
2026-10-13  6:01 ` Dave Chinner [this message]
2026-10-13  6:01 ` [PATCH 41/48] xfs: validate logged btree fork roots " Dave Chinner
2026-10-13  6:01 ` [PATCH 42/48] xfs: validate logged metadata " Dave Chinner
2026-10-13  6:01 ` [PATCH 43/48] xfs: validate buffer item region count " Dave Chinner
2026-10-13  6:01 ` [PATCH 44/48] xfs: validate buffer item regions " Dave Chinner
2026-10-13  6:01 ` [PATCH 45/48] xfs: validate the whole buffer item " Dave Chinner
2026-10-13  6:01 ` [PATCH 46/48] xfs: remove redundant buffer checks from recovery replay Dave Chinner
2026-10-13  6:01 ` [PATCH 47/48] xfs: fail recovery on a buffer type mismatch Dave Chinner
2026-10-13  6:01 ` [PATCH 48/48] xfs: validate logged dquot buffers during recovery Dave Chinner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261013060204.3138690-41-dgc@kernel.org \
    --to=dgc@kernel.org \
    --cc=cem@kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.