]> www.infradead.org Git - linux.git/commitdiff
bcachefs: Fix key cache + BTREE_ITER_all_snapshots
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 13 Dec 2024 10:29:27 +0000 (05:29 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Dec 2024 06:36:23 +0000 (01:36 -0500)
Normally, whitouts (KEY_TYPE_whitout) are filtered from btree lookups,
since they exist only to represent deletions of keys in ancestor
snapshots - except, they should not be filtered in
BTREE_ITER_all_snapshots mode, so that e.g. snapshot deletion can clean
them up.

This means that that the key cache has to store whiteouts, and key cache
fills cannot filter them.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_iter.c

index e370fa327769c032845f27a13916f28365b4440a..b27944b6208770c168d7bf6104900f2c323ac2d7 100644 (file)
@@ -1854,7 +1854,7 @@ struct bkey_s_c bch2_btree_path_peek_slot(struct btree_path *path, struct bkey *
                        !bkey_eq(path->pos, ck->key.pos));
 
                *u = ck->k->k;
-               k = bkey_i_to_s_c(ck->k);
+               k = (struct bkey_s_c) { u, &ck->k->v };
        }
 
        return k;
@@ -2421,7 +2421,8 @@ struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *iter, struct bpos en
                                continue;
                        }
 
-                       if (bkey_whiteout(k.k)) {
+                       if (bkey_whiteout(k.k) &&
+                           !(iter->flags & BTREE_ITER_key_cache_fill)) {
                                search_key = bkey_successor(iter, k.k->p);
                                continue;
                        }
@@ -2781,6 +2782,11 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
                k = bch2_btree_path_peek_slot(trans->paths + iter->path, &iter->k);
                if (unlikely(!k.k))
                        goto out_no_locked;
+
+               if (unlikely(k.k->type == KEY_TYPE_whiteout &&
+                            (iter->flags & BTREE_ITER_filter_snapshots) &&
+                            !(iter->flags & BTREE_ITER_key_cache_fill)))
+                       iter->k.type = KEY_TYPE_deleted;
        } else {
                struct bpos next;
                struct bpos end = iter->pos;