mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-25 02:09:42 +00:00
Btrfs: Optimize allocations as we need to mix data and metadata into one group
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
a273208edd
commit
f84a8b362d
3 changed files with 43 additions and 7 deletions
|
@ -279,6 +279,8 @@ struct btrfs_csum_item {
|
|||
|
||||
|
||||
#define BTRFS_BLOCK_GROUP_DATA 1
|
||||
#define BTRFS_BLOCK_GROUP_MIXED 2
|
||||
|
||||
struct btrfs_block_group_item {
|
||||
__le64 used;
|
||||
u8 flags;
|
||||
|
|
|
@ -168,11 +168,13 @@ static u64 find_search_start(struct btrfs_root *root,
|
|||
u64 last;
|
||||
u64 start = 0;
|
||||
u64 end = 0;
|
||||
int wrapped = 0;
|
||||
|
||||
again:
|
||||
ret = cache_block_group(root, cache);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
last = max(search_start, cache->key.objectid);
|
||||
|
||||
while(1) {
|
||||
|
@ -195,8 +197,15 @@ static u64 find_search_start(struct btrfs_root *root,
|
|||
|
||||
new_group:
|
||||
last = cache->key.objectid + cache->key.offset;
|
||||
wrapped:
|
||||
cache = btrfs_lookup_block_group(root->fs_info, last);
|
||||
if (!cache) {
|
||||
if (!wrapped) {
|
||||
wrapped = 1;
|
||||
last = search_start;
|
||||
data = BTRFS_BLOCK_GROUP_MIXED;
|
||||
goto wrapped;
|
||||
}
|
||||
return search_start;
|
||||
}
|
||||
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,
|
|||
block_group_cache = &info->block_group_cache;
|
||||
|
||||
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;
|
||||
else
|
||||
bit = BLOCK_GROUP_METADATA;
|
||||
|
@ -246,14 +257,16 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
|
|||
if (search_start) {
|
||||
struct btrfs_block_group_cache *shint;
|
||||
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);
|
||||
if (used < div_factor(shint->key.offset, factor)) {
|
||||
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);
|
||||
if (used < div_factor(hint->key.offset, factor)) {
|
||||
return hint;
|
||||
|
@ -592,11 +605,15 @@ static int update_block_group(struct btrfs_trans_handle *trans,
|
|||
if (data) {
|
||||
bit_to_clear = BLOCK_GROUP_METADATA;
|
||||
bit_to_set = BLOCK_GROUP_DATA;
|
||||
cache->item.flags &=
|
||||
~BTRFS_BLOCK_GROUP_MIXED;
|
||||
cache->item.flags |=
|
||||
BTRFS_BLOCK_GROUP_DATA;
|
||||
} else {
|
||||
bit_to_clear = BLOCK_GROUP_DATA;
|
||||
bit_to_set = BLOCK_GROUP_METADATA;
|
||||
cache->item.flags &=
|
||||
~BTRFS_BLOCK_GROUP_MIXED;
|
||||
cache->item.flags &=
|
||||
~BTRFS_BLOCK_GROUP_DATA;
|
||||
}
|
||||
|
@ -606,6 +623,14 @@ static int update_block_group(struct btrfs_trans_handle *trans,
|
|||
set_extent_bits(&info->block_group_cache,
|
||||
start, end, bit_to_set,
|
||||
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;
|
||||
} else {
|
||||
|
@ -886,6 +911,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
|||
struct btrfs_block_group_cache *block_group;
|
||||
int full_scan = 0;
|
||||
int wrapped = 0;
|
||||
u64 cached_start;
|
||||
|
||||
WARN_ON(num_bytes < root->sectorsize);
|
||||
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
|
|||
check_failed:
|
||||
search_start = find_search_start(root, &block_group,
|
||||
search_start, total_needed, data);
|
||||
cached_start = search_start;
|
||||
btrfs_init_path(path);
|
||||
ins->objectid = search_start;
|
||||
ins->offset = 0;
|
||||
|
@ -1532,9 +1559,12 @@ int btrfs_read_block_groups(struct btrfs_root *root)
|
|||
key.objectid = found_key.objectid + found_key.offset;
|
||||
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;
|
||||
cache->data = 1;
|
||||
cache->data = BTRFS_BLOCK_GROUP_DATA;
|
||||
} else {
|
||||
bit = BLOCK_GROUP_METADATA;
|
||||
cache->data = 0;
|
||||
|
|
|
@ -58,6 +58,10 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
|
|||
if (root->fs_info->extent_root == root)
|
||||
is_extent = 1;
|
||||
|
||||
if (*level == 1 && cache_only && path->nodes[1] &&
|
||||
!btrfs_buffer_defrag(path->nodes[1])) {
|
||||
goto out;
|
||||
}
|
||||
while(*level > 0) {
|
||||
WARN_ON(*level < 0);
|
||||
WARN_ON(*level >= BTRFS_MAX_LEVEL);
|
||||
|
@ -116,7 +120,7 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
|
|||
WARN_ON(*level >= BTRFS_MAX_LEVEL);
|
||||
|
||||
btrfs_clear_buffer_defrag(path->nodes[*level]);
|
||||
|
||||
out:
|
||||
free_extent_buffer(path->nodes[*level]);
|
||||
path->nodes[*level] = NULL;
|
||||
*level += 1;
|
||||
|
|
Loading…
Reference in a new issue