mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 02:39:48 +00:00
Btrfs: test free space only for unclustered allocation
Since the clustered allocation may be taking extents from a different block group, there's no point in spin-locking and testing the current block group free space before attempting to allocate space from a cluster, even more so when we might refrain from even trying the cluster in the current block group because, after the cluster was set up, not enough free space remained. Furthermore, cluster creation attempts fail fast when the block group doesn't have enough free space, so the test was completely superfluous. I've move the free space test past the cluster allocation attempt, where it is more useful, and arranged for a cluster in the current block group to be released before trying an unclustered allocation, when we reach the LOOP_NO_EMPTY_SIZE stage, so that the free space in the cluster stands a chance of being combined with additional free space in the block group so as to succeed in the allocation attempt. Signed-off-by: Alexandre Oliva <oliva@lsd.ic.unicamp.br> Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
1100373f8a
commit
a5f6f719a5
1 changed files with 23 additions and 11 deletions
|
@ -5286,15 +5286,6 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
|
|||
if (unlikely(block_group->ro))
|
||||
goto loop;
|
||||
|
||||
spin_lock(&block_group->free_space_ctl->tree_lock);
|
||||
if (cached &&
|
||||
block_group->free_space_ctl->free_space <
|
||||
num_bytes + empty_cluster + empty_size) {
|
||||
spin_unlock(&block_group->free_space_ctl->tree_lock);
|
||||
goto loop;
|
||||
}
|
||||
spin_unlock(&block_group->free_space_ctl->tree_lock);
|
||||
|
||||
/*
|
||||
* Ok we want to try and use the cluster allocator, so
|
||||
* lets look there
|
||||
|
@ -5340,8 +5331,15 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
|
|||
* plenty of times and not have found
|
||||
* anything, so we are likely way too
|
||||
* fragmented for the clustering stuff to find
|
||||
* anything. */
|
||||
if (loop >= LOOP_NO_EMPTY_SIZE) {
|
||||
* anything.
|
||||
*
|
||||
* However, if the cluster is taken from the
|
||||
* current block group, release the cluster
|
||||
* first, so that we stand a better chance of
|
||||
* succeeding in the unclustered
|
||||
* allocation. */
|
||||
if (loop >= LOOP_NO_EMPTY_SIZE &&
|
||||
last_ptr->block_group != block_group) {
|
||||
spin_unlock(&last_ptr->refill_lock);
|
||||
goto unclustered_alloc;
|
||||
}
|
||||
|
@ -5352,6 +5350,11 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
|
|||
*/
|
||||
btrfs_return_cluster_to_free_space(NULL, last_ptr);
|
||||
|
||||
if (loop >= LOOP_NO_EMPTY_SIZE) {
|
||||
spin_unlock(&last_ptr->refill_lock);
|
||||
goto unclustered_alloc;
|
||||
}
|
||||
|
||||
/* allocate a cluster in this block group */
|
||||
ret = btrfs_find_space_cluster(trans, root,
|
||||
block_group, last_ptr,
|
||||
|
@ -5392,6 +5395,15 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
|
|||
}
|
||||
|
||||
unclustered_alloc:
|
||||
spin_lock(&block_group->free_space_ctl->tree_lock);
|
||||
if (cached &&
|
||||
block_group->free_space_ctl->free_space <
|
||||
num_bytes + empty_cluster + empty_size) {
|
||||
spin_unlock(&block_group->free_space_ctl->tree_lock);
|
||||
goto loop;
|
||||
}
|
||||
spin_unlock(&block_group->free_space_ctl->tree_lock);
|
||||
|
||||
offset = btrfs_find_space_for_alloc(block_group, search_start,
|
||||
num_bytes, empty_size);
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue