Btrfs: more block allocator work
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
9078a3e1e4
commit
cd1bc4653d
|
@ -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 {
|
||||||
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)
|
||||||
}
|
}
|
||||||
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
|
||||||
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,
|
||||||
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,
|
||||||
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
|
||||||
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
|
||||||
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 @@ check_pending:
|
||||||
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 @@ check_pending:
|
||||||
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)
|
||||||
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 @@ err:
|
||||||
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,
|
||||||
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)
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue