btrfs: Refactor unclustered extent allocation into find_free_extent_unclustered()

This patch will extract unclsutered extent allocation code into
find_free_extent_unclustered().

And this helper function will use return value to indicate what to do
next.

This should make find_free_extent() a little easier to read.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Su Yue <suy.fnst@cn.fujitsu.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
[Update merge conflict with fb5c39d7a8 ("btrfs: don't use ctl->free_space for max_extent_size")]
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Qu Wenruo 2018-11-02 09:39:49 +08:00 committed by David Sterba
parent d06e3bb690
commit e1a4184815
1 changed files with 69 additions and 46 deletions

View File

@ -7415,6 +7415,70 @@ static int find_free_extent_clustered(struct btrfs_block_group_cache *bg,
return 1;
}
/*
* Return >0 to inform caller that we find nothing
* Return 0 when we found an free extent and set ffe_ctrl->found_offset
* Return -EAGAIN to inform caller that we need to re-search this block group
*/
static int find_free_extent_unclustered(struct btrfs_block_group_cache *bg,
struct btrfs_free_cluster *last_ptr,
struct find_free_extent_ctl *ffe_ctl)
{
u64 offset;
/*
* We are doing an unclustered allocation, set the fragmented flag so
* we don't bother trying to setup a cluster again until we get more
* space.
*/
if (unlikely(last_ptr)) {
spin_lock(&last_ptr->lock);
last_ptr->fragmented = 1;
spin_unlock(&last_ptr->lock);
}
if (ffe_ctl->cached) {
struct btrfs_free_space_ctl *free_space_ctl;
free_space_ctl = bg->free_space_ctl;
spin_lock(&free_space_ctl->tree_lock);
if (free_space_ctl->free_space <
ffe_ctl->num_bytes + ffe_ctl->empty_cluster +
ffe_ctl->empty_size) {
ffe_ctl->total_free_space = max_t(u64,
ffe_ctl->total_free_space,
free_space_ctl->free_space);
spin_unlock(&free_space_ctl->tree_lock);
return 1;
}
spin_unlock(&free_space_ctl->tree_lock);
}
offset = btrfs_find_space_for_alloc(bg, ffe_ctl->search_start,
ffe_ctl->num_bytes, ffe_ctl->empty_size,
&ffe_ctl->max_extent_size);
/*
* If we didn't find a chunk, and we haven't failed on this block group
* before, and this block group is in the middle of caching and we are
* ok with waiting, then go ahead and wait for progress to be made, and
* set @retry_unclustered to true.
*
* If @retry_unclustered is true then we've already waited on this
* block group once and should move on to the next block group.
*/
if (!offset && !ffe_ctl->retry_unclustered && !ffe_ctl->cached &&
ffe_ctl->loop > LOOP_CACHING_NOWAIT) {
wait_block_group_cache_progress(bg, ffe_ctl->num_bytes +
ffe_ctl->empty_size);
ffe_ctl->retry_unclustered = true;
return -EAGAIN;
} else if (!offset) {
return 1;
}
ffe_ctl->found_offset = offset;
return 0;
}
/*
* walks the btree of allocated extents and find a hole of a given size.
* The key ins is changed to record the hole:
@ -7617,54 +7681,13 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
/* ret == -ENOENT case falls through */
}
/*
* We are doing an unclustered alloc, set the fragmented flag so
* we don't bother trying to setup a cluster again until we get
* more space.
*/
if (unlikely(last_ptr)) {
spin_lock(&last_ptr->lock);
last_ptr->fragmented = 1;
spin_unlock(&last_ptr->lock);
}
if (ffe_ctl.cached) {
struct btrfs_free_space_ctl *ctl =
block_group->free_space_ctl;
spin_lock(&ctl->tree_lock);
if (ctl->free_space <
num_bytes + ffe_ctl.empty_cluster + empty_size) {
ffe_ctl.total_free_space = max(ctl->free_space,
ffe_ctl.total_free_space);
spin_unlock(&ctl->tree_lock);
goto loop;
}
spin_unlock(&ctl->tree_lock);
}
ffe_ctl.found_offset = btrfs_find_space_for_alloc(block_group,
ffe_ctl.search_start, num_bytes, empty_size,
&ffe_ctl.max_extent_size);
/*
* If we didn't find a chunk, and we haven't failed on this
* block group before, and this block group is in the middle of
* caching and we are ok with waiting, then go ahead and wait
* for progress to be made, and set ffe_ctl.retry_unclustered to
* true.
*
* If ffe_ctl.retry_unclustered is true then we've already
* waited on this block group once and should move on to the
* next block group.
*/
if (!ffe_ctl.found_offset && !ffe_ctl.retry_unclustered &&
!ffe_ctl.cached && ffe_ctl.loop > LOOP_CACHING_NOWAIT) {
wait_block_group_cache_progress(block_group,
num_bytes + empty_size);
ffe_ctl.retry_unclustered = true;
ret = find_free_extent_unclustered(block_group, last_ptr,
&ffe_ctl);
if (ret == -EAGAIN)
goto have_block_group;
} else if (!ffe_ctl.found_offset) {
else if (ret > 0)
goto loop;
}
/* ret == 0 case falls through */
checks:
ffe_ctl.search_start = round_up(ffe_ctl.found_offset,
fs_info->stripesize);