All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context
@ 2022-03-22  9:11 Naohiro Aota
  2022-03-22  9:11 ` [PATCH v2 1/2] btrfs: return allocated block group from do_chunk_alloc() Naohiro Aota
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Naohiro Aota @ 2022-03-22  9:11 UTC (permalink / raw)
  To: linux-btrfs; +Cc: johannes.thumshirn, Naohiro Aota

In btrfs_make_block_group(), we activate the allocated block group,
expecting that the block group is soon used for the extent allocation.

With a lot of IOs, btrfs_async_reclaim_data_space() tries to prepare
for them by pre-allocating data block groups. That preallocation can
consume all the active zone counting. It is OK if they are soon
written and filled. However, that's not the case. As a result, an
allocation of non-data block groups fails due to the lack of an active
zone resource.

This series fixes the issue by activating a new block group only when
it's called from find_free_extent(). This series introduces
CHUNK_ALLOC_FORCE_FOR_EXTENT in btrfs_chunk_alloc_enum to distinguish
the context.

--
Changes
- v2
  - Fix a flipped condition

Naohiro Aota (2):
  btrfs: return allocated block group from do_chunk_alloc()
  btrfs: zoned: activate block group only for extent allocation

 fs/btrfs/block-group.c | 36 +++++++++++++++++++++++++++---------
 fs/btrfs/block-group.h |  1 +
 fs/btrfs/extent-tree.c |  2 +-
 3 files changed, 29 insertions(+), 10 deletions(-)

-- 
2.35.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/2] btrfs: return allocated block group from do_chunk_alloc()
  2022-03-22  9:11 [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context Naohiro Aota
@ 2022-03-22  9:11 ` Naohiro Aota
  2022-03-22  9:11 ` [PATCH v2 2/2] btrfs: zoned: activate block group only for extent allocation Naohiro Aota
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Naohiro Aota @ 2022-03-22  9:11 UTC (permalink / raw)
  To: linux-btrfs; +Cc: johannes.thumshirn, Naohiro Aota

Return the allocated block group from do_chunk_alloc(). This is a
preparation patch for the next patch.

Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
 fs/btrfs/block-group.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 59f18a10fd5f..d4ac1c76f539 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -3433,7 +3433,7 @@ int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, u64 type)
 	return btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE);
 }
 
-static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags)
+static struct btrfs_block_group *do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags)
 {
 	struct btrfs_block_group *bg;
 	int ret;
@@ -3520,7 +3520,11 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags)
 out:
 	btrfs_trans_release_chunk_metadata(trans);
 
-	return ret;
+	if (ret)
+		return ERR_PTR(ret);
+
+	btrfs_get_block_group(bg);
+	return bg;
 }
 
 /*
@@ -3635,6 +3639,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
 	struct btrfs_space_info *space_info;
+	struct btrfs_block_group *ret_bg;
 	bool wait_for_alloc = false;
 	bool should_alloc = false;
 	int ret = 0;
@@ -3728,9 +3733,14 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
 			force_metadata_allocation(fs_info);
 	}
 
-	ret = do_chunk_alloc(trans, flags);
+	ret_bg = do_chunk_alloc(trans, flags);
 	trans->allocating_chunk = false;
 
+	if (IS_ERR(ret_bg))
+		ret = PTR_ERR(ret_bg);
+	else
+		btrfs_put_block_group(ret_bg);
+
 	spin_lock(&space_info->lock);
 	if (ret < 0) {
 		if (ret == -ENOSPC)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/2] btrfs: zoned: activate block group only for extent allocation
  2022-03-22  9:11 [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context Naohiro Aota
  2022-03-22  9:11 ` [PATCH v2 1/2] btrfs: return allocated block group from do_chunk_alloc() Naohiro Aota
@ 2022-03-22  9:11 ` Naohiro Aota
  2022-04-01 14:12   ` David Sterba
  2022-03-22 16:03 ` [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context Johannes Thumshirn
  2022-04-01 14:22 ` David Sterba
  3 siblings, 1 reply; 6+ messages in thread
