diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2020-04-11 19:29:32 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:08:38 +0300 |
commit | 94035eed52f58a321fa28e938898535973bec847 (patch) | |
tree | fb9d64d55bd18c9dd5e2f9d7798b13349daaa9f1 /fs/bcachefs/journal_reclaim.c | |
parent | 58fb3e519a7612a01d9fc969aa4eca56b30d898e (diff) | |
download | linux-94035eed52f58a321fa28e938898535973bec847.tar.xz |
bcachefs: Fix a locking bug in bch2_journal_pin_copy()
There was a race where the src pin would be flushed - releasing the last
pin on that sequence number - before adding the new journal pin. Oops.
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.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c index 5233cb82d422..341106ab4a77 100644 --- a/fs/bcachefs/journal_reclaim.c +++ b/fs/bcachefs/journal_reclaim.c @@ -322,14 +322,12 @@ void bch2_journal_pin_drop(struct journal *j, spin_unlock(&j->lock); } -void __bch2_journal_pin_add(struct journal *j, u64 seq, +static void bch2_journal_pin_add_locked(struct journal *j, u64 seq, struct journal_entry_pin *pin, journal_pin_flush_fn flush_fn) { struct journal_entry_pin_list *pin_list = journal_seq_pin(j, seq); - spin_lock(&j->lock); - __journal_pin_drop(j, pin); BUG_ON(!atomic_read(&pin_list->count)); @@ -339,7 +337,14 @@ void __bch2_journal_pin_add(struct journal *j, u64 seq, pin->flush = flush_fn; list_add(&pin->list, flush_fn ? &pin_list->list : &pin_list->flushed); +} +void __bch2_journal_pin_add(struct journal *j, u64 seq, + struct journal_entry_pin *pin, + journal_pin_flush_fn flush_fn) +{ + spin_lock(&j->lock); + bch2_journal_pin_add_locked(j, seq, pin, flush_fn); spin_unlock(&j->lock); /* @@ -354,9 +359,13 @@ void bch2_journal_pin_copy(struct journal *j, struct journal_entry_pin *src, journal_pin_flush_fn flush_fn) { + spin_lock(&j->lock); + if (journal_pin_active(src) && (!journal_pin_active(dst) || src->seq < dst->seq)) - __bch2_journal_pin_add(j, src->seq, dst, flush_fn); + bch2_journal_pin_add_locked(j, src->seq, dst, flush_fn); + + spin_unlock(&j->lock); } /** |