summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2022-12-14 14:47:42 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:48 -0400
commit1ba8a796b427d312aa68c2e04e00b42ec742883e (patch)
tree575f1dd06ce6c49e99a8746ee066f8c6efc146ec /fs
parent14d7d61fac9c151a270c6ef6f969993eae9f1bbf (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/journal_io.c10
-rw-r--r--fs/bcachefs/recovery.c10
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);