From 4d54337cdbf3baf8115bf8c1ed61bf44b3932a6d Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 16 Nov 2020 12:22:30 -0500 Subject: [PATCH] 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 Signed-off-by: Kent Overstreet --- fs/bcachefs/journal_io.c | 48 ++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index a6fb4fb207a2..354d57a3cd59 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -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;