+static inline bool journal_check_may_get_unreserved(struct journal *j)
+{
+ union journal_preres_state s = READ_ONCE(j->prereserved);
+ bool ret = s.reserved <= s.remaining &&
+ fifo_free(&j->pin) > 8;
+
+ lockdep_assert_held(&j->lock);
+
+ if (ret != test_bit(JOURNAL_MAY_GET_UNRESERVED, &j->flags)) {
+ if (ret) {
+ set_bit(JOURNAL_MAY_GET_UNRESERVED, &j->flags);
+ journal_wake(j);
+ } else {
+ clear_bit(JOURNAL_MAY_GET_UNRESERVED, &j->flags);
+ }
+ }
+ return ret;
+}
+
+static inline void bch2_journal_preres_put(struct journal *j,
+ struct journal_preres *res)
+{
+ union journal_preres_state s = { .reserved = res->u64s };
+
+ if (!res->u64s)
+ return;
+
+ s.v = atomic64_sub_return(s.v, &j->prereserved.counter);
+ res->u64s = 0;
+ closure_wake_up(&j->preres_wait);
+
+ if (s.reserved <= s.remaining &&
+ !test_bit(JOURNAL_MAY_GET_UNRESERVED, &j->flags)) {
+ spin_lock(&j->lock);
+ journal_check_may_get_unreserved(j);
+ spin_unlock(&j->lock);
+ }
+}
+
+int __bch2_journal_preres_get(struct journal *,
+ struct journal_preres *, unsigned, unsigned);
+
+static inline int bch2_journal_preres_get_fast(struct journal *j,
+ struct journal_preres *res,
+ unsigned new_u64s,
+ unsigned flags)
+{
+ int d = new_u64s - res->u64s;
+ union journal_preres_state old, new;
+ u64 v = atomic64_read(&j->prereserved.counter);
+
+ do {
+ old.v = new.v = v;
+
+ new.reserved += d;
+
+ /*
+ * If we're being called from the journal reclaim path, we have
+ * to unconditionally give out the pre-reservation, there's
+ * nothing else sensible we can do - otherwise we'd recurse back
+ * into the reclaim path and deadlock:
+ */
+
+ if (!(flags & JOURNAL_RES_GET_RECLAIM) &&
+ new.reserved > new.remaining)
+ return 0;
+ } while ((v = atomic64_cmpxchg(&j->prereserved.counter,
+ old.v, new.v)) != old.v);
+
+ res->u64s += d;
+ return 1;
+}
+
+static inline int bch2_journal_preres_get(struct journal *j,
+ struct journal_preres *res,
+ unsigned new_u64s,
+ unsigned flags)
+{
+ if (new_u64s <= res->u64s)
+ return 0;
+
+ if (bch2_journal_preres_get_fast(j, res, new_u64s, flags))
+ return 0;
+
+ if (flags & JOURNAL_RES_GET_NONBLOCK)
+ return -EAGAIN;
+
+ return __bch2_journal_preres_get(j, res, new_u64s, flags);
+}
+
+/* journal_entry_res: */
+
+void bch2_journal_entry_res_resize(struct journal *,
+ struct journal_entry_res *,
+ unsigned);
+
+int bch2_journal_flush_seq_async(struct journal *, u64, struct closure *);