]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Add an assertion in bch2_journal_pin_set()
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 7 Nov 2023 17:32:50 +0000 (12:32 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 1 Jan 2024 16:47:37 +0000 (11:47 -0500)
Previously, bch2_journal_pin_set() would silently ignore a request to
pin a journal sequence number that was no longer dirty, because it was
used internally by bch2_journal_pin_copy() which could race with the src
pin being flushed.

Split these apart so that we can properly assert that @seq is a
currently dirty journal sequence number - this is almost always a bug.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/journal_reclaim.c
fs/bcachefs/journal_reclaim.h

index ec712104addb32c94a1baa350a4bb3a43304c8b2..f2668d9d8e2432a597cafc3de5b52b75492d74af 100644 (file)
@@ -367,15 +367,34 @@ static enum journal_pin_type journal_pin_type(journal_pin_flush_fn fn)
                return JOURNAL_PIN_other;
 }
 
-void bch2_journal_pin_set(struct journal *j, u64 seq,
+static inline void bch2_journal_pin_set_locked(struct journal *j, u64 seq,
                          struct journal_entry_pin *pin,
-                         journal_pin_flush_fn flush_fn)
+                         journal_pin_flush_fn flush_fn,
+                         enum journal_pin_type type)
+{
+       struct journal_entry_pin_list *pin_list = journal_seq_pin(j, seq);
+
+       atomic_inc(&pin_list->count);
+       pin->seq        = seq;
+       pin->flush      = flush_fn;
+
+       if (flush_fn)
+               list_add(&pin->list, &pin_list->list[type]);
+       else
+               list_add(&pin->list, &pin_list->flushed);
+}
+
+void bch2_journal_pin_copy(struct journal *j,
+                          struct journal_entry_pin *dst,
+                          struct journal_entry_pin *src,
+                          journal_pin_flush_fn flush_fn)
 {
-       struct journal_entry_pin_list *pin_list;
        bool reclaim;
 
        spin_lock(&j->lock);
 
+       u64 seq = READ_ONCE(src->seq);
+
        if (seq < journal_last_seq(j)) {
                /*
                 * bch2_journal_pin_copy() raced with bch2_journal_pin_drop() on
@@ -387,18 +406,34 @@ void bch2_journal_pin_set(struct journal *j, u64 seq,
                return;
        }
 
-       pin_list = journal_seq_pin(j, seq);
+       reclaim = __journal_pin_drop(j, dst);
 
-       reclaim = __journal_pin_drop(j, pin);
+       bch2_journal_pin_set_locked(j, seq, dst, flush_fn, journal_pin_type(flush_fn));
 
-       atomic_inc(&pin_list->count);
-       pin->seq        = seq;
-       pin->flush      = flush_fn;
+       if (reclaim)
+               bch2_journal_reclaim_fast(j);
+       spin_unlock(&j->lock);
 
-       if (flush_fn)
-               list_add(&pin->list, &pin_list->list[journal_pin_type(flush_fn)]);
-       else
-               list_add(&pin->list, &pin_list->flushed);
+       /*
+        * If the journal is currently full,  we might want to call flush_fn
+        * immediately:
+        */
+       journal_wake(j);
+}
+
+void bch2_journal_pin_set(struct journal *j, u64 seq,
+                         struct journal_entry_pin *pin,
+                         journal_pin_flush_fn flush_fn)
+{
+       bool reclaim;
+
+       spin_lock(&j->lock);
+
+       BUG_ON(seq < journal_last_seq(j));
+
+       reclaim = __journal_pin_drop(j, pin);
+
+       bch2_journal_pin_set_locked(j, seq, pin, flush_fn, journal_pin_type(flush_fn));
 
        if (reclaim)
                bch2_journal_reclaim_fast(j);
index 494d1a6eddb011fd5c0aa0b41676522949b12577..7b15d682a0f51d28c47f7d881edb1b08ca24d10c 100644 (file)
@@ -47,17 +47,10 @@ static inline void bch2_journal_pin_add(struct journal *j, u64 seq,
                bch2_journal_pin_set(j, seq, pin, flush_fn);
 }
 
-static inline void bch2_journal_pin_copy(struct journal *j,
-                                        struct journal_entry_pin *dst,
-                                        struct journal_entry_pin *src,
-                                        journal_pin_flush_fn flush_fn)
-{
-       /* Guard against racing with journal_pin_drop(src): */
-       u64 seq = READ_ONCE(src->seq);
-
-       if (seq)
-               bch2_journal_pin_add(j, seq, dst, flush_fn);
-}
+void bch2_journal_pin_copy(struct journal *,
+                          struct journal_entry_pin *,
+                          struct journal_entry_pin *,
+                          journal_pin_flush_fn);
 
 static inline void bch2_journal_pin_update(struct journal *j, u64 seq,
                                           struct journal_entry_pin *pin,