aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/block-group.c
diff options
context:
space:
mode:
authorNaohiro Aota <naohiro.aota@wdc.com>2022-03-22 18:11:34 +0900
committerDavid Sterba <dsterba@suse.com>2022-04-06 00:50:41 +0200
commit760e69c4c2e2f475a812bdd414b62758215ce9cb (patch)
treee7c664538a587650a344fc5569f43b2b889ba709 /fs/btrfs/block-group.c
parentbtrfs: return allocated block group from do_chunk_alloc() (diff)
downloadlinux-dev-760e69c4c2e2f475a812bdd414b62758215ce9cb.tar.xz
linux-dev-760e69c4c2e2f475a812bdd414b62758215ce9cb.zip
btrfs: zoned: activate block group only for extent allocation
In btrfs_make_block_group(), we activate the allocated block group, expecting that the block group is soon used for allocation. However, the chunk allocation from flush_space() context broke the assumption. There can be a large time gap between the chunk allocation time and the extent allocation time from the chunk. Activating the empty block groups pre-allocated from flush_space() context can exhaust the active zone counter of a device. Once we use all the active zone counts for empty pre-allocated block groups, we cannot activate new block group for the other things: metadata, tree-log, or data relocation block group. That failure results in a fake -ENOSPC. This patch introduces CHUNK_ALLOC_FORCE_FOR_EXTENT to distinguish the chunk allocation from find_free_extent(). Now, the new block group is activated only in that context. Fixes: eb66a010d518 ("btrfs: zoned: activate new block group") CC: stable@vger.kernel.org # 5.16+ Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Tested-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/block-group.c')
-rw-r--r--fs/btrfs/block-group.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index c2b898fe7b24..0dd6de994199 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -2503,12 +2503,6 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
return ERR_PTR(ret);
}
- /*
- * New block group is likely to be used soon. Try to activate it now.
- * Failure is OK for now.
- */
- btrfs_zone_activate(cache);
-
ret = exclude_super_stripes(cache);
if (ret) {
/* We may have excluded something, so call this just in case */
@@ -3660,8 +3654,14 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
struct btrfs_block_group *ret_bg;
bool wait_for_alloc = false;
bool should_alloc = false;
+ bool from_extent_allocation = false;
int ret = 0;
+ if (force == CHUNK_ALLOC_FORCE_FOR_EXTENT) {
+ from_extent_allocation = true;
+ force = CHUNK_ALLOC_FORCE;
+ }
+
/* Don't re-enter if we're already allocating a chunk */
if (trans->allocating_chunk)
return -ENOSPC;
@@ -3754,9 +3754,17 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
ret_bg = do_chunk_alloc(trans, flags);
trans->allocating_chunk = false;
- if (IS_ERR(ret_bg))
+ if (IS_ERR(ret_bg)) {
ret = PTR_ERR(ret_bg);
- else
+ } else if (from_extent_allocation) {
+ /*
+ * New block group is likely to be used soon. Try to activate
+ * it now. Failure is OK for now.
+ */
+ btrfs_zone_activate(ret_bg);
+ }
+
+ if (!ret)
btrfs_put_block_group(ret_bg);
spin_lock(&space_info->lock);