Commit 257d0ce3 authored by Chris Mason's avatar Chris Mason

Btrfs: Allow large data extents in a single file to span into metadata block groups

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 09be207d
...@@ -168,6 +168,7 @@ static u64 find_search_start(struct btrfs_root *root, ...@@ -168,6 +168,7 @@ 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;
u64 cache_miss = 0;
int wrapped = 0; int wrapped = 0;
again: again:
...@@ -181,14 +182,20 @@ static u64 find_search_start(struct btrfs_root *root, ...@@ -181,14 +182,20 @@ static u64 find_search_start(struct btrfs_root *root,
ret = find_first_extent_bit(&root->fs_info->free_space_cache, ret = find_first_extent_bit(&root->fs_info->free_space_cache,
last, &start, &end, EXTENT_DIRTY); last, &start, &end, EXTENT_DIRTY);
if (ret) { if (ret) {
if (!cache_miss)
cache_miss = last;
goto new_group; goto new_group;
} }
start = max(last, start); start = max(last, start);
last = end + 1; last = end + 1;
if (end + 1 - start < num) if (last - start < num) {
if (last == cache->key.objectid + cache->key.offset)
cache_miss = start;
continue; continue;
if (start + num >= cache->key.objectid + cache->key.offset) }
if (data != BTRFS_BLOCK_GROUP_MIXED &&
start + num >= cache->key.objectid + cache->key.offset)
goto new_group; goto new_group;
return start; return start;
} }
...@@ -208,13 +215,22 @@ static u64 find_search_start(struct btrfs_root *root, ...@@ -208,13 +215,22 @@ static u64 find_search_start(struct btrfs_root *root,
} }
return search_start; return search_start;
} }
if (cache_miss && !cache->cached) {
cache_block_group(root, cache);
last = cache_miss;
cache = btrfs_lookup_block_group(root->fs_info, last);
}
cache = btrfs_find_block_group(root, cache, last, data, 0); cache = btrfs_find_block_group(root, cache, last, data, 0);
*cache_ret = cache; *cache_ret = cache;
cache_miss = 0;
goto again; goto again;
} }
static u64 div_factor(u64 num, int factor) static u64 div_factor(u64 num, int factor)
{ {
if (factor == 10)
return num;
num *= factor; num *= factor;
do_div(num, 10); do_div(num, 10);
return num; return num;
...@@ -247,9 +263,10 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -247,9 +263,10 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
if (!owner) if (!owner)
factor = 8; factor = 8;
if (data == BTRFS_BLOCK_GROUP_MIXED) if (data == BTRFS_BLOCK_GROUP_MIXED) {
bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA; bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA;
else if (data) factor = 10;
} else if (data)
bit = BLOCK_GROUP_DATA; bit = BLOCK_GROUP_DATA;
else else
bit = BLOCK_GROUP_METADATA; bit = BLOCK_GROUP_METADATA;
...@@ -918,6 +935,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -918,6 +935,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
level = btrfs_header_level(root->node); level = btrfs_header_level(root->node);
if (num_bytes >= 96 * 1024 * 1024 && hint_byte) {
data = BTRFS_BLOCK_GROUP_MIXED;
}
if (search_end == (u64)-1) if (search_end == (u64)-1)
search_end = btrfs_super_total_bytes(&info->super_copy); search_end = btrfs_super_total_bytes(&info->super_copy);
if (hint_byte) { if (hint_byte) {
...@@ -937,6 +958,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -937,6 +958,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
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; 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;
...@@ -1021,7 +1043,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1021,7 +1043,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
start_found = 1; start_found = 1;
last_byte = key.objectid + key.offset; last_byte = key.objectid + key.offset;
if (!full_scan && last_byte >= block_group->key.objectid + if (!full_scan && data != BTRFS_BLOCK_GROUP_MIXED &&
last_byte >= block_group->key.objectid +
block_group->key.offset) { block_group->key.offset) {
btrfs_release_path(root, path); btrfs_release_path(root, path);
search_start = block_group->key.objectid + search_start = block_group->key.objectid +
...@@ -1042,7 +1065,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1042,7 +1065,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
if (ins->objectid + num_bytes >= search_end) if (ins->objectid + num_bytes >= search_end)
goto enospc; goto enospc;
if (!full_scan && ins->objectid + num_bytes >= block_group-> if (!full_scan && data != BTRFS_BLOCK_GROUP_MIXED &&
ins->objectid + num_bytes >= block_group->
key.objectid + block_group->key.offset) { key.objectid + block_group->key.offset) {
search_start = block_group->key.objectid + search_start = block_group->key.objectid +
block_group->key.offset; block_group->key.offset;
......
...@@ -439,6 +439,12 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, ...@@ -439,6 +439,12 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
struct btrfs_file_extent_item); struct btrfs_file_extent_item);
found_type = btrfs_file_extent_type(leaf, extent); found_type = btrfs_file_extent_type(leaf, extent);
if (found_type == BTRFS_FILE_EXTENT_REG) { if (found_type == BTRFS_FILE_EXTENT_REG) {
extent_end =
btrfs_file_extent_disk_bytenr(leaf,
extent);
if (extent_end)
*hint_byte = extent_end;
extent_end = key.offset + extent_end = key.offset +
btrfs_file_extent_num_bytes(leaf, extent); btrfs_file_extent_num_bytes(leaf, extent);
found_extent = 1; found_extent = 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