mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
bcachefs: Don't BUG_ON() btree topology error
This replaces an assertion in the btree merge path with a bch2_inconsistent_error() - fsck will fix it. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
1c8441bea5
commit
537c32f521
|
|
@ -686,6 +686,41 @@ static int lock_node_check_fn(struct six_lock *lock, void *p)
|
|||
return b->hash_val == btree_ptr_hash_val(k) ? 0 : -1;
|
||||
}
|
||||
|
||||
static noinline void btree_bad_header(struct bch_fs *c, struct btree *b)
|
||||
{
|
||||
char buf1[100], buf2[100], buf3[100], buf4[100];
|
||||
|
||||
if (!test_bit(BCH_FS_INITIAL_GC_DONE, &c->flags))
|
||||
return;
|
||||
|
||||
bch2_bpos_to_text(&PBUF(buf1), b->key.k.type == KEY_TYPE_btree_ptr_v2
|
||||
? bkey_i_to_btree_ptr_v2(&b->key)->v.min_key
|
||||
: POS_MIN);
|
||||
bch2_bpos_to_text(&PBUF(buf2), b->data->min_key);
|
||||
|
||||
bch2_bpos_to_text(&PBUF(buf3), b->key.k.p);
|
||||
bch2_bpos_to_text(&PBUF(buf4), b->data->max_key);
|
||||
bch2_fs_inconsistent(c, "btree node header doesn't match ptr\n"
|
||||
"btree: ptr %u header %llu\n"
|
||||
"level: ptr %u header %llu\n"
|
||||
"min ptr %s node header %s\n"
|
||||
"max ptr %s node header %s",
|
||||
b->c.btree_id, BTREE_NODE_ID(b->data),
|
||||
b->c.level, BTREE_NODE_LEVEL(b->data),
|
||||
buf1, buf2, buf3, buf4);
|
||||
}
|
||||
|
||||
static inline void btree_check_header(struct bch_fs *c, struct btree *b)
|
||||
{
|
||||
if (b->c.btree_id != BTREE_NODE_ID(b->data) ||
|
||||
b->c.level != BTREE_NODE_LEVEL(b->data) ||
|
||||
bpos_cmp(b->data->max_key, b->key.k.p) ||
|
||||
(b->key.k.type == KEY_TYPE_btree_ptr_v2 &&
|
||||
bpos_cmp(b->data->min_key,
|
||||
bkey_i_to_btree_ptr_v2(&b->key)->v.min_key)))
|
||||
btree_bad_header(c, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* bch_btree_node_get - find a btree node in the cache and lock it, reading it
|
||||
* in from disk if necessary.
|
||||
|
|
@ -803,10 +838,7 @@ struct btree *bch2_btree_node_get(struct bch_fs *c, struct btree_iter *iter,
|
|||
|
||||
EBUG_ON(b->c.btree_id != iter->btree_id);
|
||||
EBUG_ON(BTREE_NODE_LEVEL(b->data) != level);
|
||||
EBUG_ON(bpos_cmp(b->data->max_key, k->k.p));
|
||||
EBUG_ON(b->key.k.type == KEY_TYPE_btree_ptr_v2 &&
|
||||
bpos_cmp(b->data->min_key,
|
||||
bkey_i_to_btree_ptr_v2(&b->key)->v.min_key));
|
||||
btree_check_header(c, b);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
|
@ -886,10 +918,7 @@ struct btree *bch2_btree_node_get_noiter(struct bch_fs *c,
|
|||
|
||||
EBUG_ON(b->c.btree_id != btree_id);
|
||||
EBUG_ON(BTREE_NODE_LEVEL(b->data) != level);
|
||||
EBUG_ON(bpos_cmp(b->data->max_key, k->k.p));
|
||||
EBUG_ON(b->key.k.type == KEY_TYPE_btree_ptr_v2 &&
|
||||
bpos_cmp(b->data->min_key,
|
||||
bkey_i_to_btree_ptr_v2(&b->key)->v.min_key));
|
||||
btree_check_header(c, b);
|
||||
out:
|
||||
bch2_btree_cache_cannibalize_unlock(c);
|
||||
return b;
|
||||
|
|
|
|||
|
|
@ -1606,7 +1606,19 @@ int __bch2_foreground_maybe_merge(struct bch_fs *c,
|
|||
next = m;
|
||||
}
|
||||
|
||||
BUG_ON(bkey_cmp(bpos_successor(prev->data->max_key), next->data->min_key));
|
||||
if (bkey_cmp(bpos_successor(prev->data->max_key), next->data->min_key)) {
|
||||
char buf1[100], buf2[100];
|
||||
|
||||
bch2_bpos_to_text(&PBUF(buf1), prev->data->max_key);
|
||||
bch2_bpos_to_text(&PBUF(buf2), next->data->min_key);
|
||||
bch2_fs_inconsistent(c,
|
||||
"btree topology error in btree merge:\n"
|
||||
"prev ends at %s\n"
|
||||
"next starts at %s\n",
|
||||
buf1, buf2);
|
||||
ret = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
bch2_bkey_format_init(&new_s);
|
||||
bch2_bkey_format_add_pos(&new_s, prev->data->min_key);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user