Add a new journal method for blocking new journal reservations and
waiting on outstanding reservations, to be used by the btree write
buffer flush path.

Signed-off-by: Kent Overstreet <[email protected]>
---
 fs/bcachefs/journal.c | 29 +++++++++++++++++++++++++++++
 fs/bcachefs/journal.h |  3 ++-
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index 3a6b73d4ec24..5b390cb91884 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -147,6 +147,7 @@ void bch2_journal_buf_put_final(struct journal *j, u64 seq, 
bool write)
                bch2_journal_reclaim_fast(j);
        if (write)
                closure_call(&j->io, bch2_journal_write, c->io_complete_wq, 
NULL);
+       wake_up(&j->wait);
 }
 
 /*
@@ -764,6 +765,34 @@ void bch2_journal_block(struct journal *j)
        journal_quiesce(j);
 }
 
+/*
+ * XXX: ideally this would not be closing the current journal entry, but
+ * otherwise we do not have a way to avoid racing with res_get() - j->blocked
+ * will race.
+ */
+static bool journal_reservations_stopped(struct journal *j)
+{
+       union journal_res_state s;
+
+       journal_entry_close(j);
+
+       s.v = atomic64_read_acquire(&j->reservations.counter);
+
+       return  s.buf0_count == 0 &&
+               s.buf1_count == 0 &&
+               s.buf2_count == 0 &&
+               s.buf3_count == 0;
+}
+
+void bch2_journal_block_reservations(struct journal *j)
+{
+       spin_lock(&j->lock);
+       j->blocked++;
+       spin_unlock(&j->lock);
+
+       wait_event(j->wait, journal_reservations_stopped(j));
+}
+
 /* allocate journal on a device: */
 
 static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr,
diff --git a/fs/bcachefs/journal.h b/fs/bcachefs/journal.h
index c85d01cf4948..310654bb74de 100644
--- a/fs/bcachefs/journal.h
+++ b/fs/bcachefs/journal.h
@@ -259,7 +259,7 @@ static inline union journal_res_state 
journal_state_buf_put(struct journal *j, u
 {
        union journal_res_state s;
 
-       s.v = atomic64_sub_return(((union journal_res_state) {
+       s.v = atomic64_sub_return_release(((union journal_res_state) {
                                    .buf0_count = idx == 0,
                                    .buf1_count = idx == 1,
                                    .buf2_count = idx == 2,
@@ -427,6 +427,7 @@ static inline void bch2_journal_set_replay_done(struct 
journal *j)
 
 void bch2_journal_unblock(struct journal *);
 void bch2_journal_block(struct journal *);
+void bch2_journal_block_reservations(struct journal *);
 
 void __bch2_journal_debug_to_text(struct printbuf *, struct journal *);
 void bch2_journal_debug_to_text(struct printbuf *, struct journal *);
-- 
2.42.0


Reply via email to