diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2022-12-14 14:47:42 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:48 -0400 |
commit | 1ba8a796b427d312aa68c2e04e00b42ec742883e (patch) | |
tree | 575f1dd06ce6c49e99a8746ee066f8c6efc146ec | |
parent | 14d7d61fac9c151a270c6ef6f969993eae9f1bbf (diff) | |
download | lwn-1ba8a796b427d312aa68c2e04e00b42ec742883e.tar.gz lwn-1ba8a796b427d312aa68c2e04e00b42ec742883e.zip |
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>
-rw-r--r-- | fs/bcachefs/journal_io.c | 10 | ||||
-rw-r--r-- | fs/bcachefs/recovery.c | 10 |
2 files changed, 12 insertions, 8 deletions
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index 854a0685db09..a54c06064647 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -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; } } diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 15a676196e2f..976c336f294a 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -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); |