From: Naohiro Aota @ 2022-03-22  9:11 UTC (permalink / raw)
  To: linux-btrfs; +Cc: johannes.thumshirn, Naohiro Aota

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 BGs, we cannot activate new BG for the
other things: metadata, tree-log, or data relocation BG. 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+: c7d1b9109dd0: btrfs: return allocated block group from do_chunk_alloc()
Cc: stable@vger.kernel.org # 5.16+
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
 fs/btrfs/block-group.c | 24 ++++++++++++++++--------
 fs/btrfs/block-group.h |  1 +
 fs/btrfs/extent-tree.c |  2 +-
 3 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index d4ac1c76f539..84c97d76de92 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -2481,12 +2481,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 */
@@ -3642,8 +3636,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;
@@ -3736,9 +3736,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);
diff --git a/fs/btrfs/block-group.h b/fs/btrfs/block-group.h
index 93aabc68bb6a..9c822367c432 100644
--- a/fs/btrfs/block-group.h
+++ b/fs/btrfs/block-group.h
@@ -40,6 +40,7 @@ enum btrfs_chunk_alloc_enum {
 	CHUNK_ALLOC_NO_FORCE,
 	CHUNK_ALLOC_LIMITED,
 	CHUNK_ALLOC_FORCE,
+	CHUNK_ALLOC_FORCE_FOR_EXTENT,
 };
 
 struct btrfs_caching_control {
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f477035a2ac2..6aa92f84f465 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4082,7 +4082,7 @@ static int find_free_extent_update_loop(struct btrfs_fs_info *fs_info,
 			}
 
 			ret = btrfs_chunk_alloc(trans, ffe_ctl->flags,
-						CHUNK_ALLOC_FORCE);
+						CHUNK_ALLOC_FORCE_FOR_EXTENT);
 
 			/* Do not bail out on ENOSPC since we can do more. */
 			if (ret == -ENOSPC)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context
  2022-03-22  9:11 [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context Naohiro Aota
  2022-03-22  9:11 ` [PATCH v2 1/2] btrfs: return allocated block group from do_chunk_alloc() Naohiro Aota
  2022-03-22  9:11 ` [PATCH v2 2/2] btrfs: zoned: activate block group only for extent allocation Naohiro Aota
@ 2022-03-22 16:03 ` Johannes Thumshirn
  2022-04-01 14:22 ` David Sterba
  3 siblings, 0 replies; 6+ messages in thread
From: Johannes Thumshirn @ 2022-03-22 16:03 UTC (permalink / raw)
  To: Naohiro Aota, linux-btrfs

On 22/03/2022 10:11, Naohiro Aota wrote:
> In btrfs_make_block_group(), we activate the allocated block group,
> expecting that the block group is soon used for the extent allocation.
> 
> With a lot of IOs, btrfs_async_reclaim_data_space() tries to prepare
> for them by pre-allocating data block groups. That preallocation can
> consume all the active zone counting. It is OK if they are soon
> written and filled. However, that's not the case. As a result, an
> allocation of non-data block groups fails due to the lack of an active
> zone resource.
> 
> This series fixes the issue by activating a new block group only when
> it's called from find_free_extent(). This series introduces
> CHUNK_ALLOC_FORCE_FOR_EXTENT in btrfs_chunk_alloc_enum to distinguish
> the context.
> 
> --
> Changes
> - v2
>   - Fix a flipped condition
> 
> Naohiro Aota (2):
>   btrfs: return allocated block group from do_chunk_alloc()
>   btrfs: zoned: activate block group only for extent allocation
> 
>  fs/btrfs/block-group.c | 36 +++++++++++++++++++++++++++---------
>  fs/btrfs/block-group.h |  1 +
>  fs/btrfs/extent-tree.c |  2 +-
>  3 files changed, 29 insertions(+), 10 deletions(-)
> 


For the series,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Tested-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/2] btrfs: zoned: activate block group only for extent allocation
  2022-03-22  9:11 ` [PATCH v2 2/2] btrfs: zoned: activate block group only for extent allocation Naohiro Aota
@ 2022-04-01 14:12   ` David Sterba
  0 siblings, 0 replies; 6+ messages in thread
