[PATCH] btrfs: zoned: finish active block group cleanup if call_zone_finish() fails
Johannes Thumshirn <[email protected]>
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <[email protected]> |
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;
}
up_read(&dev_replace->rwsem);
- if (!fully_written)
+ if (!ret && !fully_written)
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)
--
2.55.0