Commit f84a8b36 authored by Chris Mason's avatar Chris Mason

Btrfs: Optimize allocations as we need to mix data and metadata into one group

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent a273208e
...@@ -279,6 +279,8 @@ struct btrfs_csum_item { ...@@ -279,6 +279,8 @@ struct btrfs_csum_item {
#define BTRFS_BLOCK_GROUP_DATA 1 #define BTRFS_BLOCK_GROUP_DATA 1
#define BTRFS_BLOCK_GROUP_MIXED 2
struct btrfs_block_group_item { struct btrfs_block_group_item {
__le64 used; __le64 used;
u8 flags; u8 flags;
......
...@@ -168,11 +168,13 @@ static u64 find_search_start(struct btrfs_root *root, ...@@ -168,11 +168,13 @@ static u64 find_search_start(struct btrfs_root *root,
u64 last; u64 last;
u64 start = 0; u64 start = 0;
u64 end = 0; u64 end = 0;
int wrapped = 0;
again: again:
ret = cache_block_group(root, cache); ret = cache_block_group(root, cache);
if (ret) if (ret)
goto out; goto out;
last = max(search_start, cache->key.objectid); last = max(search_start, cache->key.objectid);
while(1) { while(1) {
...@@ -195,8 +197,15 @@ static u64 find_search_start(struct btrfs_root *root, ...@@ -195,8 +197,15 @@ static u64 find_search_start(struct btrfs_root *root,
new_group: new_group:
last = cache->key.objectid + cache->key.offset; last = cache->key.objectid + cache->key.offset;
wrapped:
cache = btrfs_lookup_block_group(root->fs_info, last); cache = btrfs_lookup_block_group(root->fs_info, last);
if (!cache) { if (!cache) {
if (!wrapped) {
wrapped = 1;
last = search_start;
data = BTRFS_BLOCK_GROUP_MIXED;
goto wrapped;
}
return search_start; return search_start;
} }
cache = btrfs_find_block_group(root, cache, last, data, 0); cache = btrfs_find_block_group(root, cache, last, data, 0);
...@@ -236,9 +245,11 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -236,9 +245,11 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
block_group_cache = &info->block_group_cache; block_group_cache = &info->block_group_cache;
if (!owner) if (!owner)
factor = 5; factor = 8;
if (data) if (data == BTRFS_BLOCK_GROUP_MIXED)
bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA;
else if (data)
bit = BLOCK_GROUP_DATA; bit = BLOCK_GROUP_DATA;
else else
bit = BLOCK_GROUP_METADATA; bit = BLOCK_GROUP_METADATA;
...@@ -246,14 +257,16 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -246,14 +257,16 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
if (search_start) { if (search_start) {
struct btrfs_block_group_cache *shint; struct btrfs_block_group_cache *shint;
shint = btrfs_lookup_block_group(info, search_start); shint = btrfs_lookup_block_group(info, search_start);
if (shint && shint->data == data) { if (shint && (shint->data == data ||
shint->data == BTRFS_BLOCK_GROUP_MIXED)) {
used = btrfs_block_group_used(&shint->item); used = btrfs_block_group_used(&shint->item);
if (used < div_factor(shint->key.offset, factor)) { if (used < div_factor(shint->key.offset, factor)) {
return shint; return shint;
} }
} }
} }
if (hint && hint->data == data) { if (hint && (hint->data == data ||
hint->data == BTRFS_BLOCK_GROUP_MIXED)) {
used = btrfs_block_group_used(&hint->item); used = btrfs_block_group_used(&hint->item);
if (used < div_factor(hint->key.offset, factor)) { if (used < div_factor(hint->key.offset, factor)) {
return hint; return hint;
...@@ -592,11 +605,15 @@ static int update_block_group(struct btrfs_trans_handle *trans, ...@@ -592,11 +605,15 @@ static int update_block_group(struct btrfs_trans_handle *trans,
if (data) { if (data) {
bit_to_clear = BLOCK_GROUP_METADATA; bit_to_clear = BLOCK_GROUP_METADATA;
bit_to_set = BLOCK_GROUP_DATA; bit_to_set = BLOCK_GROUP_DATA;
cache->item.flags &=
~BTRFS_BLOCK_GROUP_MIXED;
cache->item.flags |= cache->item.flags |=
BTRFS_BLOCK_GROUP_DATA; BTRFS_BLOCK_GROUP_DATA;
} else { } else {
bit_to_clear = BLOCK_GROUP_DATA; bit_to_clear = BLOCK_GROUP_DATA;
bit_to_set = BLOCK_GROUP_METADATA; bit_to_set = BLOCK_GROUP_METADATA;
cache->item.flags &=
~BTRFS_BLOCK_GROUP_MIXED;
cache->item.flags &= cache->item.flags &=
~BTRFS_BLOCK_GROUP_DATA; ~BTRFS_BLOCK_GROUP_DATA;
} }
...@@ -606,6 +623,14 @@ static int update_block_group(struct btrfs_trans_handle *trans, ...@@ -606,6 +623,14 @@ static int update_block_group(struct btrfs_trans_handle *trans,
set_extent_bits(&info->block_group_cache, set_extent_bits(&info->block_group_cache,
start, end, bit_to_set, start, end, bit_to_set,
GFP_NOFS); GFP_NOFS);
} else if (cache->data != data &&
cache->data != BTRFS_BLOCK_GROUP_MIXED) {
cache->data = BTRFS_BLOCK_GROUP_MIXED;
set_extent_bits(&info->block_group_cache,
start, end,
BLOCK_GROUP_DATA |
BLOCK_GROUP_METADATA,
GFP_NOFS);
} }
old_val += num_bytes; old_val += num_bytes;
} else { } else {
...@@ -886,6 +911,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -886,6 +911,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
struct btrfs_block_group_cache *block_group; struct btrfs_block_group_cache *block_group;
int full_scan = 0; int full_scan = 0;
int wrapped = 0; int wrapped = 0;
u64 cached_start;
WARN_ON(num_bytes < root->sectorsize); WARN_ON(num_bytes < root->sectorsize);
btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
...@@ -910,6 +936,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -910,6 +936,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
check_failed: check_failed:
search_start = find_search_start(root, &block_group, search_start = find_search_start(root, &block_group,
search_start, total_needed, data); search_start, total_needed, data);
cached_start = search_start;
btrfs_init_path(path); btrfs_init_path(path);
ins->objectid = search_start; ins->objectid = search_start;
ins->offset = 0; ins->offset = 0;
...@@ -1532,9 +1559,12 @@ int btrfs_read_block_groups(struct btrfs_root *root) ...@@ -1532,9 +1559,12 @@ int btrfs_read_block_groups(struct btrfs_root *root)
key.objectid = found_key.objectid + found_key.offset; key.objectid = found_key.objectid + found_key.offset;
btrfs_release_path(root, path); btrfs_release_path(root, path);
if (cache->item.flags & BTRFS_BLOCK_GROUP_DATA) { if (cache->item.flags & BTRFS_BLOCK_GROUP_MIXED) {
bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA;
cache->data = BTRFS_BLOCK_GROUP_MIXED;
} else if (cache->item.flags & BTRFS_BLOCK_GROUP_DATA) {
bit = BLOCK_GROUP_DATA; bit = BLOCK_GROUP_DATA;
cache->data = 1; cache->data = BTRFS_BLOCK_GROUP_DATA;
} else { } else {
bit = BLOCK_GROUP_METADATA; bit = BLOCK_GROUP_METADATA;
cache->data = 0; cache->data = 0;
......
...@@ -58,6 +58,10 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, ...@@ -58,6 +58,10 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
if (root->fs_info->extent_root == root) if (root->fs_info->extent_root == root)
is_extent = 1; is_extent = 1;
if (*level == 1 && cache_only && path->nodes[1] &&
!btrfs_buffer_defrag(path->nodes[1])) {
goto out;
}
while(*level > 0) { while(*level > 0) {
WARN_ON(*level < 0); WARN_ON(*level < 0);
WARN_ON(*level >= BTRFS_MAX_LEVEL); WARN_ON(*level >= BTRFS_MAX_LEVEL);
...@@ -116,7 +120,7 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, ...@@ -116,7 +120,7 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
WARN_ON(*level >= BTRFS_MAX_LEVEL); WARN_ON(*level >= BTRFS_MAX_LEVEL);
btrfs_clear_buffer_defrag(path->nodes[*level]); btrfs_clear_buffer_defrag(path->nodes[*level]);
out:
free_extent_buffer(path->nodes[*level]); free_extent_buffer(path->nodes[*level]);
path->nodes[*level] = NULL; path->nodes[*level] = NULL;
*level += 1; *level += 1;
......
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