Re: [PATCH] btrfs: zoned: finish active block group cleanup if call_zone_finish() fails

Qu Wenruo <[email protected]>
Newsgroups org.kernel.vger.linux-btrfs
Message-ID <[email protected]>

在 2026/8/19 19:56, Johannes Thumshirn 写道:
> do_zone_finish() clears BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE before finishing
> the zones. If call_zone_finish() then fails it returned early, leaving the
> now inactive block group on fs_info->zone_active_bgs, leaking its
> reference, the BTRFS_FS_NEED_ZONE_FINISH waiters are never woken, and as
> its alloc_offset equals the zone capacity btrfs_zone_finish_one_bg() keeps
> selecting it, spinning btrfs_zoned_activate_one_bg().
> 
> Fall through to the cleanup on failure too and return the error, but keep
> the block group read-only as its zones are left inconsistent.
> 
> Fixes: d70cbdda75da ("btrfs: zoned: consolidate zone finish functions")
> Link: https://sashiko.dev/#/patchset/20260818100037.1366563-1-johannes.thumshirn%40wdc.com
> Signed-off-by: Johannes Thumshirn <[email protected]>
> ---
>   fs/btrfs/zoned.c | 10 ++++------
>   1 file changed, 4 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
> index 82c2394dd43c..9d448cdd60c4 100644
> --- a/fs/btrfs/zoned.c
> +++ b/fs/btrfs/zoned.c
> @@ -2628,14 +2628,12 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
>   	for (i = 0; i < map->num_stripes; i++) {
>   
>   		ret = call_zone_finish(block_group, &map->stripes[i]);
> -		if (ret) {
> -			up_read(&dev_replace->rwsem);
> -			return ret;
> -		}
> +		if (ret)
> +			break;

I'm wondering should we continue to finish the other stripes instead?

>   	}
>   	up_read(&dev_replace->rwsem);
>   
> -	if (!fully_written)
> +	if (!ret && !fully_written)

Not familiar with zoned code, but if we hit an error, the block group 
will stay RO.

Is that the expected behavior?

The branch for bg with FLAG_ZONED_DATA_RELOC case, we return -EAGAIN but 
decrease the bg RO before returning.

So it looks like we should always decrease the bg RO even for error case?

Thanks,
Qu

>   		btrfs_dec_block_group_ro(block_group);
>   
>   	spin_lock(&fs_info->zone_active_bgs_lock);
> @@ -2648,7 +2646,7 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
>   
>   	clear_and_wake_up_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags);
>   
> -	return 0;
> +	return ret;
>   }
>   
>   int btrfs_zone_finish(struct btrfs_block_group *block_group)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.