summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/journal_reclaim.c14
-rw-r--r--fs/bcachefs/journal_reclaim.h7
2 files changed, 17 insertions, 4 deletions
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c
index e8fd11abe4c3..1141b7d3a060 100644
--- a/fs/bcachefs/journal_reclaim.c
+++ b/fs/bcachefs/journal_reclaim.c
@@ -384,12 +384,22 @@ void bch2_journal_pin_set(struct journal *j, u64 seq,
struct journal_entry_pin_list *pin_list;
spin_lock(&j->lock);
+
+ if (seq < journal_last_seq(j)) {
+ /*
+ * bch2_journal_pin_copy() raced with bch2_journal_pin_drop() on
+ * the src pin - with the pin dropped, the entry to pin might no
+ * longer to exist, but that means there's no longer anything to
+ * copy and we can bail out here:
+ */
+ spin_unlock(&j->lock);
+ return;
+ }
+
pin_list = journal_seq_pin(j, seq);
__journal_pin_drop(j, pin);
- BUG_ON(!atomic_read(&pin_list->count) && seq == journal_last_seq(j));
-
atomic_inc(&pin_list->count);
pin->seq = seq;
pin->flush = flush_fn;
diff --git a/fs/bcachefs/journal_reclaim.h b/fs/bcachefs/journal_reclaim.h
index f02caa3d49ea..adf1f5c981cd 100644
--- a/fs/bcachefs/journal_reclaim.h
+++ b/fs/bcachefs/journal_reclaim.h
@@ -53,8 +53,11 @@ static inline void bch2_journal_pin_copy(struct journal *j,
struct journal_entry_pin *src,
journal_pin_flush_fn flush_fn)
{
- if (journal_pin_active(src))
- bch2_journal_pin_add(j, src->seq, dst, 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);
}
static inline void bch2_journal_pin_update(struct journal *j, u64 seq,