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

Btrfs: more block allocator work

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 9078a3e1
...@@ -250,6 +250,8 @@ struct btrfs_block_group_item { ...@@ -250,6 +250,8 @@ struct btrfs_block_group_item {
struct btrfs_block_group_cache { struct btrfs_block_group_cache {
struct btrfs_key key; struct btrfs_key key;
struct btrfs_block_group_item item; struct btrfs_block_group_item item;
u64 first_free;
u64 last_alloc;
}; };
struct crypto_hash; struct crypto_hash;
...@@ -257,7 +259,7 @@ struct btrfs_fs_info { ...@@ -257,7 +259,7 @@ struct btrfs_fs_info {
struct btrfs_root *extent_root; struct btrfs_root *extent_root;
struct btrfs_root *tree_root; struct btrfs_root *tree_root;
struct btrfs_root *dev_root; struct btrfs_root *dev_root;
struct btrfs_key last_insert; struct btrfs_block_group_cache *block_group_cache;
struct radix_tree_root fs_roots_radix; struct radix_tree_root fs_roots_radix;
struct radix_tree_root pending_del_radix; struct radix_tree_root pending_del_radix;
struct radix_tree_root pinned_radix; struct radix_tree_root pinned_radix;
......
...@@ -558,7 +558,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -558,7 +558,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
} }
mutex_init(&fs_info->trans_mutex); mutex_init(&fs_info->trans_mutex);
mutex_init(&fs_info->fs_mutex); mutex_init(&fs_info->fs_mutex);
memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); fs_info->block_group_cache = NULL;
__setup_root(sb->s_blocksize, dev_root, __setup_root(sb->s_blocksize, dev_root,
fs_info, BTRFS_DEV_TREE_OBJECTID); fs_info, BTRFS_DEV_TREE_OBJECTID);
......
...@@ -12,6 +12,63 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct ...@@ -12,6 +12,63 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
static int del_pending_extents(struct btrfs_trans_handle *trans, struct static int del_pending_extents(struct btrfs_trans_handle *trans, struct
btrfs_root *extent_root); btrfs_root *extent_root);
static int find_search_start(struct btrfs_root *root, int data)
{
struct btrfs_block_group_cache *cache[8];
struct btrfs_fs_info *info = root->fs_info;
u64 used;
u64 last;
int i;
int ret;
cache[0] = info->block_group_cache;
if (!cache[0])
goto find_new;
used = btrfs_block_group_used(&cache[0]->item);
if (used < (cache[0]->key.offset * 3 / 2))
return 0;
find_new:
last = 0;
while(1) {
ret = radix_tree_gang_lookup_tag(&info->block_group_radix,
(void **)cache,
last, ARRAY_SIZE(cache),
BTRFS_BLOCK_GROUP_DIRTY);
if (!ret)
break;
for (i = 0; i < ret; i++) {
used = btrfs_block_group_used(&cache[i]->item);
if (used < (cache[i]->key.offset * 3 / 2)) {
info->block_group_cache = cache[i];
cache[i]->last_alloc = cache[i]->first_free;
return 0;
}
last = cache[i]->key.objectid +
cache[i]->key.offset - 1;
}
}
last = 0;
while(1) {
ret = radix_tree_gang_lookup(&info->block_group_radix,
(void **)cache,
last, ARRAY_SIZE(cache));
if (!ret)
break;
for (i = 0; i < ret; i++) {
used = btrfs_block_group_used(&cache[i]->item);
if (used < (cache[i]->key.offset * 3 / 2)) {
info->block_group_cache = cache[i];
cache[i]->last_alloc = cache[i]->first_free;
return 0;
}
last = cache[i]->key.objectid +
cache[i]->key.offset - 1;
}
}
info->block_group_cache = NULL;
return 0;
}
int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 blocknr, u64 num_blocks) u64 blocknr, u64 num_blocks)
...@@ -205,8 +262,11 @@ static int update_block_group(struct btrfs_trans_handle *trans, ...@@ -205,8 +262,11 @@ static int update_block_group(struct btrfs_trans_handle *trans,
while(total) { while(total) {
ret = radix_tree_gang_lookup(&info->block_group_radix, ret = radix_tree_gang_lookup(&info->block_group_radix,
(void **)&cache, blocknr, 1); (void **)&cache, blocknr, 1);
if (!ret) if (!ret) {
printk(KERN_CRIT "blocknr %Lu lookup failed\n",
blocknr);
return -1; return -1;
}
block_in_group = blocknr - cache->key.objectid; block_in_group = blocknr - cache->key.objectid;
WARN_ON(block_in_group > cache->key.offset); WARN_ON(block_in_group > cache->key.offset);
radix_tree_tag_set(&info->block_group_radix, radix_tree_tag_set(&info->block_group_radix,
...@@ -217,10 +277,15 @@ static int update_block_group(struct btrfs_trans_handle *trans, ...@@ -217,10 +277,15 @@ static int update_block_group(struct btrfs_trans_handle *trans,
num = min(total, cache->key.offset - block_in_group); num = min(total, cache->key.offset - block_in_group);
total -= num; total -= num;
blocknr += num; blocknr += num;
if (alloc) if (alloc) {
old_val += num; old_val += num;
else if (blocknr > cache->last_alloc)
cache->last_alloc = blocknr;
} else {
old_val -= num; old_val -= num;
if (blocknr < cache->first_free)
cache->first_free = blocknr;
}
btrfs_set_block_group_used(&cache->item, old_val); btrfs_set_block_group_used(&cache->item, old_val);
} }
return 0; return 0;
...@@ -246,9 +311,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct ...@@ -246,9 +311,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
clear_radix_bit(pinned_radix, gang[i]); clear_radix_bit(pinned_radix, gang[i]);
} }
} }
if (root->fs_info->last_insert.objectid > first) root->fs_info->block_group_cache = NULL;
root->fs_info->last_insert.objectid = first;
root->fs_info->last_insert.offset = 0;
return 0; return 0;
} }
...@@ -466,8 +529,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -466,8 +529,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
num_blocks = 1; num_blocks = 1;
total_needed = min(level + 2, BTRFS_MAX_LEVEL) * 3; total_needed = min(level + 2, BTRFS_MAX_LEVEL) * 3;
} }
if (info->last_insert.objectid > search_start) find_search_start(root, 0);
search_start = info->last_insert.objectid; if (info->block_group_cache &&
info->block_group_cache->last_alloc > search_start)
search_start = info->block_group_cache->last_alloc;
check_failed: check_failed:
btrfs_init_path(path); btrfs_init_path(path);
...@@ -567,8 +632,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -567,8 +632,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
total_found < total_needed) { total_found < total_needed) {
nr = total_needed - total_found - 1; nr = total_needed - total_found - 1;
BUG_ON(nr < 0); BUG_ON(nr < 0);
root->fs_info->extent_tree_prealloc[nr] = info->extent_tree_prealloc[nr] = test_block;
test_block;
total_found++; total_found++;
test_block++; test_block++;
} }
...@@ -576,9 +640,14 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -576,9 +640,14 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
search_start = test_block; search_start = test_block;
goto check_failed; goto check_failed;
} }
root->fs_info->extent_tree_prealloc_nr = total_found; info->extent_tree_prealloc_nr = total_found;
}
ret = radix_tree_gang_lookup(&info->block_group_radix,
(void **)&info->block_group_cache,
ins->objectid, 1);
if (ret) {
info->block_group_cache->last_alloc = ins->objectid;
} }
root->fs_info->last_insert.objectid = ins->objectid;
ins->offset = num_blocks; ins->offset = num_blocks;
btrfs_free_path(path); btrfs_free_path(path);
return 0; return 0;
...@@ -915,6 +984,8 @@ int btrfs_read_block_groups(struct btrfs_root *root) ...@@ -915,6 +984,8 @@ int btrfs_read_block_groups(struct btrfs_root *root)
struct btrfs_block_group_item); struct btrfs_block_group_item);
memcpy(&cache->item, bi, sizeof(*bi)); memcpy(&cache->item, bi, sizeof(*bi));
memcpy(&cache->key, &found_key, sizeof(found_key)); memcpy(&cache->key, &found_key, sizeof(found_key));
cache->last_alloc = 0;
cache->first_free = 0;
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);
ret = radix_tree_insert(&root->fs_info->block_group_radix, ret = radix_tree_insert(&root->fs_info->block_group_radix,
......
...@@ -223,6 +223,7 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, ...@@ -223,6 +223,7 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
btrfs_update_inode(trans, root, dir); btrfs_update_inode(trans, root, dir);
drop_nlink(dentry->d_inode); drop_nlink(dentry->d_inode);
btrfs_update_inode(trans, root, dentry->d_inode); btrfs_update_inode(trans, root, dentry->d_inode);
dir->i_sb->s_dirt = 1;
} }
return ret; return ret;
} }
...@@ -411,6 +412,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, ...@@ -411,6 +412,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
error: error:
btrfs_release_path(root, path); btrfs_release_path(root, path);
btrfs_free_path(path); btrfs_free_path(path);
inode->i_sb->s_dirt = 1;
return ret; return ret;
} }
...@@ -935,6 +937,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -935,6 +937,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
goto out_fail; goto out_fail;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
drop_on_err = 0; drop_on_err = 0;
dir->i_sb->s_dirt = 1;
out_fail: out_fail:
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
......
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