summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-01-04 18:35:00 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:22 -0400
commit4e08446db05427ad0972eba58d6447b21c1ca7e1 (patch)
treee287b8be0e369a8d0afefaff11a57ae475ac2fb5 /fs
parent9714baaa52d63416d1f7577b630831fc885bfa1f (diff)
downloadlinux-stable-4e08446db05427ad0972eba58d6447b21c1ca7e1.tar.gz
linux-stable-4e08446db05427ad0972eba58d6447b21c1ca7e1.tar.bz2
linux-stable-4e08446db05427ad0972eba58d6447b21c1ca7e1.zip
bcachefs: Fix bch2_check_fix_ptrs()
The repair for for btree_ptrs was saying one thing and doing another - fortunately, that code can just be deleted. Also, when we update a btree node pointer, we also have to update node in memery, if it exists in the btree node cache - this fixes bch2_check_fix_ptrs() to do that. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/btree_gc.c62
1 files changed, 40 insertions, 22 deletions
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index d7de00af81c9..8c60f15fc63e 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -155,6 +155,34 @@ static void btree_ptr_to_v2(struct btree *b, struct bkey_i_btree_ptr_v2 *dst)
}
}
+static void bch2_btree_node_update_key_early(struct bch_fs *c,
+ enum btree_id btree, unsigned level,
+ struct bkey_s_c old, struct bkey_i *new)
+{
+ struct btree *b;
+ struct bkey_buf tmp;
+ int ret;
+
+ bch2_bkey_buf_init(&tmp);
+ bch2_bkey_buf_reassemble(&tmp, c, old);
+
+ b = bch2_btree_node_get_noiter(c, tmp.k, btree, level, true);
+ if (!IS_ERR_OR_NULL(b)) {
+ mutex_lock(&c->btree_cache.lock);
+
+ bch2_btree_node_hash_remove(&c->btree_cache, b);
+
+ bkey_copy(&b->key, new);
+ ret = __bch2_btree_node_hash_insert(&c->btree_cache, b);
+ BUG_ON(ret);
+
+ mutex_unlock(&c->btree_cache.lock);
+ six_unlock_read(&b->c.lock);
+ }
+
+ bch2_bkey_buf_exit(&tmp, c);
+}
+
static int set_node_min(struct bch_fs *c, struct btree *b, struct bpos new_min)
{
struct bkey_i_btree_ptr_v2 *new;
@@ -524,19 +552,6 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id,
}
}
- if (fsck_err_on(data_type == BCH_DATA_btree &&
- g->mark.gen != p.ptr.gen, c,
- "bucket %u:%zu data type %s has metadata but wrong gen: %u != %u\n"
- "while marking %s",
- p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
- bch2_data_types[ptr_data_type(k->k, &p.ptr)],
- p.ptr.gen, g->mark.gen,
- (bch2_bkey_val_to_text(&PBUF(buf), c, *k), buf))) {
- g2->_mark.data_type = g->_mark.data_type = data_type;
- g2->gen_valid = g->gen_valid = true;
- set_bit(BCH_FS_NEED_ALLOC_WRITE, &c->flags);
- }
-
if (fsck_err_on(gen_cmp(p.ptr.gen, g->mark.gen) > 0, c,
"bucket %u:%zu data type %s ptr gen in the future: %u > %u\n"
"while marking %s",
@@ -576,7 +591,7 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id,
(bch2_bkey_val_to_text(&PBUF(buf), c, *k), buf)))
do_update = true;
- if (p.ptr.gen != g->mark.gen)
+ if (data_type != BCH_DATA_btree && p.ptr.gen != g->mark.gen)
continue;
if (fsck_err_on(g->mark.data_type &&
@@ -691,16 +706,19 @@ found:
}
ret = bch2_journal_key_insert_take(c, btree_id, level, new);
-
- if (ret)
+ if (ret) {
kfree(new);
- else {
- bch2_bkey_val_to_text(&PBUF(buf), c, *k);
- bch_info(c, "updated %s", buf);
- bch2_bkey_val_to_text(&PBUF(buf), c, bkey_i_to_s_c(new));
- bch_info(c, "new key %s", buf);
- *k = bkey_i_to_s_c(new);
+ return ret;
}
+
+ if (level)
+ bch2_btree_node_update_key_early(c, btree_id, level - 1, *k, new);
+
+ bch2_bkey_val_to_text(&PBUF(buf), c, *k);
+ bch_info(c, "updated %s", buf);
+ bch2_bkey_val_to_text(&PBUF(buf), c, bkey_i_to_s_c(new));
+ bch_info(c, "new key %s", buf);
+ *k = bkey_i_to_s_c(new);
}
fsck_err:
return ret;