This function wraps the optimisation implemented by d7396f0735
("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>
This commit is contained in:
Nikolay Borisov 2020-05-27 13:10:53 +03:00 коммит произвёл David Sterba
Родитель d8f3e73587
Коммит 995e9a166b
1 изменённых файлов: 18 добавлений и 23 удалений

Просмотреть файл

@ -2488,19 +2488,6 @@ done:
return ret; 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, int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *path,
u64 iobjectid, u64 ioff, u8 key_type, u64 iobjectid, u64 ioff, u8 key_type,
struct btrfs_key *found_key) struct btrfs_key *found_key)
@ -2770,9 +2757,23 @@ cow_done:
} }
} }
ret = key_search(b, key, &prev_cmp, &slot); /*
if (ret < 0) * If btrfs_bin_search returns an exact match (prev_cmp == 0)
goto done; * 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) { if (level == 0) {
p->slots[level] = slot; 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 level;
int lowest_unlock = 1; int lowest_unlock = 1;
u8 lowest_level = 0; u8 lowest_level = 0;
int prev_cmp = -1;
lowest_level = p->lowest_level; lowest_level = p->lowest_level;
WARN_ON(p->nodes[0] != NULL); WARN_ON(p->nodes[0] != NULL);
@ -2929,12 +2929,7 @@ again:
*/ */
btrfs_unlock_up_safe(p, level + 1); btrfs_unlock_up_safe(p, level + 1);
/* ret = btrfs_bin_search(b, key, &slot);
* 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);
if (ret < 0) if (ret < 0)
goto done; goto done;