diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c index be61d43458eb..fc3dd5bef386 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c @@ -132,13 +132,21 @@ journal_error_check_stuck(struct journal *j, int error, unsigned flags) return stuck; } -/* journal entry close/open: */ - -void bch2_journal_buf_put_final(struct journal *j) +/* + * Final processing when the last reference of a journal buffer has been + * dropped. Drop the pin list reference acquired at journal entry open and write + * the buffer, if requested. + */ +void bch2_journal_buf_put_final(struct journal *j, u64 seq, bool write) { struct bch_fs *c = container_of(j, struct bch_fs, journal); - closure_call(&j->io, bch2_journal_write, c->io_complete_wq, NULL); + lockdep_assert_held(&j->lock); + + if (__bch2_journal_pin_put(j, seq)) + bch2_journal_reclaim_fast(j); + if (write) + closure_call(&j->io, bch2_journal_write, c->io_complete_wq, NULL); } /* @@ -204,14 +212,11 @@ static void __journal_entry_close(struct journal *j, unsigned closed_val) buf->data->last_seq = cpu_to_le64(buf->last_seq); BUG_ON(buf->last_seq > le64_to_cpu(buf->data->seq)); - if (__bch2_journal_pin_put(j, le64_to_cpu(buf->data->seq))) - bch2_journal_reclaim_fast(j); - cancel_delayed_work(&j->write_work); bch2_journal_space_available(j); - bch2_journal_buf_put(j, old.idx); + __bch2_journal_buf_put(j, old.idx, le64_to_cpu(buf->data->seq)); } void bch2_journal_halt(struct journal *j) diff --git a/fs/bcachefs/journal.h b/fs/bcachefs/journal.h index 0a53a2142594..491133cc52f3 100644 --- a/fs/bcachefs/journal.h +++ b/fs/bcachefs/journal.h @@ -268,16 +268,26 @@ static inline union journal_res_state journal_state_buf_put(struct journal *j, u return s; } -void bch2_journal_buf_put_final(struct journal *); +void bch2_journal_buf_put_final(struct journal *, u64, bool); -static inline void bch2_journal_buf_put(struct journal *j, unsigned idx) +static inline void __bch2_journal_buf_put(struct journal *j, unsigned idx, u64 seq) +{ + union journal_res_state s; + + s = journal_state_buf_put(j, idx); + if (!journal_state_count(s, idx)) + bch2_journal_buf_put_final(j, seq, idx == s.unwritten_idx); +} + +static inline void bch2_journal_buf_put(struct journal *j, unsigned idx, u64 seq) { union journal_res_state s; s = journal_state_buf_put(j, idx); if (!journal_state_count(s, idx)) { - if (idx == s.unwritten_idx) - bch2_journal_buf_put_final(j); + spin_lock(&j->lock); + bch2_journal_buf_put_final(j, seq, idx == s.unwritten_idx); + spin_unlock(&j->lock); } } @@ -298,7 +308,7 @@ static inline void bch2_journal_res_put(struct journal *j, BCH_JSET_ENTRY_btree_keys, 0, 0, 0); - bch2_journal_buf_put(j, res->idx); + bch2_journal_buf_put(j, res->idx, res->seq); res->ref = 0; }