bcachefs: Fix error reporting from bch2_journal_flush_seq
authorKent Overstreet <kent.overstreet@gmail.com>
Mon, 15 Nov 2021 22:30:11 +0000 (17:30 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:17 +0000 (17:09 -0400)
- bch2_journal_halt() was unconditionally overwriting j->err_seq, the
  sequence number that we failed to write
- journal_write_done was updating seq_ondisk and flushed_seq_ondisk even
  for writes that errored, which broke the way bch2_journal_flush_seq_async()
  locklessly checked for completions.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/journal.c
fs/bcachefs/journal_io.c
fs/bcachefs/recovery.c

index 1ee012d94b4aeea9382649eccf5413be18f9175d..56c477bbce0fbced56eaad633fa1d21d569443bd 100644 (file)
@@ -106,7 +106,12 @@ void bch2_journal_halt(struct journal *j)
        } while ((v = atomic64_cmpxchg(&j->reservations.counter,
                                       old.v, new.v)) != old.v);
 
-       j->err_seq = journal_cur_seq(j);
+       /*
+        * XXX: we're not using j->lock here because this can be called from
+        * interrupt context, this can race with journal_write_done()
+        */
+       if (!j->err_seq)
+               j->err_seq = journal_cur_seq(j);
        journal_wake(j);
        closure_wake_up(&journal_cur_buf(j)->wait);
 }
index ed8d7f90b6071dc47cdaf80af5eb038531dbf322..0cd5ad3118e908c4af6d221c115085cb50d98af0 100644 (file)
@@ -1258,14 +1258,15 @@ static void journal_write_done(struct closure *cl)
        if (seq >= j->pin.front)
                journal_seq_pin(j, seq)->devs = w->devs_written;
 
-       j->seq_ondisk           = seq;
-       if (err && (!j->err_seq || seq < j->err_seq))
-               j->err_seq      = seq;
+       if (!err) {
+               j->seq_ondisk           = seq;
 
-       if (!JSET_NO_FLUSH(w->data)) {
-               j->flushed_seq_ondisk = seq;
-               j->last_seq_ondisk = w->last_seq;
-       }
+               if (!JSET_NO_FLUSH(w->data)) {
+                       j->flushed_seq_ondisk = seq;
+                       j->last_seq_ondisk = w->last_seq;
+               }
+       } else if (!j->err_seq || seq < j->err_seq)
+               j->err_seq      = seq;
 
        /*
         * Updating last_seq_ondisk may let bch2_journal_reclaim_work() discard
index be89126055271a6a6644a734580f55cb5af22ce5..c3b4d116275cd6e5621941d1765491d7c80ecbaf 100644 (file)
@@ -1480,7 +1480,7 @@ int bch2_fs_initialize(struct bch_fs *c)
        }
 
        err = "error writing first journal entry";
-       ret = bch2_journal_meta(&c->journal);
+       ret = bch2_journal_flush(&c->journal);
        if (ret)
                goto err;