]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Can now block journal activity without closing cur entry
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 23 Nov 2024 21:27:47 +0000 (16:27 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Dec 2024 06:36:19 +0000 (01:36 -0500)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/journal.c
fs/bcachefs/journal.h
fs/bcachefs/journal_types.h

index 2cf8f24d50cc2b30dff04c7f3cbaf5861b5b0999..bfbb1ac60c3d53971b98721b5193361547cf2f41 100644 (file)
@@ -217,6 +217,12 @@ void bch2_journal_buf_put_final(struct journal *j, u64 seq)
        if (__bch2_journal_pin_put(j, seq))
                bch2_journal_reclaim_fast(j);
        bch2_journal_do_writes(j);
+
+       /*
+        * for __bch2_next_write_buffer_flush_journal_buf(), when quiescing an
+        * open journal entry
+        */
+       wake_up(&j->wait);
 }
 
 /*
@@ -251,6 +257,9 @@ static void __journal_entry_close(struct journal *j, unsigned closed_val, bool t
        if (!__journal_entry_is_open(old))
                return;
 
+       if (old.cur_entry_offset == JOURNAL_ENTRY_BLOCKED_VAL)
+               old.cur_entry_offset = j->cur_entry_offset_if_blocked;
+
        /* Close out old buffer: */
        buf->data->u64s         = cpu_to_le32(old.cur_entry_offset);
 
@@ -868,16 +877,44 @@ int bch2_journal_meta(struct journal *j)
 void bch2_journal_unblock(struct journal *j)
 {
        spin_lock(&j->lock);
-       j->blocked--;
+       if (!--j->blocked &&
+           j->cur_entry_offset_if_blocked < JOURNAL_ENTRY_CLOSED_VAL &&
+           j->reservations.cur_entry_offset == JOURNAL_ENTRY_BLOCKED_VAL) {
+               union journal_res_state old, new;
+
+               old.v = atomic64_read(&j->reservations.counter);
+               do {
+                       new.v = old.v;
+                       new.cur_entry_offset = j->cur_entry_offset_if_blocked;
+               } while (!atomic64_try_cmpxchg(&j->reservations.counter, &old.v, new.v));
+       }
        spin_unlock(&j->lock);
 
        journal_wake(j);
 }
 
+static void __bch2_journal_block(struct journal *j)
+{
+       if (!j->blocked++) {
+               union journal_res_state old, new;
+
+               old.v = atomic64_read(&j->reservations.counter);
+               do {
+                       j->cur_entry_offset_if_blocked = old.cur_entry_offset;
+
+                       if (j->cur_entry_offset_if_blocked >= JOURNAL_ENTRY_CLOSED_VAL)
+                               break;
+
+                       new.v = old.v;
+                       new.cur_entry_offset = JOURNAL_ENTRY_BLOCKED_VAL;
+               } while (!atomic64_try_cmpxchg(&j->reservations.counter, &old.v, new.v));
+       }
+}
+
 void bch2_journal_block(struct journal *j)
 {
        spin_lock(&j->lock);
-       j->blocked++;
+       __bch2_journal_block(j);
        spin_unlock(&j->lock);
 
        journal_quiesce(j);
@@ -1481,6 +1518,9 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
        case JOURNAL_ENTRY_CLOSED_VAL:
                prt_printf(out, "closed\n");
                break;
+       case JOURNAL_ENTRY_BLOCKED_VAL:
+               prt_printf(out, "blocked\n");
+               break;
        default:
                prt_printf(out, "%u/%u\n", s.cur_entry_offset, j->cur_entry_u64s);
                break;
index 2762be6f9814c9c0417d08279abc7d0e66d7de49..6d3c839bbbefcc0254ff1394bd39003529e79ba9 100644 (file)
@@ -285,7 +285,8 @@ static inline void bch2_journal_buf_put(struct journal *j, unsigned idx, u64 seq
                spin_lock(&j->lock);
                bch2_journal_buf_put_final(j, seq);
                spin_unlock(&j->lock);
-       }
+       } else if (unlikely(s.cur_entry_offset == JOURNAL_ENTRY_BLOCKED_VAL))
+               wake_up(&j->wait);
 }
 
 /*
index 19183fcf7ad7fd031ba263da226ecb21e9d04685..425d1abb257ee227b52b489fce697080cd541571 100644 (file)
@@ -112,6 +112,7 @@ union journal_res_state {
  */
 #define JOURNAL_ENTRY_OFFSET_MAX       ((1U << 20) - 1)
 
+#define JOURNAL_ENTRY_BLOCKED_VAL      (JOURNAL_ENTRY_OFFSET_MAX - 2)
 #define JOURNAL_ENTRY_CLOSED_VAL       (JOURNAL_ENTRY_OFFSET_MAX - 1)
 #define JOURNAL_ENTRY_ERROR_VAL                (JOURNAL_ENTRY_OFFSET_MAX)
 
@@ -193,6 +194,7 @@ struct journal {
         * insufficient devices:
         */
        enum journal_errors     cur_entry_error;
+       unsigned                cur_entry_offset_if_blocked;
 
        unsigned                buf_size_want;
        /*