Commit be08c1b9 authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse

Btrfs: early metadata/data split

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 35b7e476
...@@ -1080,7 +1080,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, ...@@ -1080,7 +1080,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
int btrfs_alloc_extent(struct btrfs_trans_handle *trans, int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 owner, struct btrfs_root *root, u64 owner,
u64 num_blocks, u64 search_start, u64 num_blocks, u64 search_start,
u64 search_end, struct btrfs_key *ins); u64 search_end, struct btrfs_key *ins, int data);
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct buffer_head *buf); struct buffer_head *buf);
int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*orig_root, u64 num_blocks, u64 search_start, u64 *orig_root, u64 num_blocks, u64 search_start, u64
search_end, struct btrfs_key *ins); search_end, struct btrfs_key *ins, int data);
static int finish_current_insert(struct btrfs_trans_handle *trans, struct static int finish_current_insert(struct btrfs_trans_handle *trans, struct
btrfs_root *extent_root); btrfs_root *extent_root);
static int del_pending_extents(struct btrfs_trans_handle *trans, struct static int del_pending_extents(struct btrfs_trans_handle *trans, struct
...@@ -25,7 +25,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -25,7 +25,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
int i; int i;
int ret; int ret;
int full_search = 0; int full_search = 0;
if (hint) { if (!data && hint) {
used = btrfs_block_group_used(&hint->item); used = btrfs_block_group_used(&hint->item);
if (used < (hint->key.offset * 2) / 3) { if (used < (hint->key.offset * 2) / 3) {
return hint; return hint;
...@@ -47,6 +47,14 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -47,6 +47,14 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
if (!ret) if (!ret)
break; break;
for (i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
last = cache[i]->key.objectid +
cache[i]->key.offset;
if (!full_search && !data &&
(cache[i]->key.objectid & cache[i]->key.offset))
continue;
if (!full_search && data &&
(cache[i]->key.objectid & cache[i]->key.offset) == 0)
continue;
used = btrfs_block_group_used(&cache[i]->item); used = btrfs_block_group_used(&cache[i]->item);
if (used < (cache[i]->key.offset * 2) / 3) { if (used < (cache[i]->key.offset * 2) / 3) {
info->block_group_cache = cache[i]; info->block_group_cache = cache[i];
...@@ -57,8 +65,6 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -57,8 +65,6 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
cache[i]->key.objectid + cache[i]->key.objectid +
cache[i]->key.offset - 1, cache[i]->key.offset - 1,
BTRFS_BLOCK_GROUP_AVAIL); BTRFS_BLOCK_GROUP_AVAIL);
last = cache[i]->key.objectid +
cache[i]->key.offset;
} }
} }
last = hint_last; last = hint_last;
...@@ -70,6 +76,14 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -70,6 +76,14 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
if (!ret) if (!ret)
break; break;
for (i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
last = cache[i]->key.objectid +
cache[i]->key.offset;
if (!full_search && !data &&
(cache[i]->key.objectid & cache[i]->key.offset))
continue;
if (!full_search && data &&
(cache[i]->key.objectid & cache[i]->key.offset) == 0)
continue;
used = btrfs_block_group_used(&cache[i]->item); used = btrfs_block_group_used(&cache[i]->item);
if (used < cache[i]->key.offset) { if (used < cache[i]->key.offset) {
info->block_group_cache = cache[i]; info->block_group_cache = cache[i];
...@@ -80,8 +94,6 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -80,8 +94,6 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
cache[i]->key.objectid + cache[i]->key.objectid +
cache[i]->key.offset - 1, cache[i]->key.offset - 1,
BTRFS_BLOCK_GROUP_AVAIL); BTRFS_BLOCK_GROUP_AVAIL);
last = cache[i]->key.objectid +
cache[i]->key.offset;
} }
} }
info->block_group_cache = NULL; info->block_group_cache = NULL;
...@@ -112,7 +124,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, ...@@ -112,7 +124,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
u32 refs; u32 refs;
find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1,
&ins); &ins, 0);
path = btrfs_alloc_path(); path = btrfs_alloc_path();
BUG_ON(!path); BUG_ON(!path);
btrfs_init_path(path); btrfs_init_path(path);
...@@ -225,7 +237,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans, ...@@ -225,7 +237,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
struct btrfs_block_group_item *bi; struct btrfs_block_group_item *bi;
struct btrfs_key ins; struct btrfs_key ins;
find_free_extent(trans, extent_root, 0, 0, (u64)-1, &ins); find_free_extent(trans, extent_root, 0, 0, (u64)-1, &ins, 0);
ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
BUG_ON(ret); BUG_ON(ret);
bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
...@@ -322,10 +334,18 @@ static int update_block_group(struct btrfs_trans_handle *trans, ...@@ -322,10 +334,18 @@ static int update_block_group(struct btrfs_trans_handle *trans,
return 0; return 0;
} }
static int try_remove_page(struct address_space *mapping, unsigned long index)
{
int ret;
ret = invalidate_mapping_pages(mapping, index, index);
return ret;
}
int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
btrfs_root *root) btrfs_root *root)
{ {
unsigned long gang[8]; unsigned long gang[8];
struct inode *btree_inode = root->fs_info->btree_inode;
u64 first = 0; u64 first = 0;
int ret; int ret;
int i; int i;
...@@ -340,6 +360,9 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct ...@@ -340,6 +360,9 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
first = gang[0]; first = gang[0];
for (i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
clear_radix_bit(pinned_radix, gang[i]); clear_radix_bit(pinned_radix, gang[i]);
try_remove_page(btree_inode->i_mapping,
gang[i] << (PAGE_CACHE_SHIFT -
btree_inode->i_blkbits));
} }
} }
return 0; return 0;
...@@ -424,7 +447,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -424,7 +447,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
key.offset = num_blocks; key.offset = num_blocks;
find_free_extent(trans, root, 0, 0, (u64)-1, &ins); find_free_extent(trans, root, 0, 0, (u64)-1, &ins, 0);
path = btrfs_alloc_path(); path = btrfs_alloc_path();
BUG_ON(!path); BUG_ON(!path);
btrfs_init_path(path); btrfs_init_path(path);
...@@ -531,7 +554,7 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -531,7 +554,7 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*/ */
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*orig_root, u64 num_blocks, u64 search_start, u64 *orig_root, u64 num_blocks, u64 search_start, u64
search_end, struct btrfs_key *ins) search_end, struct btrfs_key *ins, int data)
{ {
struct btrfs_path *path; struct btrfs_path *path;
struct btrfs_key key; struct btrfs_key key;
...@@ -548,43 +571,21 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -548,43 +571,21 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
int total_found = 0; int total_found = 0;
int fill_prealloc = 0; int fill_prealloc = 0;
int level; int level;
int update_block_group = 0; struct btrfs_block_group_cache *block_group;
struct btrfs_block_group_cache *hint_block_group;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
ins->flags = 0; ins->flags = 0;
btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
level = btrfs_header_level(btrfs_buffer_header(root->node)); level = btrfs_header_level(btrfs_buffer_header(root->node));
/* find search start here */
if (0 && search_start && num_blocks) {
u64 used;
ret = radix_tree_gang_lookup(&info->block_group_radix,
(void **)&hint_block_group,
search_start, 1);
if (ret) {
used = btrfs_block_group_used(&hint_block_group->item);
if (used > (hint_block_group->key.offset * 9) / 10)
search_start = 0;
else if (search_start < hint_block_group->last_alloc)
search_start = hint_block_group->last_alloc;
} else {
search_start = 0;
}
}
if (num_blocks == 0) { if (num_blocks == 0) {
fill_prealloc = 1; fill_prealloc = 1;
num_blocks = 1; num_blocks = 1;
total_needed = (min(level + 1, BTRFS_MAX_LEVEL) + 2) * 3; total_needed = (min(level + 1, BTRFS_MAX_LEVEL) + 2) * 3;
} }
if (1 || !search_start) { block_group = btrfs_find_block_group(root, trans->block_group, data);
trans->block_group = btrfs_find_block_group(root, if (block_group->last_alloc > search_start)
trans->block_group, search_start = block_group->last_alloc;
0);
if (trans->block_group->last_alloc > search_start)
search_start = trans->block_group->last_alloc;
update_block_group = 1;
}
check_failed: check_failed:
btrfs_init_path(path); btrfs_init_path(path);
ins->objectid = search_start; ins->objectid = search_start;
...@@ -699,13 +700,13 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -699,13 +700,13 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
} }
info->extent_tree_prealloc_nr = total_found; info->extent_tree_prealloc_nr = total_found;
} }
if (update_block_group) { ret = radix_tree_gang_lookup(&info->block_group_radix,
ret = radix_tree_gang_lookup(&info->block_group_radix, (void **)&block_group,
(void **)&trans->block_group, ins->objectid, 1);
ins->objectid, 1); if (ret) {
if (ret) { block_group->last_alloc = ins->objectid;
trans->block_group->last_alloc = ins->objectid; if (!data)
} trans->block_group = block_group;
} }
ins->offset = num_blocks; ins->offset = num_blocks;
btrfs_free_path(path); btrfs_free_path(path);
...@@ -725,7 +726,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -725,7 +726,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
int btrfs_alloc_extent(struct btrfs_trans_handle *trans, int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 owner, struct btrfs_root *root, u64 owner,
u64 num_blocks, u64 search_start, u64 num_blocks, u64 search_start,
u64 search_end, struct btrfs_key *ins) u64 search_end, struct btrfs_key *ins, int data)
{ {
int ret; int ret;
int pending_ret; int pending_ret;
...@@ -755,13 +756,13 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, ...@@ -755,13 +756,13 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
} }
/* do the real allocation */ /* do the real allocation */
ret = find_free_extent(trans, root, num_blocks, search_start, ret = find_free_extent(trans, root, num_blocks, search_start,
search_end, ins); search_end, ins, data);
if (ret) if (ret)
return ret; return ret;
/* then do prealloc for the extent tree */ /* then do prealloc for the extent tree */
ret = find_free_extent(trans, root, 0, ins->objectid + ins->offset, ret = find_free_extent(trans, root, 0, ins->objectid + ins->offset,
search_end, &prealloc_key); search_end, &prealloc_key, 0);
if (ret) if (ret)
return ret; return ret;
...@@ -793,7 +794,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, ...@@ -793,7 +794,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
struct buffer_head *buf; struct buffer_head *buf;
ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, ret = btrfs_alloc_extent(trans, root, root->root_key.objectid,
1, hint, (unsigned long)-1, &ins); 1, 0, (unsigned long)-1, &ins, 0);
if (ret) { if (ret) {
BUG(); BUG();
return NULL; return NULL;
......
...@@ -1903,7 +1903,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, ...@@ -1903,7 +1903,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
if (inode->i_size >= PAGE_CACHE_SIZE || pos + count < inode->i_size || if (inode->i_size >= PAGE_CACHE_SIZE || pos + count < inode->i_size ||
pos + count - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) { pos + count - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) {
ret = btrfs_alloc_extent(trans, root, inode->i_ino, ret = btrfs_alloc_extent(trans, root, inode->i_ino,
num_blocks, 1, (u64)-1, &ins); num_blocks, 1, (u64)-1, &ins, 1);
BUG_ON(ret); BUG_ON(ret);
ret = btrfs_insert_file_extent(trans, root, inode->i_ino, ret = btrfs_insert_file_extent(trans, root, inode->i_ino,
start_pos, ins.objectid, ins.offset); start_pos, ins.objectid, ins.offset);
......
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