bcachefs: Recover from blacklisted journal entries
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 14 Dec 2022 19:47:42 +0000 (14:47 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:48 +0000 (17:09 -0400)
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>
fs/bcachefs/journal_io.c
fs/bcachefs/recovery.c

index 854a0685db09dfb47d354d02eaeb36a08d1484b6..a54c060646471212c9064d5b1322e75cfb5d86cb 100644 (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;
                }
        }
 
index 15a676196e2fdac950af3e5f13eb441632412d46..976c336f294afe51e940635a07de3774271f9a0e 100644 (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);