Btrfs: tree mod log's old roots could still be part of the tree
Tree mod log treated old root buffers as always empty buffers when starting the rewind operations. However, the old root may still be part of the current tree at a lower level, with still some valid entries. Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
This commit is contained in:
parent
ba1bfbd592
commit
834328a849
1 changed files with 21 additions and 4 deletions
|
@ -1239,6 +1239,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
|
|||
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);
|
||||
|
@ -1254,12 +1255,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
|
|||
}
|
||||
|
||||
tm = tree_mod_log_search(root->fs_info, logical, time_seq);
|
||||
if (old_root)
|
||||
if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
|
||||
btrfs_tree_read_unlock(root->node);
|
||||
free_extent_buffer(root->node);
|
||||
blocksize = btrfs_level_size(root, old_root->level);
|
||||
eb = read_tree_block(root, logical, blocksize, 0);
|
||||
if (!eb) {
|
||||
pr_warn("btrfs: failed to read tree block %llu from get_old_root\n",
|
||||
logical);
|
||||
WARN_ON(1);
|
||||
} else {
|
||||
eb = btrfs_clone_extent_buffer(eb);
|
||||
}
|
||||
} else if (old_root) {
|
||||
btrfs_tree_read_unlock(root->node);
|
||||
free_extent_buffer(root->node);
|
||||
eb = alloc_dummy_extent_buffer(logical, root->nodesize);
|
||||
else
|
||||
} else {
|
||||
eb = btrfs_clone_extent_buffer(root->node);
|
||||
btrfs_tree_read_unlock(root->node);
|
||||
free_extent_buffer(root->node);
|
||||
btrfs_tree_read_unlock(root->node);
|
||||
free_extent_buffer(root->node);
|
||||
}
|
||||
|
||||
if (!eb)
|
||||
return NULL;
|
||||
btrfs_tree_read_lock(eb);
|
||||
|
|
Loading…
Reference in a new issue