Commit 4d54337c authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

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: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 628a3ad2
...@@ -160,6 +160,8 @@ static void journal_entry_null_range(void *start, void *end) ...@@ -160,6 +160,8 @@ static void journal_entry_null_range(void *start, void *end)
#define journal_entry_err_on(cond, c, msg, ...) \ #define journal_entry_err_on(cond, c, msg, ...) \
((cond) ? journal_entry_err(c, msg, ##__VA_ARGS__) : false) ((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, static int journal_validate_key(struct bch_fs *c, struct jset *jset,
struct jset_entry *entry, struct jset_entry *entry,
unsigned level, enum btree_id btree_id, unsigned level, enum btree_id btree_id,
...@@ -172,33 +174,42 @@ static int journal_validate_key(struct bch_fs *c, struct jset *jset, ...@@ -172,33 +174,42 @@ static int journal_validate_key(struct bch_fs *c, struct jset *jset,
int ret = 0; int ret = 0;
if (journal_entry_err_on(!k->k.u64s, c, 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), 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); entry->u64s = cpu_to_le16((u64 *) k - entry->_data);
journal_entry_null_range(vstruct_next(entry), next); journal_entry_null_range(vstruct_next(entry), next);
return 0; return FSCK_DELETED_KEY;
} }
if (journal_entry_err_on((void *) bkey_next(k) > if (journal_entry_err_on((void *) bkey_next(k) >
(void *) vstruct_next(entry), c, (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), 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); entry->u64s = cpu_to_le16((u64 *) k - entry->_data);
journal_entry_null_range(vstruct_next(entry), next); 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, 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), 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),
k->k.format)) { 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)); memmove(k, bkey_next(k), next - (void *) bkey_next(k));
journal_entry_null_range(vstruct_next(entry), next); journal_entry_null_range(vstruct_next(entry), next);
return 0; return FSCK_DELETED_KEY;
} }
if (!write) if (!write)
...@@ -212,15 +223,18 @@ static int journal_validate_key(struct bch_fs *c, struct jset *jset, ...@@ -212,15 +223,18 @@ static int journal_validate_key(struct bch_fs *c, struct jset *jset,
char buf[160]; char buf[160];
bch2_bkey_val_to_text(&PBUF(buf), c, bkey_i_to_s_c(k)); 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), 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),
invalid, buf); 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)); memmove(k, bkey_next(k), next - (void *) bkey_next(k));
journal_entry_null_range(vstruct_next(entry), next); journal_entry_null_range(vstruct_next(entry), next);
return 0; return FSCK_DELETED_KEY;
} }
if (write) if (write)
...@@ -236,15 +250,17 @@ static int journal_entry_validate_btree_keys(struct bch_fs *c, ...@@ -236,15 +250,17 @@ static int journal_entry_validate_btree_keys(struct bch_fs *c,
struct jset_entry *entry, struct jset_entry *entry,
int write) 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, int ret = journal_validate_key(c, jset, entry,
entry->level, entry->level,
entry->btree_id, entry->btree_id,
k, "key", write); k, "key", write);
if (ret) if (ret == FSCK_DELETED_KEY)
return ret; continue;
k = bkey_next(k);
} }
return 0; return 0;
......
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