Loading fs/btrfs/ctree.h +3 −1 Original line number Diff line number Diff line Loading @@ -250,6 +250,8 @@ struct btrfs_block_group_item { struct btrfs_block_group_cache { struct btrfs_key key; struct btrfs_block_group_item item; u64 first_free; u64 last_alloc; }; struct crypto_hash; Loading @@ -257,7 +259,7 @@ struct btrfs_fs_info { struct btrfs_root *extent_root; struct btrfs_root *tree_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 pending_del_radix; struct radix_tree_root pinned_radix; Loading fs/btrfs/disk-io.c +1 −1 Original line number Diff line number Diff line Loading @@ -558,7 +558,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) } mutex_init(&fs_info->trans_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, fs_info, BTRFS_DEV_TREE_OBJECTID); Loading fs/btrfs/extent-tree.c +83 −12 Original line number Diff line number Diff line Loading @@ -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 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, struct btrfs_root *root, u64 blocknr, u64 num_blocks) Loading Loading @@ -205,8 +262,11 @@ static int update_block_group(struct btrfs_trans_handle *trans, while(total) { ret = radix_tree_gang_lookup(&info->block_group_radix, (void **)&cache, blocknr, 1); if (!ret) if (!ret) { printk(KERN_CRIT "blocknr %Lu lookup failed\n", blocknr); return -1; } block_in_group = blocknr - cache->key.objectid; WARN_ON(block_in_group > cache->key.offset); radix_tree_tag_set(&info->block_group_radix, Loading @@ -217,10 +277,15 @@ static int update_block_group(struct btrfs_trans_handle *trans, num = min(total, cache->key.offset - block_in_group); total -= num; blocknr += num; if (alloc) if (alloc) { old_val += num; else if (blocknr > cache->last_alloc) cache->last_alloc = blocknr; } else { old_val -= num; if (blocknr < cache->first_free) cache->first_free = blocknr; } btrfs_set_block_group_used(&cache->item, old_val); } return 0; Loading @@ -246,9 +311,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct clear_radix_bit(pinned_radix, gang[i]); } } if (root->fs_info->last_insert.objectid > first) root->fs_info->last_insert.objectid = first; root->fs_info->last_insert.offset = 0; root->fs_info->block_group_cache = NULL; return 0; } Loading Loading @@ -466,8 +529,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root num_blocks = 1; total_needed = min(level + 2, BTRFS_MAX_LEVEL) * 3; } if (info->last_insert.objectid > search_start) search_start = info->last_insert.objectid; find_search_start(root, 0); if (info->block_group_cache && info->block_group_cache->last_alloc > search_start) search_start = info->block_group_cache->last_alloc; check_failed: btrfs_init_path(path); Loading Loading @@ -567,8 +632,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root total_found < total_needed) { nr = total_needed - total_found - 1; BUG_ON(nr < 0); root->fs_info->extent_tree_prealloc[nr] = test_block; info->extent_tree_prealloc[nr] = test_block; total_found++; test_block++; } Loading @@ -576,9 +640,14 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root search_start = test_block; 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; btrfs_free_path(path); return 0; Loading Loading @@ -915,6 +984,8 @@ int btrfs_read_block_groups(struct btrfs_root *root) struct btrfs_block_group_item); memcpy(&cache->item, bi, sizeof(*bi)); memcpy(&cache->key, &found_key, sizeof(found_key)); cache->last_alloc = 0; cache->first_free = 0; key.objectid = found_key.objectid + found_key.offset; btrfs_release_path(root, path); ret = radix_tree_insert(&root->fs_info->block_group_radix, Loading fs/btrfs/super.c +3 −0 Original line number Diff line number Diff line Loading @@ -223,6 +223,7 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, btrfs_update_inode(trans, root, dir); drop_nlink(dentry->d_inode); btrfs_update_inode(trans, root, dentry->d_inode); dir->i_sb->s_dirt = 1; } return ret; } Loading Loading @@ -411,6 +412,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, error: btrfs_release_path(root, path); btrfs_free_path(path); inode->i_sb->s_dirt = 1; return ret; } Loading Loading @@ -935,6 +937,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) goto out_fail; d_instantiate(dentry, inode); drop_on_err = 0; dir->i_sb->s_dirt = 1; out_fail: btrfs_end_transaction(trans, root); Loading Loading
fs/btrfs/ctree.h +3 −1 Original line number Diff line number Diff line Loading @@ -250,6 +250,8 @@ struct btrfs_block_group_item { struct btrfs_block_group_cache { struct btrfs_key key; struct btrfs_block_group_item item; u64 first_free; u64 last_alloc; }; struct crypto_hash; Loading @@ -257,7 +259,7 @@ struct btrfs_fs_info { struct btrfs_root *extent_root; struct btrfs_root *tree_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 pending_del_radix; struct radix_tree_root pinned_radix; Loading
fs/btrfs/disk-io.c +1 −1 Original line number Diff line number Diff line Loading @@ -558,7 +558,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) } mutex_init(&fs_info->trans_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, fs_info, BTRFS_DEV_TREE_OBJECTID); Loading
fs/btrfs/extent-tree.c +83 −12 Original line number Diff line number Diff line Loading @@ -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 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, struct btrfs_root *root, u64 blocknr, u64 num_blocks) Loading Loading @@ -205,8 +262,11 @@ static int update_block_group(struct btrfs_trans_handle *trans, while(total) { ret = radix_tree_gang_lookup(&info->block_group_radix, (void **)&cache, blocknr, 1); if (!ret) if (!ret) { printk(KERN_CRIT "blocknr %Lu lookup failed\n", blocknr); return -1; } block_in_group = blocknr - cache->key.objectid; WARN_ON(block_in_group > cache->key.offset); radix_tree_tag_set(&info->block_group_radix, Loading @@ -217,10 +277,15 @@ static int update_block_group(struct btrfs_trans_handle *trans, num = min(total, cache->key.offset - block_in_group); total -= num; blocknr += num; if (alloc) if (alloc) { old_val += num; else if (blocknr > cache->last_alloc) cache->last_alloc = blocknr; } else { old_val -= num; if (blocknr < cache->first_free) cache->first_free = blocknr; } btrfs_set_block_group_used(&cache->item, old_val); } return 0; Loading @@ -246,9 +311,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct clear_radix_bit(pinned_radix, gang[i]); } } if (root->fs_info->last_insert.objectid > first) root->fs_info->last_insert.objectid = first; root->fs_info->last_insert.offset = 0; root->fs_info->block_group_cache = NULL; return 0; } Loading Loading @@ -466,8 +529,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root num_blocks = 1; total_needed = min(level + 2, BTRFS_MAX_LEVEL) * 3; } if (info->last_insert.objectid > search_start) search_start = info->last_insert.objectid; find_search_start(root, 0); if (info->block_group_cache && info->block_group_cache->last_alloc > search_start) search_start = info->block_group_cache->last_alloc; check_failed: btrfs_init_path(path); Loading Loading @@ -567,8 +632,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root total_found < total_needed) { nr = total_needed - total_found - 1; BUG_ON(nr < 0); root->fs_info->extent_tree_prealloc[nr] = test_block; info->extent_tree_prealloc[nr] = test_block; total_found++; test_block++; } Loading @@ -576,9 +640,14 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root search_start = test_block; 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; btrfs_free_path(path); return 0; Loading Loading @@ -915,6 +984,8 @@ int btrfs_read_block_groups(struct btrfs_root *root) struct btrfs_block_group_item); memcpy(&cache->item, bi, sizeof(*bi)); memcpy(&cache->key, &found_key, sizeof(found_key)); cache->last_alloc = 0; cache->first_free = 0; key.objectid = found_key.objectid + found_key.offset; btrfs_release_path(root, path); ret = radix_tree_insert(&root->fs_info->block_group_radix, Loading
fs/btrfs/super.c +3 −0 Original line number Diff line number Diff line Loading @@ -223,6 +223,7 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, btrfs_update_inode(trans, root, dir); drop_nlink(dentry->d_inode); btrfs_update_inode(trans, root, dentry->d_inode); dir->i_sb->s_dirt = 1; } return ret; } Loading Loading @@ -411,6 +412,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, error: btrfs_release_path(root, path); btrfs_free_path(path); inode->i_sb->s_dirt = 1; return ret; } Loading Loading @@ -935,6 +937,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) goto out_fail; d_instantiate(dentry, inode); drop_on_err = 0; dir->i_sb->s_dirt = 1; out_fail: btrfs_end_transaction(trans, root); Loading