diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2025-06-24 15:55:40 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2025-06-30 17:52:46 -0400 |
commit | 6d7644e987c9c16b9fd7bd988f55552f8372c272 (patch) | |
tree | e8436a09b0aadd67e1c31eb3a845997cd0d300b6 | |
parent | 5d92d2d7d711a5ccae12a8c52241c4dea4b5ba0b (diff) |
bcachefs: Don't peek key cache unless we have a real key
We require that if a key exists in the key cache it also be present in
the underlying btree, for cache coherency reasons.
So checking the key cache on whiteout is unnecessary. This is part of
fixing a major performance bug when doing many unlinks all in a row -
we end up scanning through a ton of key cache whiteouts before peek()
can return a real key.
Reported-by: John Schoenick <johns@valvesoftware.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/btree_iter.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index d7dc7a25b95d..87d98a5cb02a 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -2288,6 +2288,7 @@ static struct bkey_s_c __bch2_btree_iter_peek(struct btree_trans *trans, struct if (unlikely(iter->flags & BTREE_ITER_with_key_cache) && k.k && + !bkey_deleted(k.k) && (k2 = btree_trans_peek_key_cache(trans, iter, k.k->p)).k) { k = k2; if (bkey_err(k)) { @@ -2580,6 +2581,7 @@ static struct bkey_s_c __bch2_btree_iter_peek_prev(struct btree_trans *trans, st if (unlikely(iter->flags & BTREE_ITER_with_key_cache) && k.k && + !bkey_deleted(k.k) && (k2 = btree_trans_peek_key_cache(trans, iter, k.k->p)).k) { k = k2; if (bkey_err(k2)) { @@ -2795,7 +2797,7 @@ struct bkey_s_c bch2_btree_iter_prev(struct btree_trans *trans, struct btree_ite struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_trans *trans, struct btree_iter *iter) { struct bpos search_key; - struct bkey_s_c k; + struct bkey_s_c k, k2; int ret; bch2_trans_verify_not_unlocked_or_in_restart(trans); @@ -2854,18 +2856,18 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_trans *trans, struct btre (k = btree_trans_peek_slot_journal(trans, iter)).k) goto out; + k = bch2_btree_path_peek_slot(btree_iter_path(trans, iter), &iter->k); + if (unlikely(!k.k)) + goto out; + if (unlikely(iter->flags & BTREE_ITER_with_key_cache) && - (k = btree_trans_peek_key_cache(trans, iter, iter->pos)).k) { + !bkey_deleted(k.k) && + (k2 = btree_trans_peek_key_cache(trans, iter, iter->pos)).k) { + k = k2; if (!bkey_err(k)) iter->k = *k.k; - /* We're not returning a key from iter->path: */ - goto out; } - k = bch2_btree_path_peek_slot(btree_iter_path(trans, iter), &iter->k); - if (unlikely(!k.k)) - goto out; - if (unlikely(k.k->type == KEY_TYPE_whiteout && (iter->flags & BTREE_ITER_filter_snapshots) && !(iter->flags & BTREE_ITER_key_cache_fill))) |