bcachefs: Fix journal_buf bitfield accesses
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 17 Feb 2024 22:54:39 +0000 (17:54 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 14 Mar 2024 01:22:25 +0000 (21:22 -0400)
All jounal_buf bitfield updates must happen under the journal lock -
perhaps we should just switch these to atomic bit flags.

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

index ac7844861966368cdce41efd9e27c898fe8ad6e7..a7d86252690a72e2f5aed466adfba742ae6b85ed 100644 (file)
@@ -590,7 +590,9 @@ static int bch2_journal_keys_to_write_buffer(struct bch_fs *c, struct journal_bu
                entry->type = BCH_JSET_ENTRY_btree_keys;
        }
 
+       spin_lock(&c->journal.lock);
        buf->need_flush_to_write_buffer = false;
+       spin_unlock(&c->journal.lock);
 out:
        bch2_journal_keys_to_write_buffer_end(c, &dst);
        return ret;
index c4f19b996b45f01078ee09d86eeb16f8cac13d05..3aff628e05caedefbbf2d7ae5cedd6f4b4da5b58 100644 (file)
@@ -1831,7 +1831,10 @@ static int bch2_journal_write_prep(struct journal *j, struct journal_buf *w)
 
        if (wb.wb)
                bch2_journal_keys_to_write_buffer_end(c, &wb);
+
+       spin_lock(&c->journal.lock);
        w->need_flush_to_write_buffer = false;
+       spin_unlock(&c->journal.lock);
 
        start = end = vstruct_last(jset);
 
@@ -1949,12 +1952,20 @@ CLOSURE_CALLBACK(bch2_journal_write)
        unsigned nr_rw_members = 0;
        int ret;
 
+       for_each_rw_member(c, ca)
+               nr_rw_members++;
+
        BUG_ON(BCH_SB_CLEAN(c->disk_sb.sb));
+       BUG_ON(!w->write_started);
        BUG_ON(w->write_allocated);
+       BUG_ON(w->write_done);
 
        j->write_start_time = local_clock();
 
        spin_lock(&j->lock);
+       if (nr_rw_members > 1)
+               w->separate_flush = true;
+
        ret = bch2_journal_write_pick_flush(j, w);
        spin_unlock(&j->lock);
        if (ret)
@@ -2009,12 +2020,6 @@ CLOSURE_CALLBACK(bch2_journal_write)
        if (c->opts.nochanges)
                goto no_io;
 
-       for_each_rw_member(c, ca)
-               nr_rw_members++;
-
-       if (nr_rw_members > 1)
-               w->separate_flush = true;
-
        /*
         * Mark journal replicas before we submit the write to guarantee
         * recovery will find the journal entries after a crash.