From: Mark Harmstone Date: Thu, 19 Feb 2026 19:19:00 +0000 (+0000) Subject: btrfs: check block group before marking it unused in balance_remap_chunks() X-Git-Tag: v7.0-rc5~13^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=adbb0ebacc3223a2dc2e58ef3d4c10f5e9653f09;p=thirdparty%2Flinux.git btrfs: check block group before marking it unused in balance_remap_chunks() Fix a potential segfault in balance_remap_chunks(): if we quit early because btrfs_inc_block_group_ro() fails, all the remaining items in the chunks list will still have their bg value set to NULL. It's thus not safe to dereference this pointer without checking first. Reported-by: Chris Mason Link: https://lore.kernel.org/linux-btrfs/20260125120717.1578828-1-clm@meta.com/ Fixes: 81e5a4551c32 ("btrfs: allow balancing remap tree") Reviewed-by: Johannes Thumshirn Signed-off-by: Mark Harmstone Signed-off-by: David Sterba --- diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 7efc2f7a9bb2..8fbd736aad9f 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -4277,20 +4277,29 @@ static int balance_remap_chunks(struct btrfs_fs_info *fs_info, struct btrfs_path end: while (!list_empty(chunks)) { bool is_unused; + struct btrfs_block_group *bg; rci = list_first_entry(chunks, struct remap_chunk_info, list); - spin_lock(&rci->bg->lock); - is_unused = !btrfs_is_block_group_used(rci->bg); - spin_unlock(&rci->bg->lock); + bg = rci->bg; + if (bg) { + /* + * This is a bit racy and the 'used' status can change + * but this is not a problem as later functions will + * verify it again. + */ + spin_lock(&bg->lock); + is_unused = !btrfs_is_block_group_used(bg); + spin_unlock(&bg->lock); - if (is_unused) - btrfs_mark_bg_unused(rci->bg); + if (is_unused) + btrfs_mark_bg_unused(bg); - if (rci->made_ro) - btrfs_dec_block_group_ro(rci->bg); + if (rci->made_ro) + btrfs_dec_block_group_ro(bg); - btrfs_put_block_group(rci->bg); + btrfs_put_block_group(bg); + } list_del(&rci->list); kfree(rci);