]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: panic instead of warn when splitting extent state not in the tree
authorFilipe Manana <fdmanana@suse.com>
Wed, 11 Mar 2026 16:15:59 +0000 (16:15 +0000)
committerDavid Sterba <dsterba@suse.com>
Tue, 7 Apr 2026 16:56:04 +0000 (18:56 +0200)
We are not expected ever to split an extent state record that is not in
the rbtree, as every record we pass to split_state() was found by
iterating the rbtree, so if that ever happens it means we are not holding
the extent io tree's spinlock or we have some memory corruption.

Instead of simply warning in case the extent state record passed to
split_state() is not in the rbtree, panic as this is a serious problem.
Also tag as unlikely the case where the record is not in the rbtree.

This also makes a tiny reduction the btrfs module's text size.

Before:

  $ size fs/btrfs/btrfs.ko
     text    data     bss     dec     hex filename
  2000080  174328   15592 2190000  216ab0 fs/btrfs/btrfs.ko

After:

  $ size fs/btrfs/btrfs.ko
     text    data     bss     dec     hex filename
  2000064  174328   15592 2189984  216aa0 fs/btrfs/btrfs.ko

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent-io-tree.c

index 29fcd08b9ca9b64722dc5eedcb8f06da06068f60..72ddd8d2e7a3eb8f63d87ea3c6abbfbe24b0c59e 100644 (file)
@@ -591,14 +591,13 @@ static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
        state->state &= ~bits_to_clear;
        state_wake_up(tree, state, bits);
        if (state->state == 0) {
+               if (unlikely(!extent_state_in_tree(state)))
+                       extent_io_tree_panic(tree, state, "extent_state_in_tree", -EUCLEAN);
+
                next = next_search_state(state, end);
-               if (extent_state_in_tree(state)) {
-                       rb_erase(&state->rb_node, &tree->state);
-                       RB_CLEAR_NODE(&state->rb_node);
-                       btrfs_free_extent_state(state);
-               } else {
-                       WARN_ON(1);
-               }
+               rb_erase(&state->rb_node, &tree->state);
+               RB_CLEAR_NODE(&state->rb_node);
+               btrfs_free_extent_state(state);
        } else {
                merge_state(tree, state);
                next = next_search_state(state, end);