From: David Sterba @ 2022-04-01 14:12 UTC (permalink / raw)
  To: Naohiro Aota; +Cc: linux-btrfs, johannes.thumshirn

On Tue, Mar 22, 2022 at 06:11:34PM +0900, Naohiro Aota wrote:
> 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 BGs, we cannot activate new BG for the
> other things: metadata, tree-log, or data relocation BG. 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+: c7d1b9109dd0: btrfs: return allocated block group from do_chunk_alloc()
> Cc: stable@vger.kernel.org # 5.16+
> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
> ---
>  fs/btrfs/block-group.c | 24 ++++++++++++++++--------
>  fs/btrfs/block-group.h |  1 +
>  fs/btrfs/extent-tree.c |  2 +-
>  3 files changed, 18 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
> index d4ac1c76f539..84c97d76de92 100644
> --- a/fs/btrfs/block-group.c
> +++ b/fs/btrfs/block-group.c
> @@ -2481,12 +2481,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 */
> @@ -3642,8 +3636,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;
> @@ -3736,9 +3736,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);
> diff --git a/fs/btrfs/block-group.h b/fs/btrfs/block-group.h
> index 93aabc68bb6a..9c822367c432 100644
> --- a/fs/btrfs/block-group.h
> +++ b/fs/btrfs/block-group.h
> @@ -40,6 +40,7 @@ enum btrfs_chunk_alloc_enum {
>  	CHUNK_ALLOC_NO_FORCE,
>  	CHUNK_ALLOC_LIMITED,
>  	CHUNK_ALLOC_FORCE,
> +	CHUNK_ALLOC_FORCE_FOR_EXTENT,

There's a comment documenting what it means, I've written

	CHUNK_ALLOC_FORCE_FOR_EXTENT like CHUNK_ALLOC_FORCE but called from
	find_free_extent() that also activaes the zone

based on the changelog.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context
  2022-03-22  9:11 [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context Naohiro Aota
                   ` (2 preceding siblings ...)
  2022-03-22 16:03 ` [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context Johannes Thumshirn
@ 2022-04-01 14:22 ` David Sterba
  3 siblings, 0 replies; 6+ messages in thread
From: David Sterba @ 2022-04-01 14:22 UTC (permalink / raw)
  To: Naohiro Aota; +Cc: linux-btrfs, johannes.thumshirn

On Tue, Mar 22, 2022 at 06:11:32PM +0900, Naohiro Aota wrote:
> In btrfs_make_block_group(), we activate the allocated block group,
> expecting that the block group is soon used for the extent allocation.
> 
> With a lot of IOs, btrfs_async_reclaim_data_space() tries to prepare
> for them by pre-allocating data block groups. That preallocation can
> consume all the active zone counting. It is OK if they are soon
> written and filled. However, that's not the case. As a result, an
> allocation of non-data block groups fails due to the lack of an active
> zone resource.
> 
> This series fixes the issue by activating a new block group only when
> it's called from find_free_extent(). This series introduces
> CHUNK_ALLOC_FORCE_FOR_EXTENT in btrfs_chunk_alloc_enum to distinguish
> the context.
> 
> --
> Changes
> - v2
>   - Fix a flipped condition
> 
> Naohiro Aota (2):
>   btrfs: return allocated block group from do_chunk_alloc()
>   btrfs: zoned: activate block group only for extent allocation

Added to misc-next, thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-04-01 14:26 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-22  9:11 [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context Naohiro Aota
2022-03-22  9:11 ` [PATCH v2 1/2] btrfs: return allocated block group from do_chunk_alloc() Naohiro Aota
2022-03-22  9:11 ` [PATCH v2 2/2] btrfs: zoned: activate block group only for extent allocation Naohiro Aota
2022-04-01 14:12   ` David Sterba
2022-03-22 16:03 ` [PATCH v2 0/2] btrfs: zoned: activate new BG only from extent allocation context Johannes Thumshirn
2022-04-01 14:22 ` David Sterba

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.