From 776924b2d9c451fc9dcc40673d17ff255bbc0fef Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Mon, 24 Aug 2026 18:47:58 +0200 Subject: [PATCH] btrfs: set space_info before adding new free space in btrfs_make_block_group() btrfs_make_block_group() calls btrfs_add_new_free_space() before assigning cache->space_info. On a zoned filesystem that ends up in __btrfs_add_free_space_zoned(), which dereferences block_group->space_info and thus hits a NULL pointer dereference when a non-initial free space range is added (e.g. during relocation). Assign cache->space_info before the btrfs_add_new_free_space() call. Reviewed-by: Boris Burkov Signed-off-by: Johannes Thumshirn Signed-off-by: David Sterba --- fs/btrfs/block-group.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index 830460a40e86..ee182369254c 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -3074,6 +3074,18 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran return ERR_PTR(ret); } + /* + * Ensure the corresponding space_info object is created and + * assigned to our block group. We want our bg to be added to the rbtree + * with its ->space_info set. + * + * On a zoned filesystem btrfs_add_new_free_space() ends up in + * __btrfs_add_free_space_zoned(), which dereferences + * block_group->space_info, so it has to be set beforehand. + */ + cache->space_info = space_info; + ASSERT(cache->space_info); + ret = btrfs_add_new_free_space(cache, chunk_offset, chunk_offset + size, NULL); btrfs_free_excluded_extents(cache); if (ret) { @@ -3081,14 +3093,6 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran return ERR_PTR(ret); } - /* - * Ensure the corresponding space_info object is created and - * assigned to our block group. We want our bg to be added to the rbtree - * with its ->space_info set. - */ - cache->space_info = space_info; - ASSERT(cache->space_info); - ret = btrfs_add_block_group_cache(cache); if (ret) { btrfs_remove_free_space_cache(cache);