summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/extent-tree.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index b8c6541c33fe..0d73a53c6763 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2116,6 +2116,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
struct btrfs_root * root = orig_root->fs_info->extent_root;
u64 total_needed = num_bytes;
u64 *last_ptr = NULL;
+ u64 last_wanted = 0;
struct btrfs_block_group_cache *block_group = NULL;
int chunk_alloc_done = 0;
int empty_cluster = 2 * 1024 * 1024;
@@ -2134,22 +2135,28 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
if (data & BTRFS_BLOCK_GROUP_METADATA) {
last_ptr = &root->fs_info->last_alloc;
- empty_cluster = 256 * 1024;
+ empty_cluster = 64 * 1024;
}
if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD))
last_ptr = &root->fs_info->last_data_alloc;
if (last_ptr) {
- if (*last_ptr)
+ if (*last_ptr) {
hint_byte = *last_ptr;
- else
+ last_wanted = *last_ptr;
+ } else
empty_size += empty_cluster;
+ } else {
+ empty_cluster = 0;
}
search_start = max(search_start, first_logical_byte(root, 0));
search_start = max(search_start, hint_byte);
total_needed += empty_size;
+ if (search_start != last_wanted)
+ last_wanted = 0;
+
block_group = btrfs_lookup_block_group(root->fs_info, search_start);
if (!block_group)
block_group = btrfs_lookup_first_block_group(root->fs_info,
@@ -2195,9 +2202,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
if (search_start + num_bytes > end)
goto new_group;
- if (last_ptr && *last_ptr && search_start != *last_ptr) {
+ if (last_wanted && search_start != last_wanted) {
total_needed += empty_cluster;
- *last_ptr = 0;
+ last_wanted = 0;
/*
* if search_start is still in this block group
* then we just re-search this block group
@@ -2223,6 +2230,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
if (search_start >= start &&
search_start < end) {
mutex_unlock(&block_group->alloc_mutex);
+ last_wanted = 0;
continue;
}
@@ -2240,6 +2248,11 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
break;
}
new_group:
+ last_wanted = 0;
+ if (loop > 0) {
+ total_needed -= empty_cluster;
+ empty_cluster = 0;
+ }
mutex_unlock(&block_group->alloc_mutex);
/*
* Here's how this works.
@@ -2256,11 +2269,6 @@ new_group:
if (loop == 0) {
head = &space_info->block_groups;
cur = head->next;
-
- if (last_ptr && *last_ptr) {
- total_needed += empty_cluster;
- *last_ptr = 0;
- }
loop++;
} else if (loop == 1 && cur == head) {
if (allowed_chunk_alloc && !chunk_alloc_done) {