bcachefs: Handle last journal write being torn
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 20 Nov 2022 02:40:35 +0000 (21:40 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:46 +0000 (17:09 -0400)
If the last journal write didn't complete sucessfully due to a torn
write, we'll detect it as a checksum error. In that case, we should just
pretend that journal entry was never written.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/journal_io.c

index 485fd6f3003bf32afc9952f89cd3992197df862c..d1deb0573ffd2a30e1d167537d42aa4110a369c5 100644 (file)
@@ -1106,7 +1106,7 @@ int bch2_journal_read(struct bch_fs *c, u64 *blacklist_seq, u64 *start_seq)
        struct bch_dev *ca;
        unsigned iter;
        struct printbuf buf = PRINTBUF;
-       bool degraded = false;
+       bool degraded = false, last_write_torn = false;
        u64 seq, last_seq = 0;
        int ret = 0;
 
@@ -1142,8 +1142,13 @@ 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;
+
                i = *_i;
 
                if (!i || i->ignore)
@@ -1152,21 +1157,27 @@ int bch2_journal_read(struct bch_fs *c, u64 *blacklist_seq, u64 *start_seq)
                if (!*start_seq)
                        *blacklist_seq = *start_seq = le64_to_cpu(i->j.seq) + 1;
 
-               if (!JSET_NO_FLUSH(&i->j)) {
-                       int write = READ;
-                       if (journal_entry_err_on(le64_to_cpu(i->j.last_seq) > le64_to_cpu(i->j.seq),
-                                                c, &i->j, NULL,
-                                                "invalid journal entry: last_seq > seq (%llu > %llu)",
-                                                le64_to_cpu(i->j.last_seq),
-                                                le64_to_cpu(i->j.seq)))
-                               i->j.last_seq = i->j.seq;
-
-                       last_seq        = le64_to_cpu(i->j.last_seq);
-                       *blacklist_seq  = le64_to_cpu(i->j.seq) + 1;
-                       break;
+               if (JSET_NO_FLUSH(&i->j)) {
+                       journal_replay_free(c, i);
+                       continue;
                }
 
-               journal_replay_free(c, i);
+               if (!last_write_torn && !i->csum_good) {
+                       last_write_torn = true;
+                       journal_replay_free(c, i);
+                       continue;
+               }
+
+               if (journal_entry_err_on(le64_to_cpu(i->j.last_seq) > le64_to_cpu(i->j.seq),
+                                        c, &i->j, NULL,
+                                        "invalid journal entry: last_seq > seq (%llu > %llu)",
+                                        le64_to_cpu(i->j.last_seq),
+                                        le64_to_cpu(i->j.seq)))
+                       i->j.last_seq = i->j.seq;
+
+               last_seq        = le64_to_cpu(i->j.last_seq);
+               *blacklist_seq  = le64_to_cpu(i->j.seq) + 1;
+               break;
        }
 
        if (!*start_seq) {