Commit ceda1b9a authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Evict btree nodes we're deleting

There was a bug that led to duplicate btree node pointers being inserted
at the wrong level. The new topology repair code can fix that, except
that the btree cache code gets confused when we read in a btree node
from the pointer that was at the wrong level. This patch evicts nodes
that we're deleting to, which nicely solves the problem.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent fc51b041
......@@ -948,6 +948,36 @@ void bch2_btree_node_prefetch(struct bch_fs *c, struct btree_iter *iter,
bch2_btree_node_fill(c, iter, k, btree_id, level, SIX_LOCK_read, false);
}
void bch2_btree_node_evict(struct bch_fs *c, const struct bkey_i *k)
{
struct btree_cache *bc = &c->btree_cache;
struct btree *b;
b = btree_cache_find(bc, k);
if (!b)
return;
six_lock_intent(&b->c.lock, NULL, NULL);
six_lock_write(&b->c.lock, NULL, NULL);
wait_on_bit_io(&b->flags, BTREE_NODE_read_in_flight,
TASK_UNINTERRUPTIBLE);
__bch2_btree_node_write(c, b);
/* wait for any in flight btree write */
btree_node_wait_on_io(b);
BUG_ON(btree_node_dirty(b));
mutex_lock(&bc->lock);
btree_node_data_free(c, b);
bch2_btree_node_hash_remove(bc, b);
mutex_unlock(&bc->lock);
six_unlock_write(&b->c.lock);
six_unlock_intent(&b->c.lock);
}
void bch2_btree_node_to_text(struct printbuf *out, struct bch_fs *c,
struct btree *b)
{
......
......@@ -30,6 +30,8 @@ struct btree *bch2_btree_node_get_noiter(struct bch_fs *, const struct bkey_i *,
void bch2_btree_node_prefetch(struct bch_fs *, struct btree_iter *,
const struct bkey_i *, enum btree_id, unsigned);
void bch2_btree_node_evict(struct bch_fs *, const struct bkey_i *);
void bch2_fs_btree_cache_exit(struct bch_fs *);
int bch2_fs_btree_cache_init(struct bch_fs *);
void bch2_fs_btree_cache_init_early(struct btree_cache *);
......
......@@ -298,6 +298,7 @@ static int bch2_btree_repair_topology_recurse(struct bch_fs *c, struct btree *b)
bch2_btree_ids[b->c.btree_id],
b->c.level - 1,
(bch2_bkey_val_to_text(&PBUF(buf), c, bkey_i_to_s_c(tmp.k)), buf))) {
bch2_btree_node_evict(c, tmp.k);
ret = bch2_journal_key_delete(c, b->c.btree_id,
b->c.level, tmp.k->k.p);
if (ret)
......@@ -359,6 +360,7 @@ static int bch2_btree_repair_topology_recurse(struct bch_fs *c, struct btree *b)
cur = NULL;
if (ret == DROP_THIS_NODE) {
bch2_btree_node_evict(c, tmp.k);
ret = bch2_journal_key_delete(c, b->c.btree_id,
b->c.level, tmp.k->k.p);
dropped_children = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment