bcachefs: Recover from blacklisted journal entries

If it so happens that we crash while dirty, meaning we don't have the
superblock clean section, and we erroneously mark a journal entry we
wrote as blacklisted, we won't be able to recover.

This patch fixes this by adding a fallback: if we've got no superblock
clean section, and no non-ignored journal entries, we try the most
recent ignored journal entry.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2022-12-14 14:47:42 -05:00
parent 14d7d61fac
commit 1ba8a796b4
2 changed files with 12 additions and 8 deletions

View file

@ -1123,9 +1123,6 @@ int bch2_journal_read(struct bch_fs *c, u64 *blacklist_seq, u64 *start_seq)
/*
* Find most recent flush entry, and ignore newer non flush entries -
* those entries will be blacklisted:
*
*
* XXX check for torn write on last journal entry
*/
genradix_for_each_reverse(&c->journal_entries, radix_iter, _i) {
int write = READ;
@ -1139,13 +1136,13 @@ int bch2_journal_read(struct bch_fs *c, u64 *blacklist_seq, u64 *start_seq)
*blacklist_seq = *start_seq = le64_to_cpu(i->j.seq) + 1;
if (JSET_NO_FLUSH(&i->j)) {
journal_replay_free(c, i);
i->ignore = true;
continue;
}
if (!last_write_torn && !i->csum_good) {
last_write_torn = true;
journal_replay_free(c, i);
i->ignore = true;
continue;
}
@ -1194,8 +1191,7 @@ int bch2_journal_read(struct bch_fs *c, u64 *blacklist_seq, u64 *start_seq)
if (bch2_journal_seq_is_blacklisted(c, seq, true)) {
fsck_err_on(!JSET_NO_FLUSH(&i->j), c,
"found blacklisted journal entry %llu", seq);
journal_replay_free(c, i);
i->ignore = true;
}
}

View file

@ -1137,7 +1137,15 @@ int bch2_fs_recovery(struct bch_fs *c)
if (!last_journal_entry) {
fsck_err_on(!c->sb.clean, c, "no journal entries found");
goto use_clean;
if (clean)
goto use_clean;
genradix_for_each_reverse(&c->journal_entries, iter, i)
if (*i) {
last_journal_entry = &(*i)->j;
(*i)->ignore = false;
break;
}
}
ret = journal_keys_sort(c);