]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Btrfs: try to avoid doing a search in btrfs_next_leaf
authorJosef Bacik <jbacik@fusionio.com>
Mon, 24 Sep 2012 20:01:09 +0000 (16:01 -0400)
committerChris Mason <chris.mason@fusionio.com>
Mon, 1 Oct 2012 19:19:35 +0000 (15:19 -0400)
Things like btrfs_drop_extents call btrfs_next_leaf to see if there is
anything else they need on the next leaf.  This will result in a re-search,
but if we are already at the last leaf in the tree or if the first item in
the next leaf doesn't match the objectid of the one we want we can just
return without doing the search at all.  This helps in things like fsync()
where our tree is pretty shallow and we're likely to be on the last leaf
often.  Thanks,

Signed-off-by: Josef Bacik <jbacik@fusionio.com>
fs/btrfs/ctree.c
fs/btrfs/ctree.h

index fcc8c21a6233780da6cf2c0330d011f54c7b80c2..3ac7d79e359011e16deae094a21f7757a5a2751f 100644 (file)
@@ -2441,6 +2441,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
        lowest_level = p->lowest_level;
        WARN_ON(lowest_level && ins_len > 0);
        WARN_ON(p->nodes[0] != NULL);
+       p->shecantgoanyfarthercapt = 1;
 
        if (ins_len < 0) {
                lowest_unlock = 2;
@@ -2568,6 +2569,13 @@ cow_done:
 
                if (level != 0) {
                        int dec = 0;
+
+                       /*
+                        * Slot is not the last in the node, we can go farther
+                        * capt.
+                        */
+                       if (slot < btrfs_header_nritems(b))
+                               p->shecantgoanyfarthercapt = 0;
                        if (ret && slot > 0) {
                                dec = 1;
                                slot -= 1;
@@ -5615,8 +5623,27 @@ int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
        nritems = btrfs_header_nritems(path->nodes[0]);
        if (nritems == 0)
                return 1;
+       if (path->shecantgoanyfarthercapt)
+               return 1;
+       if (!path->nodes[1])
+               return 1;
 
        btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1);
+
+       /*
+        * If we have the level above us locked already just check and see if
+        * the key in the next leaf even has the same objectid, and if not
+        * return 1 and avoid the search.
+        */
+       if (path->locks[1] &&
+           path->slots[1] + 1 < btrfs_header_nritems(path->nodes[1])) {
+               struct btrfs_key tmp;
+
+               btrfs_node_key_to_cpu(path->nodes[1], &tmp,
+                                     path->slots[1] + 1);
+               if (key.objectid != tmp.objectid)
+                       return 1;
+       }
 again:
        level = 1;
        next = NULL;
index 50dcd0fbae111eae757ac9076a01a615c51ff815..2feb2ac67a91b47e1733b55c01832472a8d44f78 100644 (file)
@@ -571,6 +571,7 @@ struct btrfs_path {
        unsigned int skip_locking:1;
        unsigned int leave_spinning:1;
        unsigned int search_commit_root:1;
+       unsigned int shecantgoanyfarthercapt:1;
 };
 
 /*