diff options
| author | Johannes Thumshirn <johannes.thumshirn@wdc.com> | 2026-08-24 18:47:58 +0200 |
|---|---|---|
| committer | David Sterba <dsterba@suse.com> | 2026-09-07 18:35:48 +0200 |
| commit | 776924b2d9c451fc9dcc40673d17ff255bbc0fef (patch) | |
| tree | f1d248c1a586eda3ddcdac1824b4fc670998bb42 | |
| parent | 6a7a45b1d94799a5eb8e6d26e65cf31a3fcda9e5 (diff) | |
| download | linux-next-776924b2d9c451fc9dcc40673d17ff255bbc0fef.tar.gz linux-next-776924b2d9c451fc9dcc40673d17ff255bbc0fef.zip | |
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 <boris@bur.io>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
| -rw-r--r-- | fs/btrfs/block-group.c | 18 |
1 files changed, 11 insertions, 7 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,21 +3074,25 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran return ERR_PTR(ret); } - ret = btrfs_add_new_free_space(cache, chunk_offset, chunk_offset + size, NULL); - btrfs_free_excluded_extents(cache); - if (ret) { - btrfs_put_block_group(cache); - 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) { + btrfs_put_block_group(cache); + return ERR_PTR(ret); + } + ret = btrfs_add_block_group_cache(cache); if (ret) { btrfs_remove_free_space_cache(cache); |
