bcachefs: Eliminate memory barrier from fast path of journal_preres_put()
authorKent Overstreet <kent.overstreet@gmail.com>
Sun, 4 Apr 2021 01:31:02 +0000 (21:31 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:59 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/journal.c
fs/bcachefs/journal.h
fs/bcachefs/journal_types.h

index bce056cb6841a4d1fb58dae66703edda41fcc38f..35a48629b63b5766f09af11f69fafcfd93eec85c 100644 (file)
@@ -520,7 +520,7 @@ static bool journal_preres_available(struct journal *j,
                                     unsigned new_u64s,
                                     unsigned flags)
 {
-       bool ret = bch2_journal_preres_get_fast(j, res, new_u64s, flags);
+       bool ret = bch2_journal_preres_get_fast(j, res, new_u64s, flags, true);
 
        if (!ret && mutex_trylock(&j->reclaim_lock)) {
                bch2_journal_reclaim(j);
index a0d19fad3bdd29f6ce8a0fef6919a365494eb909..cc497125889f2cbea8f3b754d3c72fd4c1c33aeb 100644 (file)
@@ -411,7 +411,12 @@ static inline void bch2_journal_preres_put(struct journal *j,
 
        s.v = atomic64_sub_return(s.v, &j->prereserved.counter);
        res->u64s = 0;
-       closure_wake_up(&j->preres_wait);
+
+       if (unlikely(s.waiting)) {
+               clear_bit(ilog2((((union journal_preres_state) { .waiting = 1 }).v)),
+                         (unsigned long *) &j->prereserved.v);
+               closure_wake_up(&j->preres_wait);
+       }
 
        if (s.reserved <= s.remaining &&
            !test_bit(JOURNAL_MAY_GET_UNRESERVED, &j->flags)) {
@@ -427,32 +432,32 @@ int __bch2_journal_preres_get(struct journal *,
 static inline int bch2_journal_preres_get_fast(struct journal *j,
                                               struct journal_preres *res,
                                               unsigned new_u64s,
-                                              unsigned flags)
+                                              unsigned flags,
+                                              bool set_waiting)
 {
        int d = new_u64s - res->u64s;
        union journal_preres_state old, new;
        u64 v = atomic64_read(&j->prereserved.counter);
+       int ret;
 
        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_RESERVED) &&
-                   new.reserved > new.remaining)
+               ret = 0;
+
+               if ((flags & JOURNAL_RES_GET_RESERVED) ||
+                   new.reserved + d < new.remaining) {
+                       new.reserved += d;
+                       ret = 1;
+               } else if (set_waiting && !new.waiting)
+                       new.waiting = true;
+               else
                        return 0;
        } while ((v = atomic64_cmpxchg(&j->prereserved.counter,
                                       old.v, new.v)) != old.v);
 
-       res->u64s += d;
-       return 1;
+       if (ret)
+               res->u64s += d;
+       return ret;
 }
 
 static inline int bch2_journal_preres_get(struct journal *j,
@@ -463,7 +468,7 @@ static inline int bch2_journal_preres_get(struct journal *j,
        if (new_u64s <= res->u64s)
                return 0;
 
-       if (bch2_journal_preres_get_fast(j, res, new_u64s, flags))
+       if (bch2_journal_preres_get_fast(j, res, new_u64s, flags, false))
                return 0;
 
        if (flags & JOURNAL_RES_GET_NONBLOCK)
index ec3c604cdf224c2d8a1327bdbb2c79dff5ebd882..97d764370b898dfd17bbd3c98552029fbd549c44 100644 (file)
@@ -105,8 +105,9 @@ union journal_preres_state {
        };
 
        struct {
-               u32             reserved;
-               u32             remaining;
+               u64             waiting:1,
+                               reserved:31,
+                               remaining:32;
        };
 };