]> git.baikalelectronics.ru Git - kernel.git/commitdiff
btrfs: speed up and simplify generic_bin_search
authorDavid Sterba <dsterba@suse.com>
Wed, 29 Apr 2020 21:23:37 +0000 (23:23 +0200)
committerDavid Sterba <dsterba@suse.com>
Mon, 25 May 2020 09:25:33 +0000 (11:25 +0200)
The bin search jumps over the extent buffer item keys, comparing
directly the bytes if the key is in one page, or storing it in a
temporary buffer in case it spans two pages.

The mapping start and length are obtained from map_private_extent_buffer,
which is heavy weight compared to what we need. We know the key size and
can find out the eb page in a simple way.  For keys spanning two pages
the fallback read_extent_buffer is used.

The temporary variables are reduced and moved to the scope of use.

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

index 6dbeb23c59ecb58619c18d4cd4260052858d30de..746dec22f250c6a0733880675db6c36d2211bfa6 100644 (file)
@@ -1668,15 +1668,8 @@ static noinline int generic_bin_search(struct extent_buffer *eb,
 {
        int low = 0;
        int high = max;
-       int mid;
        int ret;
-       struct btrfs_disk_key *tmp = NULL;
-       struct btrfs_disk_key unaligned;
-       unsigned long offset;
-       char *kaddr = NULL;
-       unsigned long map_start = 0;
-       unsigned long map_len = 0;
-       int err;
+       const int key_size = sizeof(struct btrfs_disk_key);
 
        if (low > high) {
                btrfs_err(eb->fs_info,
@@ -1687,32 +1680,26 @@ static noinline int generic_bin_search(struct extent_buffer *eb,
        }
 
        while (low < high) {
+               unsigned long oip;
+               unsigned long offset;
+               struct btrfs_disk_key *tmp;
+               struct btrfs_disk_key unaligned;
+               int mid;
+
                mid = (low + high) / 2;
                offset = p + mid * item_size;
+               oip = offset_in_page(offset);
 
-               if (!kaddr || offset < map_start ||
-                   (offset + sizeof(struct btrfs_disk_key)) >
-                   map_start + map_len) {
-
-                       err = map_private_extent_buffer(eb, offset,
-                                               sizeof(struct btrfs_disk_key),
-                                               &kaddr, &map_start, &map_len);
-
-                       if (!err) {
-                               tmp = (struct btrfs_disk_key *)(kaddr + offset -
-                                                       map_start);
-                       } else if (err == 1) {
-                               read_extent_buffer(eb, &unaligned,
-                                                  offset, sizeof(unaligned));
-                               tmp = &unaligned;
-                       } else {
-                               return err;
-                       }
+               if (oip + key_size <= PAGE_SIZE) {
+                       const unsigned long idx = offset >> PAGE_SHIFT;
+                       char *kaddr = page_address(eb->pages[idx]);
 
+                       tmp = (struct btrfs_disk_key *)(kaddr + oip);
                } else {
-                       tmp = (struct btrfs_disk_key *)(kaddr + offset -
-                                                       map_start);
+                       read_extent_buffer(eb, &unaligned, offset, key_size);
+                       tmp = &unaligned;
                }
+
                ret = comp_keys(tmp, key);
 
                if (ret < 0)