Commit d483dd17 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

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: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent f30dd860
...@@ -384,12 +384,22 @@ void bch2_journal_pin_set(struct journal *j, u64 seq, ...@@ -384,12 +384,22 @@ void bch2_journal_pin_set(struct journal *j, u64 seq,
struct journal_entry_pin_list *pin_list; struct journal_entry_pin_list *pin_list;
spin_lock(&j->lock); 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); pin_list = journal_seq_pin(j, seq);
__journal_pin_drop(j, pin); __journal_pin_drop(j, pin);
BUG_ON(!atomic_read(&pin_list->count) && seq == journal_last_seq(j));
atomic_inc(&pin_list->count); atomic_inc(&pin_list->count);
pin->seq = seq; pin->seq = seq;
pin->flush = flush_fn; pin->flush = flush_fn;
......
...@@ -53,8 +53,11 @@ static inline void bch2_journal_pin_copy(struct journal *j, ...@@ -53,8 +53,11 @@ static inline void bch2_journal_pin_copy(struct journal *j,
struct journal_entry_pin *src, struct journal_entry_pin *src,
journal_pin_flush_fn flush_fn) journal_pin_flush_fn flush_fn)
{ {
if (journal_pin_active(src)) /* Guard against racing with journal_pin_drop(src): */
bch2_journal_pin_add(j, src->seq, dst, flush_fn); 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, static inline void bch2_journal_pin_update(struct journal *j, u64 seq,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment