[PATCH 2/2] btrfs: add validation for extent states

Qu Wenruo <[email protected]> Tue, 28 Jul 2026 16:09:04 +0930
Newsgroups org.kernel.vger.linux-btrfs
Message-ID <b9f436fc89e7bdb5411ff8e6b5eb8e90ea6043a0.1785220613.git.wqu@suse.com>
Extent maps have the extra validation since commit 3f255ece2f1e ("btrfs:
introduce extra sanity checks for extent maps"), but extent states do
not have a similar check.

Introduce a basic alignment check for the following call sites, so that
we can cover all extent maps inserted into the tree:

- insert_state_fast()
- insert_state()
- split_state()

Signed-off-by: Qu Wenruo <[email protected]>
---
 fs/btrfs/extent-io-tree.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/fs/btrfs/extent-io-tree.c b/fs/btrfs/extent-io-tree.c
index c18ea5ef2974..4f1ef33f17ac 100644
--- a/fs/btrfs/extent-io-tree.c
+++ b/fs/btrfs/extent-io-tree.c
@@ -403,6 +403,21 @@ static void set_state_bits(struct extent_io_tree *tree,
 	state->state |= bits_to_set;
 }
 
+static void validate_extent_state(const struct extent_io_tree *tree,
+				  struct extent_state *state)
+{
+	u32 blocksize;
+
+	if (tree->owner != IO_TREE_INODE_IO)
+		return;
+
+	blocksize = btrfs_extent_io_tree_to_fs_info(tree)->sectorsize;
+	ASSERT(IS_ALIGNED(state->start, blocksize) &&
+	       IS_ALIGNED(state->end + 1, blocksize),
+	       "unaligned extent state, blocksize=%u start=%llu end=%llu state=0x%x",
+	       blocksize, state->start, state->end, state->state);
+}
+
 /*
  * Insert an extent_state struct into the tree.  'bits' are set on the
  * struct before it is inserted.
@@ -429,6 +444,8 @@ static struct extent_state *insert_state(struct extent_io_tree *tree,
 	const u64 end = state->end + 1;
 	const bool try_merge = !(bits & (EXTENT_LOCK_BITS | EXTENT_BOUNDARY));
 
+	validate_extent_state(tree, state);
+
 	set_state_bits(tree, state, bits, changeset);
 
 	node = &tree->state.rb_node;
@@ -481,6 +498,8 @@ static void insert_state_fast(struct extent_io_tree *tree,
 			      struct rb_node *parent, unsigned bits,
 			      struct extent_changeset *changeset)
 {
+	validate_extent_state(tree, state);
+
 	set_state_bits(tree, state, bits, changeset);
 	rb_link_node(&state->rb_node, parent, node);
 	rb_insert_color(&state->rb_node, &tree->state);
@@ -533,6 +552,8 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig,
 		}
 	}
 
+	validate_extent_state(tree, orig);
+	validate_extent_state(tree, prealloc);
 	rb_link_node(&prealloc->rb_node, parent, node);
 	rb_insert_color(&prealloc->rb_node, &tree->state);
 
-- 
2.54.0