Commit abed4aaa authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

btrfs: track the csum, extent, and free space trees in a rb tree

In the future we are going to have multiple copies of these trees.  To
facilitate this we need a way to lookup the different roots we are
looking for.  Handle this by adding a global root rb tree that is
indexed on the root->root_key.  Then instead of loading the roots at
mount time with individually targeted keys, simply search the tree_root
for anything with the specific objectid we want.  This will make it
straightforward to support both old style and new style file systems.
Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 7fcf8a00
...@@ -623,20 +623,21 @@ enum btrfs_exclusive_operation { ...@@ -623,20 +623,21 @@ enum btrfs_exclusive_operation {
struct btrfs_fs_info { struct btrfs_fs_info {
u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
unsigned long flags; unsigned long flags;
struct btrfs_root *_extent_root;
struct btrfs_root *tree_root; struct btrfs_root *tree_root;
struct btrfs_root *chunk_root; struct btrfs_root *chunk_root;
struct btrfs_root *dev_root; struct btrfs_root *dev_root;
struct btrfs_root *fs_root; struct btrfs_root *fs_root;
struct btrfs_root *_csum_root;
struct btrfs_root *quota_root; struct btrfs_root *quota_root;
struct btrfs_root *uuid_root; struct btrfs_root *uuid_root;
struct btrfs_root *_free_space_root;
struct btrfs_root *data_reloc_root; struct btrfs_root *data_reloc_root;
/* the log root tree is a directory of all the other log roots */ /* the log root tree is a directory of all the other log roots */
struct btrfs_root *log_root_tree; struct btrfs_root *log_root_tree;
/* The tree that holds the global roots (csum, extent, etc) */
rwlock_t global_root_lock;
struct rb_root global_root_tree;
spinlock_t fs_roots_radix_lock; spinlock_t fs_roots_radix_lock;
struct radix_tree_root fs_roots_radix; struct radix_tree_root fs_roots_radix;
...@@ -1129,6 +1130,8 @@ struct btrfs_qgroup_swapped_blocks { ...@@ -1129,6 +1130,8 @@ struct btrfs_qgroup_swapped_blocks {
* and for the extent tree extent_root root. * and for the extent tree extent_root root.
*/ */
struct btrfs_root { struct btrfs_root {
struct rb_node rb_node;
struct extent_buffer *node; struct extent_buffer *node;
struct extent_buffer *commit_root; struct extent_buffer *commit_root;
......
This diff is collapsed.
...@@ -71,6 +71,12 @@ struct btrfs_root *btrfs_get_new_fs_root(struct btrfs_fs_info *fs_info, ...@@ -71,6 +71,12 @@ struct btrfs_root *btrfs_get_new_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_root *btrfs_get_fs_root_commit_root(struct btrfs_fs_info *fs_info, struct btrfs_root *btrfs_get_fs_root_commit_root(struct btrfs_fs_info *fs_info,
struct btrfs_path *path, struct btrfs_path *path,
u64 objectid); u64 objectid);
int btrfs_global_root_insert(struct btrfs_root *root);
void btrfs_global_root_delete(struct btrfs_root *root);
struct btrfs_root *btrfs_global_root(struct btrfs_fs_info *fs_info,
struct btrfs_key *key);
struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info, u64 bytenr);
struct btrfs_root *btrfs_extent_root(struct btrfs_fs_info *fs_info, u64 bytenr);
void btrfs_free_fs_info(struct btrfs_fs_info *fs_info); void btrfs_free_fs_info(struct btrfs_fs_info *fs_info);
int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info); int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info);
...@@ -103,18 +109,6 @@ static inline struct btrfs_root *btrfs_grab_root(struct btrfs_root *root) ...@@ -103,18 +109,6 @@ static inline struct btrfs_root *btrfs_grab_root(struct btrfs_root *root)
return NULL; return NULL;
} }
static inline struct btrfs_root *btrfs_extent_root(struct btrfs_fs_info *fs_info,
u64 bytenr)
{
return fs_info->_extent_root;
}
static inline struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info,
u64 bytenr)
{
return fs_info->_csum_root;
}
static inline struct btrfs_root *btrfs_block_group_root(struct btrfs_fs_info *fs_info) static inline struct btrfs_root *btrfs_block_group_root(struct btrfs_fs_info *fs_info)
{ {
return btrfs_extent_root(fs_info, 0); return btrfs_extent_root(fs_info, 0);
......
...@@ -2947,6 +2947,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, ...@@ -2947,6 +2947,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
bool skinny_metadata = btrfs_fs_incompat(info, SKINNY_METADATA); bool skinny_metadata = btrfs_fs_incompat(info, SKINNY_METADATA);
extent_root = btrfs_extent_root(info, bytenr); extent_root = btrfs_extent_root(info, bytenr);
ASSERT(extent_root);
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path)
......
...@@ -19,7 +19,13 @@ static int __add_block_group_free_space(struct btrfs_trans_handle *trans, ...@@ -19,7 +19,13 @@ static int __add_block_group_free_space(struct btrfs_trans_handle *trans,
static struct btrfs_root *btrfs_free_space_root( static struct btrfs_root *btrfs_free_space_root(
struct btrfs_block_group *block_group) struct btrfs_block_group *block_group)
{ {
return block_group->fs_info->_free_space_root; struct btrfs_key key = {
.objectid = BTRFS_FREE_SPACE_TREE_OBJECTID,
.type = BTRFS_ROOT_ITEM_KEY,
.offset = 0,
};
return btrfs_global_root(block_group->fs_info, &key);
} }
void set_free_space_tree_thresholds(struct btrfs_block_group *cache) void set_free_space_tree_thresholds(struct btrfs_block_group *cache)
...@@ -1164,7 +1170,11 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info) ...@@ -1164,7 +1170,11 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
ret = PTR_ERR(free_space_root); ret = PTR_ERR(free_space_root);
goto abort; goto abort;
} }
fs_info->_free_space_root = free_space_root; ret = btrfs_global_root_insert(free_space_root);
if (ret) {
btrfs_put_root(free_space_root);
goto abort;
}
node = rb_first(&fs_info->block_group_cache_tree); node = rb_first(&fs_info->block_group_cache_tree);
while (node) { while (node) {
...@@ -1239,7 +1249,12 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info) ...@@ -1239,7 +1249,12 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
{ {
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_root *tree_root = fs_info->tree_root;
struct btrfs_root *free_space_root = fs_info->_free_space_root; struct btrfs_key key = {
.objectid = BTRFS_FREE_SPACE_TREE_OBJECTID,
.type = BTRFS_ROOT_ITEM_KEY,
.offset = 0,
};
struct btrfs_root *free_space_root = btrfs_global_root(fs_info, &key);
int ret; int ret;
trans = btrfs_start_transaction(tree_root, 0); trans = btrfs_start_transaction(tree_root, 0);
...@@ -1248,7 +1263,6 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info) ...@@ -1248,7 +1263,6 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE); btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE);
btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID); btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
fs_info->_free_space_root = NULL;
ret = clear_free_space_tree(trans, free_space_root); ret = clear_free_space_tree(trans, free_space_root);
if (ret) if (ret)
...@@ -1258,6 +1272,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info) ...@@ -1258,6 +1272,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
if (ret) if (ret)
goto abort; goto abort;
btrfs_global_root_delete(free_space_root);
list_del(&free_space_root->dirty_list); list_del(&free_space_root->dirty_list);
btrfs_tree_lock(free_space_root->node); btrfs_tree_lock(free_space_root->node);
......
...@@ -204,6 +204,7 @@ void btrfs_free_dummy_root(struct btrfs_root *root) ...@@ -204,6 +204,7 @@ void btrfs_free_dummy_root(struct btrfs_root *root)
/* Will be freed by btrfs_free_fs_roots */ /* Will be freed by btrfs_free_fs_roots */
if (WARN_ON(test_bit(BTRFS_ROOT_IN_RADIX, &root->state))) if (WARN_ON(test_bit(BTRFS_ROOT_IN_RADIX, &root->state)))
return; return;
btrfs_global_root_delete(root);
btrfs_put_root(root); btrfs_put_root(root);
} }
......
...@@ -1036,7 +1036,10 @@ int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize) ...@@ -1036,7 +1036,10 @@ int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
goto out; goto out;
} }
root->fs_info->_extent_root = root; root->root_key.objectid = BTRFS_EXTENT_TREE_OBJECTID;
root->root_key.type = BTRFS_ROOT_ITEM_KEY;
root->root_key.offset = 0;
btrfs_global_root_insert(root);
ret = test_extents(cache); ret = test_extents(cache);
if (ret) if (ret)
......
...@@ -446,7 +446,10 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize, ...@@ -446,7 +446,10 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
btrfs_set_super_compat_ro_flags(root->fs_info->super_copy, btrfs_set_super_compat_ro_flags(root->fs_info->super_copy,
BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE); BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE);
root->fs_info->_free_space_root = root; root->root_key.objectid = BTRFS_FREE_SPACE_TREE_OBJECTID;
root->root_key.type = BTRFS_ROOT_ITEM_KEY;
root->root_key.offset = 0;
btrfs_global_root_insert(root);
root->fs_info->tree_root = root; root->fs_info->tree_root = root;
root->node = alloc_test_extent_buffer(root->fs_info, nodesize); root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
......
...@@ -455,7 +455,10 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize) ...@@ -455,7 +455,10 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
} }
/* We are using this root as our extent root */ /* We are using this root as our extent root */
root->fs_info->_extent_root = root; root->root_key.objectid = BTRFS_EXTENT_TREE_OBJECTID;
root->root_key.type = BTRFS_ROOT_ITEM_KEY;
root->root_key.offset = 0;
btrfs_global_root_insert(root);
/* /*
* Some of the paths we test assume we have a filled out fs_info, so we * Some of the paths we test assume we have a filled out fs_info, so we
......
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