|
@@ -1069,11 +1069,11 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|
|
*/
|
|
|
static struct tree_mod_elem *
|
|
|
__tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info,
|
|
|
- struct btrfs_root *root, u64 time_seq)
|
|
|
+ struct extent_buffer *eb_root, u64 time_seq)
|
|
|
{
|
|
|
struct tree_mod_elem *tm;
|
|
|
struct tree_mod_elem *found = NULL;
|
|
|
- u64 root_logical = root->node->start;
|
|
|
+ u64 root_logical = eb_root->start;
|
|
|
int looped = 0;
|
|
|
|
|
|
if (!time_seq)
|
|
@@ -1107,7 +1107,6 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info,
|
|
|
|
|
|
found = tm;
|
|
|
root_logical = tm->old_root.logical;
|
|
|
- BUG_ON(root_logical == root->node->start);
|
|
|
looped = 1;
|
|
|
}
|
|
|
|
|
@@ -1245,30 +1244,31 @@ static inline struct extent_buffer *
|
|
|
get_old_root(struct btrfs_root *root, u64 time_seq)
|
|
|
{
|
|
|
struct tree_mod_elem *tm;
|
|
|
- struct extent_buffer *eb;
|
|
|
+ struct extent_buffer *eb = NULL;
|
|
|
+ struct extent_buffer *eb_root;
|
|
|
struct extent_buffer *old;
|
|
|
struct tree_mod_root *old_root = NULL;
|
|
|
u64 old_generation = 0;
|
|
|
u64 logical;
|
|
|
u32 blocksize;
|
|
|
|
|
|
- eb = btrfs_read_lock_root_node(root);
|
|
|
- tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
|
|
|
+ eb_root = btrfs_read_lock_root_node(root);
|
|
|
+ tm = __tree_mod_log_oldest_root(root->fs_info, eb_root, time_seq);
|
|
|
if (!tm)
|
|
|
- return root->node;
|
|
|
+ return eb_root;
|
|
|
|
|
|
if (tm->op == MOD_LOG_ROOT_REPLACE) {
|
|
|
old_root = &tm->old_root;
|
|
|
old_generation = tm->generation;
|
|
|
logical = old_root->logical;
|
|
|
} else {
|
|
|
- logical = root->node->start;
|
|
|
+ logical = eb_root->start;
|
|
|
}
|
|
|
|
|
|
tm = tree_mod_log_search(root->fs_info, logical, time_seq);
|
|
|
if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
|
|
|
- btrfs_tree_read_unlock(root->node);
|
|
|
- free_extent_buffer(root->node);
|
|
|
+ btrfs_tree_read_unlock(eb_root);
|
|
|
+ free_extent_buffer(eb_root);
|
|
|
blocksize = btrfs_level_size(root, old_root->level);
|
|
|
old = read_tree_block(root, logical, blocksize, 0);
|
|
|
if (!old) {
|
|
@@ -1280,13 +1280,13 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
|
|
|
free_extent_buffer(old);
|
|
|
}
|
|
|
} else if (old_root) {
|
|
|
- btrfs_tree_read_unlock(root->node);
|
|
|
- free_extent_buffer(root->node);
|
|
|
+ btrfs_tree_read_unlock(eb_root);
|
|
|
+ free_extent_buffer(eb_root);
|
|
|
eb = alloc_dummy_extent_buffer(logical, root->nodesize);
|
|
|
} else {
|
|
|
- eb = btrfs_clone_extent_buffer(root->node);
|
|
|
- btrfs_tree_read_unlock(root->node);
|
|
|
- free_extent_buffer(root->node);
|
|
|
+ eb = btrfs_clone_extent_buffer(eb_root);
|
|
|
+ btrfs_tree_read_unlock(eb_root);
|
|
|
+ free_extent_buffer(eb_root);
|
|
|
}
|
|
|
|
|
|
if (!eb)
|
|
@@ -1296,7 +1296,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
|
|
|
if (old_root) {
|
|
|
btrfs_set_header_bytenr(eb, eb->start);
|
|
|
btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV);
|
|
|
- btrfs_set_header_owner(eb, root->root_key.objectid);
|
|
|
+ btrfs_set_header_owner(eb, btrfs_header_owner(eb_root));
|
|
|
btrfs_set_header_level(eb, old_root->level);
|
|
|
btrfs_set_header_generation(eb, old_generation);
|
|
|
}
|
|
@@ -1313,15 +1313,15 @@ int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq)
|
|
|
{
|
|
|
struct tree_mod_elem *tm;
|
|
|
int level;
|
|
|
+ struct extent_buffer *eb_root = btrfs_root_node(root);
|
|
|
|
|
|
- tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
|
|
|
+ tm = __tree_mod_log_oldest_root(root->fs_info, eb_root, time_seq);
|
|
|
if (tm && tm->op == MOD_LOG_ROOT_REPLACE) {
|
|
|
level = tm->old_root.level;
|
|
|
} else {
|
|
|
- rcu_read_lock();
|
|
|
- level = btrfs_header_level(root->node);
|
|
|
- rcu_read_unlock();
|
|
|
+ level = btrfs_header_level(eb_root);
|
|
|
}
|
|
|
+ free_extent_buffer(eb_root);
|
|
|
|
|
|
return level;
|
|
|
}
|