mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 04:29:11 -04:00
bcachefs: Fix journal entry repair code
When we detect bad keys in the journal that have to be dropped, the flow control was wrong - we ended up not checking the next key in that entry. Oops. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
committed by
Kent Overstreet
parent
628a3ad2c2
commit
4d54337cdb
@@ -160,6 +160,8 @@ static void journal_entry_null_range(void *start, void *end)
|
||||
#define journal_entry_err_on(cond, c, msg, ...) \
|
||||
((cond) ? journal_entry_err(c, msg, ##__VA_ARGS__) : false)
|
||||
|
||||
#define FSCK_DELETED_KEY 5
|
||||
|
||||
static int journal_validate_key(struct bch_fs *c, struct jset *jset,
|
||||
struct jset_entry *entry,
|
||||
unsigned level, enum btree_id btree_id,
|
||||
@@ -172,33 +174,42 @@ static int journal_validate_key(struct bch_fs *c, struct jset *jset,
|
||||
int ret = 0;
|
||||
|
||||
if (journal_entry_err_on(!k->k.u64s, c,
|
||||
"invalid %s in journal entry %llu offset %zi: k->u64s 0",
|
||||
"invalid %s in jset %llu offset %zi/%u entry offset %zi/%u: k->u64s 0",
|
||||
type, le64_to_cpu(jset->seq),
|
||||
(u64 *) entry - jset->_data)) {
|
||||
(u64 *) entry - jset->_data,
|
||||
le32_to_cpu(jset->u64s),
|
||||
(u64 *) k - entry->_data,
|
||||
le16_to_cpu(entry->u64s))) {
|
||||
entry->u64s = cpu_to_le16((u64 *) k - entry->_data);
|
||||
journal_entry_null_range(vstruct_next(entry), next);
|
||||
return 0;
|
||||
return FSCK_DELETED_KEY;
|
||||
}
|
||||
|
||||
if (journal_entry_err_on((void *) bkey_next(k) >
|
||||
(void *) vstruct_next(entry), c,
|
||||
"invalid %s in journal entry %llu offset %zi: extends past end of journal entry",
|
||||
"invalid %s in jset %llu offset %zi/%u entry offset %zi/%u: extends past end of journal entry",
|
||||
type, le64_to_cpu(jset->seq),
|
||||
(u64 *) entry - jset->_data)) {
|
||||
(u64 *) entry - jset->_data,
|
||||
le32_to_cpu(jset->u64s),
|
||||
(u64 *) k - entry->_data,
|
||||
le16_to_cpu(entry->u64s))) {
|
||||
entry->u64s = cpu_to_le16((u64 *) k - entry->_data);
|
||||
journal_entry_null_range(vstruct_next(entry), next);
|
||||
return 0;
|
||||
return FSCK_DELETED_KEY;
|
||||
}
|
||||
|
||||
if (journal_entry_err_on(k->k.format != KEY_FORMAT_CURRENT, c,
|
||||
"invalid %s in journal entry %llu offset %zi: bad format %u",
|
||||
"invalid %s in jset %llu offset %zi/%u entry offset %zi/%u: bad format %u",
|
||||
type, le64_to_cpu(jset->seq),
|
||||
(u64 *) entry - jset->_data,
|
||||
le32_to_cpu(jset->u64s),
|
||||
(u64 *) k - entry->_data,
|
||||
le16_to_cpu(entry->u64s),
|
||||
k->k.format)) {
|
||||
le16_add_cpu(&entry->u64s, -k->k.u64s);
|
||||
le16_add_cpu(&entry->u64s, -((u16) k->k.u64s));
|
||||
memmove(k, bkey_next(k), next - (void *) bkey_next(k));
|
||||
journal_entry_null_range(vstruct_next(entry), next);
|
||||
return 0;
|
||||
return FSCK_DELETED_KEY;
|
||||
}
|
||||
|
||||
if (!write)
|
||||
@@ -212,15 +223,18 @@ static int journal_validate_key(struct bch_fs *c, struct jset *jset,
|
||||
char buf[160];
|
||||
|
||||
bch2_bkey_val_to_text(&PBUF(buf), c, bkey_i_to_s_c(k));
|
||||
mustfix_fsck_err(c, "invalid %s in journal entry %llu offset %zi: %s\n%s",
|
||||
mustfix_fsck_err(c, "invalid %s in jset %llu offset %zi/%u entry offset %zi/%u: %s\n%s",
|
||||
type, le64_to_cpu(jset->seq),
|
||||
(u64 *) entry - jset->_data,
|
||||
le32_to_cpu(jset->u64s),
|
||||
(u64 *) k - entry->_data,
|
||||
le16_to_cpu(entry->u64s),
|
||||
invalid, buf);
|
||||
|
||||
le16_add_cpu(&entry->u64s, -k->k.u64s);
|
||||
le16_add_cpu(&entry->u64s, -((u16) k->k.u64s));
|
||||
memmove(k, bkey_next(k), next - (void *) bkey_next(k));
|
||||
journal_entry_null_range(vstruct_next(entry), next);
|
||||
return 0;
|
||||
return FSCK_DELETED_KEY;
|
||||
}
|
||||
|
||||
if (write)
|
||||
@@ -236,15 +250,17 @@ static int journal_entry_validate_btree_keys(struct bch_fs *c,
|
||||
struct jset_entry *entry,
|
||||
int write)
|
||||
{
|
||||
struct bkey_i *k;
|
||||
struct bkey_i *k = entry->start;
|
||||
|
||||
vstruct_for_each(entry, k) {
|
||||
while (k != vstruct_last(entry)) {
|
||||
int ret = journal_validate_key(c, jset, entry,
|
||||
entry->level,
|
||||
entry->btree_id,
|
||||
k, "key", write);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret == FSCK_DELETED_KEY)
|
||||
continue;
|
||||
|
||||
k = bkey_next(k);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user