bcachefs: improve validate_bset_keys()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
5e448c4893
commit
2d02bfb01b
@ -524,7 +524,8 @@ static void btree_err_msg(struct printbuf *out, struct bch_fs *c,
|
|||||||
prt_printf(out, "at btree ");
|
prt_printf(out, "at btree ");
|
||||||
bch2_btree_pos_to_text(out, c, b);
|
bch2_btree_pos_to_text(out, c, b);
|
||||||
|
|
||||||
prt_printf(out, "\n node offset %u", b->written);
|
prt_printf(out, "\n node offset %u/%u",
|
||||||
|
b->written, btree_ptr_sectors_written(&b->key));
|
||||||
if (i)
|
if (i)
|
||||||
prt_printf(out, " bset u64s %u", le16_to_cpu(i->u64s));
|
prt_printf(out, " bset u64s %u", le16_to_cpu(i->u64s));
|
||||||
prt_str(out, ": ");
|
prt_str(out, ": ");
|
||||||
@ -830,6 +831,23 @@ static int bset_key_invalid(struct bch_fs *c, struct btree *b,
|
|||||||
(rw == WRITE ? bch2_bkey_val_invalid(c, k, READ, err) : 0);
|
(rw == WRITE ? bch2_bkey_val_invalid(c, k, READ, err) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool __bkey_valid(struct bch_fs *c, struct btree *b,
|
||||||
|
struct bset *i, struct bkey_packed *k)
|
||||||
|
{
|
||||||
|
if (bkey_p_next(k) > vstruct_last(i))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (k->format > KEY_FORMAT_CURRENT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
struct printbuf buf = PRINTBUF;
|
||||||
|
struct bkey tmp;
|
||||||
|
struct bkey_s u = __bkey_disassemble(b, k, &tmp);
|
||||||
|
bool ret = __bch2_bkey_invalid(c, u.s_c, btree_node_type(b), READ, &buf);
|
||||||
|
printbuf_exit(&buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int validate_bset_keys(struct bch_fs *c, struct btree *b,
|
static int validate_bset_keys(struct bch_fs *c, struct btree *b,
|
||||||
struct bset *i, int write,
|
struct bset *i, int write,
|
||||||
bool have_retry, bool *saw_error)
|
bool have_retry, bool *saw_error)
|
||||||
@ -845,6 +863,7 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
|
|||||||
k != vstruct_last(i);) {
|
k != vstruct_last(i);) {
|
||||||
struct bkey_s u;
|
struct bkey_s u;
|
||||||
struct bkey tmp;
|
struct bkey tmp;
|
||||||
|
unsigned next_good_key;
|
||||||
|
|
||||||
if (btree_err_on(bkey_p_next(k) > vstruct_last(i),
|
if (btree_err_on(bkey_p_next(k) > vstruct_last(i),
|
||||||
-BCH_ERR_btree_node_read_err_fixable,
|
-BCH_ERR_btree_node_read_err_fixable,
|
||||||
@ -859,12 +878,8 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
|
|||||||
-BCH_ERR_btree_node_read_err_fixable,
|
-BCH_ERR_btree_node_read_err_fixable,
|
||||||
c, NULL, b, i,
|
c, NULL, b, i,
|
||||||
btree_node_bkey_bad_format,
|
btree_node_bkey_bad_format,
|
||||||
"invalid bkey format %u", k->format)) {
|
"invalid bkey format %u", k->format))
|
||||||
i->u64s = cpu_to_le16(le16_to_cpu(i->u64s) - k->u64s);
|
goto drop_this_key;
|
||||||
memmove_u64s_down(k, bkey_p_next(k),
|
|
||||||
(u64 *) vstruct_end(i) - (u64 *) k);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: validate k->u64s */
|
/* XXX: validate k->u64s */
|
||||||
if (!write)
|
if (!write)
|
||||||
@ -885,11 +900,7 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
|
|||||||
c, NULL, b, i,
|
c, NULL, b, i,
|
||||||
btree_node_bad_bkey,
|
btree_node_bad_bkey,
|
||||||
"invalid bkey: %s", buf.buf);
|
"invalid bkey: %s", buf.buf);
|
||||||
|
goto drop_this_key;
|
||||||
i->u64s = cpu_to_le16(le16_to_cpu(i->u64s) - k->u64s);
|
|
||||||
memmove_u64s_down(k, bkey_p_next(k),
|
|
||||||
(u64 *) vstruct_end(i) - (u64 *) k);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write)
|
if (write)
|
||||||
@ -906,21 +917,45 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
|
|||||||
prt_printf(&buf, " > ");
|
prt_printf(&buf, " > ");
|
||||||
bch2_bkey_to_text(&buf, u.k);
|
bch2_bkey_to_text(&buf, u.k);
|
||||||
|
|
||||||
bch2_dump_bset(c, b, i, 0);
|
|
||||||
|
|
||||||
if (btree_err(-BCH_ERR_btree_node_read_err_fixable,
|
if (btree_err(-BCH_ERR_btree_node_read_err_fixable,
|
||||||
c, NULL, b, i,
|
c, NULL, b, i,
|
||||||
btree_node_bkey_out_of_order,
|
btree_node_bkey_out_of_order,
|
||||||
"%s", buf.buf)) {
|
"%s", buf.buf))
|
||||||
i->u64s = cpu_to_le16(le16_to_cpu(i->u64s) - k->u64s);
|
goto drop_this_key;
|
||||||
memmove_u64s_down(k, bkey_p_next(k),
|
|
||||||
(u64 *) vstruct_end(i) - (u64 *) k);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = k;
|
prev = k;
|
||||||
k = bkey_p_next(k);
|
k = bkey_p_next(k);
|
||||||
|
continue;
|
||||||
|
drop_this_key:
|
||||||
|
next_good_key = k->u64s;
|
||||||
|
|
||||||
|
if (!next_good_key ||
|
||||||
|
(BSET_BIG_ENDIAN(i) == CPU_BIG_ENDIAN &&
|
||||||
|
version >= bcachefs_metadata_version_snapshot)) {
|
||||||
|
/*
|
||||||
|
* only do scanning if bch2_bkey_compat() has nothing to
|
||||||
|
* do
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!__bkey_valid(c, b, i, (void *) ((u64 *) k + next_good_key))) {
|
||||||
|
for (next_good_key = 1;
|
||||||
|
next_good_key < (u64 *) vstruct_last(i) - (u64 *) k;
|
||||||
|
next_good_key++)
|
||||||
|
if (__bkey_valid(c, b, i, (void *) ((u64 *) k + next_good_key)))
|
||||||
|
goto got_good_key;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* didn't find a good key, have to truncate the rest of
|
||||||
|
* the bset
|
||||||
|
*/
|
||||||
|
next_good_key = (u64 *) vstruct_last(i) - (u64 *) k;
|
||||||
|
}
|
||||||
|
got_good_key:
|
||||||
|
le16_add_cpu(&i->u64s, -next_good_key);
|
||||||
|
memmove_u64s_down(k, bkey_p_next(k), (u64 *) vstruct_end(i) - (u64 *) k);
|
||||||
}
|
}
|
||||||
fsck_err:
|
fsck_err:
|
||||||
printbuf_exit(&buf);
|
printbuf_exit(&buf);
|
||||||
|
Loading…
Reference in New Issue
Block a user