Skip to content

Commit

Permalink
Btrfs: tree mod log's old roots could still be part of the tree
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jan Schmidt committed Oct 24, 2012
1 parent ba1bfbd commit 834328a
Showing 1 changed file with 21 additions and 4 deletions.
25 changes: 21 additions & 4 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 834328a

Please sign in to comment.