aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2012-10-23 05:27:33 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-10-24 06:36:37 -0400
commit834328a8493079d15f30866ace42489463f52571 (patch)
tree892c092aa11b015b064bf86ff98f4b60aeb692ed /fs/btrfs
parentba1bfbd592c1adddd5d0005f587a6e308e25c949 (diff)
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>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index e6b75ccd2850..d9308c38a8f2 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1239,6 +1239,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
1239 struct tree_mod_root *old_root = NULL; 1239 struct tree_mod_root *old_root = NULL;
1240 u64 old_generation = 0; 1240 u64 old_generation = 0;
1241 u64 logical; 1241 u64 logical;
1242 u32 blocksize;
1242 1243
1243 eb = btrfs_read_lock_root_node(root); 1244 eb = btrfs_read_lock_root_node(root);
1244 tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); 1245 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)
1254 } 1255 }
1255 1256
1256 tm = tree_mod_log_search(root->fs_info, logical, time_seq); 1257 tm = tree_mod_log_search(root->fs_info, logical, time_seq);
1257 if (old_root) 1258 if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
1259 btrfs_tree_read_unlock(root->node);
1260 free_extent_buffer(root->node);
1261 blocksize = btrfs_level_size(root, old_root->level);
1262 eb = read_tree_block(root, logical, blocksize, 0);
1263 if (!eb) {
1264 pr_warn("btrfs: failed to read tree block %llu from get_old_root\n",
1265 logical);
1266 WARN_ON(1);
1267 } else {
1268 eb = btrfs_clone_extent_buffer(eb);
1269 }
1270 } else if (old_root) {
1271 btrfs_tree_read_unlock(root->node);
1272 free_extent_buffer(root->node);
1258 eb = alloc_dummy_extent_buffer(logical, root->nodesize); 1273 eb = alloc_dummy_extent_buffer(logical, root->nodesize);
1259 else 1274 } else {
1260 eb = btrfs_clone_extent_buffer(root->node); 1275 eb = btrfs_clone_extent_buffer(root->node);
1261 btrfs_tree_read_unlock(root->node); 1276 btrfs_tree_read_unlock(root->node);
1262 free_extent_buffer(root->node); 1277 free_extent_buffer(root->node);
1278 }
1279
1263 if (!eb) 1280 if (!eb)
1264 return NULL; 1281 return NULL;
1265 btrfs_tree_read_lock(eb); 1282 btrfs_tree_read_lock(eb);