summaryrefslogtreecommitdiff
path: root/fs/bcachefs/journal_reclaim.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2020-04-11 19:29:32 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:08:38 +0300
commit94035eed52f58a321fa28e938898535973bec847 (patch)
treefb9d64d55bd18c9dd5e2f9d7798b13349daaa9f1 /fs/bcachefs/journal_reclaim.c
parent58fb3e519a7612a01d9fc969aa4eca56b30d898e (diff)
downloadlinux-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.c17
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);
}
/**