Btrfs: determine level of old roots
authorJan Schmidt <list.btrfs@jan-o-sch.net>
Tue, 23 Oct 2012 09:28:27 +0000 (11:28 +0200)
committerJan Schmidt <list.btrfs@jan-o-sch.net>
Wed, 24 Oct 2012 10:36:38 +0000 (12:36 +0200)
In btrfs_find_all_roots' termination condition, we compare the level of the
old buffer we got from btrfs_search_old_slot to the level of the current
root node. We'd better compare it to the level of the rewinded root node.

Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
fs/btrfs/backref.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h

index f3187938e081c7dcbf842d424f5de6ed06d3f93f..65608fbf2232f23780a5620b6c15db22f9084475 100644 (file)
@@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
                goto out;
        }
 
-       rcu_read_lock();
-       root_level = btrfs_header_level(root->node);
-       rcu_read_unlock();
+       root_level = btrfs_old_root_level(root, time_seq);
 
        if (root_level + 1 == level)
                goto out;
index d9308c38a8f270c740f2775b99bf070e3e9ccf56..ef68c33eefd9caaac2f9d2cff353d915081c1b6e 100644 (file)
@@ -1297,6 +1297,23 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
        return eb;
 }
 
+int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq)
+{
+       struct tree_mod_elem *tm;
+       int level;
+
+       tm = __tree_mod_log_oldest_root(root->fs_info, 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();
+       }
+
+       return level;
+}
+
 static inline int should_cow_block(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
                                   struct extent_buffer *buf)
index 1630be831210c9c9a0bb57eb7d5e98ad36a3b235..34c5a442dd33032b6e76d93695ea7346802779b7 100644 (file)
@@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info)
 {
        return atomic_inc_return(&fs_info->tree_mod_seq);
 }
+int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq);
 
 /* root-item.c */
 int btrfs_find_root_ref(struct btrfs_root *tree_root,