OSDN Git Service

btrfs: open code key_search
authorNikolay Borisov <nborisov@suse.com>
Wed, 27 May 2020 10:10:53 +0000 (13:10 +0300)
committerDavid Sterba <dsterba@suse.com>
Thu, 28 May 2020 12:01:52 +0000 (14:01 +0200)
This function wraps the optimisation implemented by d7396f07358a
("Btrfs: optimize key searches in btrfs_search_slot") however this
optimisation is really used in only one place - btrfs_search_slot.

Just open code the optimisation and also add a comment explaining how it
works since it's not clear just by looking at the code - the key point
here is it depends on an internal invariant that BTRFS' btree provides,
namely intermediate pointers always contain the key at slot0 at the
child node. So in the case of exact match we can safely assume that the
given key will always be in slot 0 on lower levels.

Furthermore this results in a reduction of btrfs_search_slot's size:

./scripts/bloat-o-meter ctree.orig fs/btrfs/ctree.o
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-75 (-75)
Function                                     old     new   delta
btrfs_search_slot                           2783    2708     -75
Total: Before=50423, After=50348, chg -0.15%

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ctree.c

index 9277555..5f94414 100644 (file)
@@ -2488,19 +2488,6 @@ done:
        return ret;
 }
 
-static int key_search(struct extent_buffer *b, const struct btrfs_key *key,
-                     int *prev_cmp, int *slot)
-{
-       if (*prev_cmp != 0) {
-               *prev_cmp = btrfs_bin_search(b, key, slot);
-               return *prev_cmp;
-       }
-
-       *slot = 0;
-
-       return 0;
-}
-
 int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *path,
                u64 iobjectid, u64 ioff, u8 key_type,
                struct btrfs_key *found_key)
@@ -2770,9 +2757,23 @@ cow_done:
                        }
                }
 
-               ret = key_search(b, key, &prev_cmp, &slot);
-               if (ret < 0)
-                       goto done;
+               /*
+                * If btrfs_bin_search returns an exact match (prev_cmp == 0)
+                * we can safely assume the target key will always be in slot 0
+                * on lower levels due to the invariants BTRFS' btree provides,
+                * namely that a btrfs_key_ptr entry always points to the
+                * lowest key in the child node, thus we can skip searching
+                * lower levels
+                */
+               if (prev_cmp == 0) {
+                       slot = 0;
+                       ret = 0;
+               } else {
+                       ret = btrfs_bin_search(b, key, &slot);
+                       prev_cmp = ret;
+                       if (ret < 0)
+                               goto done;
+               }
 
                if (level == 0) {
                        p->slots[level] = slot;
@@ -2896,7 +2897,6 @@ int btrfs_search_old_slot(struct btrfs_root *root, const struct btrfs_key *key,
        int level;
        int lowest_unlock = 1;
        u8 lowest_level = 0;
-       int prev_cmp = -1;
 
        lowest_level = p->lowest_level;
        WARN_ON(p->nodes[0] != NULL);
@@ -2929,12 +2929,7 @@ again:
                 */
                btrfs_unlock_up_safe(p, level + 1);
 
-               /*
-                * Since we can unwind ebs we want to do a real search every
-                * time.
-                */
-               prev_cmp = -1;
-               ret = key_search(b, key, &prev_cmp, &slot);
+               ret = btrfs_bin_search(b, key, &slot);
                if (ret < 0)
                        goto done;