btrfs: backref: Add special time_seq == (u64)-1 case for
authorQu Wenruo <quwenruo@cn.fujitsu.com>
Thu, 16 Apr 2015 06:54:50 +0000 (14:54 +0800)
committerChris Mason <clm@fb.com>
Wed, 10 Jun 2015 16:25:45 +0000 (09:25 -0700)
btrfs_find_all_roots().

Allow btrfs_find_all_roots() to skip all delayed_ref_head lock and tree
lock to do tree search.

This is important for later qgroup implement which will call
find_all_roots() after fs trees are committed.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
fs/btrfs/backref.c

index 49bc5a41c1f814a30fad6a02e9fd0c3e9f81bc96..802fabb30e1575338eec8ae53f157e9f2d7a6b56 100644 (file)
@@ -250,8 +250,12 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
         * the first item to check. But sometimes, we may enter it with
         * slot==nritems. In that case, go to the next leaf before we continue.
         */
-       if (path->slots[0] >= btrfs_header_nritems(path->nodes[0]))
-               ret = btrfs_next_old_leaf(root, path, time_seq);
+       if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
+               if (time_seq == (u64)-1)
+                       ret = btrfs_next_leaf(root, path);
+               else
+                       ret = btrfs_next_old_leaf(root, path, time_seq);
+       }
 
        while (!ret && count < total_refs) {
                eb = path->nodes[0];
@@ -291,7 +295,10 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
                        eie = NULL;
                }
 next:
-               ret = btrfs_next_old_item(root, path, time_seq);
+               if (time_seq == (u64)-1)
+                       ret = btrfs_next_item(root, path);
+               else
+                       ret = btrfs_next_old_item(root, path, time_seq);
        }
 
        if (ret > 0)
@@ -334,6 +341,8 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
 
        if (path->search_commit_root)
                root_level = btrfs_header_level(root->commit_root);
+       else if (time_seq == (u64)-1)
+               root_level = btrfs_header_level(root->node);
        else
                root_level = btrfs_old_root_level(root, time_seq);
 
@@ -343,7 +352,12 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
        }
 
        path->lowest_level = level;
-       ret = btrfs_search_old_slot(root, &ref->key_for_search, path, time_seq);
+       if (time_seq == (u64)-1)
+               ret = btrfs_search_slot(NULL, root, &ref->key_for_search, path,
+                                       0, 0);
+       else
+               ret = btrfs_search_old_slot(root, &ref->key_for_search, path,
+                                           time_seq);
 
        /* root node has been locked, we can release @subvol_srcu safely here */
        srcu_read_unlock(&fs_info->subvol_srcu, index);
@@ -879,6 +893,11 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
  *
  * NOTE: This can return values > 0
  *
+ * If time_seq is set to (u64)-1, it will not search delayed_refs, and behave
+ * much like trans == NULL case, the difference only lies in it will not
+ * commit root.
+ * The special case is for qgroup to search roots in commit_transaction().
+ *
  * FIXME some caching might speed things up
  */
 static int find_parent_nodes(struct btrfs_trans_handle *trans,
@@ -917,6 +936,9 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
                path->skip_locking = 1;
        }
 
+       if (time_seq == (u64)-1)
+               path->skip_locking = 1;
+
        /*
         * grab both a lock on the path and a lock on the delayed ref head.
         * We need both to get a consistent picture of how the refs look
@@ -931,9 +953,10 @@ again:
        BUG_ON(ret == 0);
 
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
-       if (trans && likely(trans->type != __TRANS_DUMMY)) {
+       if (trans && likely(trans->type != __TRANS_DUMMY) &&
+           time_seq != (u64)-1) {
 #else
-       if (trans) {
+       if (trans && time_seq != (u64)-1) {
 #endif
                /*
                 * look if there are updates for this ref queued and lock the