summaryrefslogtreecommitdiff
path: root/fs/bcachefs/journal_reclaim.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2020-12-16 23:41:29 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:08:50 +0300
commitd483dd17e2bfd6858498d39eb92abd232d7b8e97 (patch)
tree14accac982779273e6f2b769834aded96fc39de3 /fs/bcachefs/journal_reclaim.c
parentf30dd8601262c74caf148fe834418ad7c931af66 (diff)
downloadlinux-d483dd17e2bfd6858498d39eb92abd232d7b8e97.tar.xz
bcachefs: Fix race between journal_seq_copy() and journal_seq_drop()
In bch2_btree_interior_update_will_free_node, we copy the journal pins from outstanding writes on the btree node we're about to free. But, this can race with the writes completing, and dropping their journal pins. To guard against this, just use READ_ONCE() in bch2_journal_pin_copy(). Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/journal_reclaim.c')
-rw-r--r--fs/bcachefs/journal_reclaim.c14
1 files changed, 12 insertions, 2 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;