Commit 4366211c authored by Chris Mason's avatar Chris Mason

Btfs: More metadata allocator optimizations

This lowers the empty cluster target for metadata allocations.  The lower
target makes it easier to do allocations and still seems to perform well.

It also fixes the allocator loop to drop the empty cluster when things
start getting difficult, avoiding false enospc warnings.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 3b7885bf
...@@ -2116,6 +2116,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, ...@@ -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; struct btrfs_root * root = orig_root->fs_info->extent_root;
u64 total_needed = num_bytes; u64 total_needed = num_bytes;
u64 *last_ptr = NULL; u64 *last_ptr = NULL;
u64 last_wanted = 0;
struct btrfs_block_group_cache *block_group = NULL; struct btrfs_block_group_cache *block_group = NULL;
int chunk_alloc_done = 0; int chunk_alloc_done = 0;
int empty_cluster = 2 * 1024 * 1024; int empty_cluster = 2 * 1024 * 1024;
...@@ -2134,22 +2135,28 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, ...@@ -2134,22 +2135,28 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
if (data & BTRFS_BLOCK_GROUP_METADATA) { if (data & BTRFS_BLOCK_GROUP_METADATA) {
last_ptr = &root->fs_info->last_alloc; 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)) if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD))
last_ptr = &root->fs_info->last_data_alloc; last_ptr = &root->fs_info->last_data_alloc;
if (last_ptr) { if (last_ptr) {
if (*last_ptr) if (*last_ptr) {
hint_byte = *last_ptr; hint_byte = *last_ptr;
else last_wanted = *last_ptr;
} else
empty_size += empty_cluster; empty_size += empty_cluster;
} else {
empty_cluster = 0;
} }
search_start = max(search_start, first_logical_byte(root, 0)); search_start = max(search_start, first_logical_byte(root, 0));
search_start = max(search_start, hint_byte); search_start = max(search_start, hint_byte);
total_needed += empty_size; total_needed += empty_size;
if (search_start != last_wanted)
last_wanted = 0;
block_group = btrfs_lookup_block_group(root->fs_info, search_start); block_group = btrfs_lookup_block_group(root->fs_info, search_start);
if (!block_group) if (!block_group)
block_group = btrfs_lookup_first_block_group(root->fs_info, 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, ...@@ -2195,9 +2202,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
if (search_start + num_bytes > end) if (search_start + num_bytes > end)
goto new_group; goto new_group;
if (last_ptr && *last_ptr && search_start != *last_ptr) { if (last_wanted && search_start != last_wanted) {
total_needed += empty_cluster; total_needed += empty_cluster;
*last_ptr = 0; last_wanted = 0;
/* /*
* if search_start is still in this block group * if search_start is still in this block group
* then we just re-search 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, ...@@ -2223,6 +2230,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
if (search_start >= start && if (search_start >= start &&
search_start < end) { search_start < end) {
mutex_unlock(&block_group->alloc_mutex); mutex_unlock(&block_group->alloc_mutex);
last_wanted = 0;
continue; continue;
} }
...@@ -2240,6 +2248,11 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, ...@@ -2240,6 +2248,11 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
break; break;
} }
new_group: new_group:
last_wanted = 0;
if (loop > 0) {
total_needed -= empty_cluster;
empty_cluster = 0;
}
mutex_unlock(&block_group->alloc_mutex); mutex_unlock(&block_group->alloc_mutex);
/* /*
* Here's how this works. * Here's how this works.
...@@ -2256,11 +2269,6 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, ...@@ -2256,11 +2269,6 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
if (loop == 0) { if (loop == 0) {
head = &space_info->block_groups; head = &space_info->block_groups;
cur = head->next; cur = head->next;
if (last_ptr && *last_ptr) {
total_needed += empty_cluster;
*last_ptr = 0;
}
loop++; loop++;
} else if (loop == 1 && cur == head) { } else if (loop == 1 && cur == head) {
if (allowed_chunk_alloc && !chunk_alloc_done) { if (allowed_chunk_alloc && !chunk_alloc_done) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment