summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-02-28 14:22:52 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:17 -0400
commit9ace606e93e9c6dff919ca8f35d461e8462590b7 (patch)
tree1392da42af426494cff2bd8150a8177799eba548 /fs
parent03d5eaed8624fdc7918478bffd05d67e773ac7d0 (diff)
downloadlinux-9ace606e93e9c6dff919ca8f35d461e8462590b7.tar.gz
linux-9ace606e93e9c6dff919ca8f35d461e8462590b7.tar.bz2
linux-9ace606e93e9c6dff919ca8f35d461e8462590b7.zip
bcachefs: Don't block on reclaim_lock from journal_res_get
When we're doing btree updates from journal flush, this becomes a locking inversion Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/journal.c5
-rw-r--r--fs/bcachefs/journal_reclaim.c23
-rw-r--r--fs/bcachefs/journal_reclaim.h1
3 files changed, 20 insertions, 9 deletions
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index 5caa01881d00..ba6adf11ef42 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -390,7 +390,10 @@ retry:
goto retry;
}
- bch2_journal_reclaim_work(&j->reclaim_work.work);
+ if (mutex_trylock(&j->reclaim_lock)) {
+ bch2_journal_reclaim(j);
+ mutex_unlock(&j->reclaim_lock);
+ }
}
ret = -EAGAIN;
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c
index 0884fc823cdf..a3c53b78ad10 100644
--- a/fs/bcachefs/journal_reclaim.c
+++ b/fs/bcachefs/journal_reclaim.c
@@ -433,7 +433,7 @@ static void journal_flush_pins(struct journal *j, u64 seq_to_flush,
}
/**
- * bch2_journal_reclaim_work - free up journal buckets
+ * bch2_journal_reclaim - free up journal buckets
*
* Background journal reclaim writes out btree nodes. It should be run
* early enough so that we never completely run out of journal buckets.
@@ -450,18 +450,17 @@ static void journal_flush_pins(struct journal *j, u64 seq_to_flush,
* 512 journal entries or 25% of all journal buckets, then
* journal_next_bucket() should not stall.
*/
-void bch2_journal_reclaim_work(struct work_struct *work)
+void bch2_journal_reclaim(struct journal *j)
{
- struct bch_fs *c = container_of(to_delayed_work(work),
- struct bch_fs, journal.reclaim_work);
- struct journal *j = &c->journal;
+ struct bch_fs *c = container_of(j, struct bch_fs, journal);
struct bch_dev *ca;
unsigned iter, bucket_to_flush, min_nr = 0;
u64 seq_to_flush = 0;
+ lockdep_assert_held(&j->reclaim_lock);
+
bch2_journal_do_discards(j);
- mutex_lock(&j->reclaim_lock);
spin_lock(&j->lock);
for_each_rw_member(ca, c, iter) {
@@ -493,13 +492,21 @@ void bch2_journal_reclaim_work(struct work_struct *work)
journal_flush_pins(j, seq_to_flush, min_nr);
- mutex_unlock(&j->reclaim_lock);
-
if (!test_bit(BCH_FS_RO, &c->flags))
queue_delayed_work(c->journal_reclaim_wq, &j->reclaim_work,
msecs_to_jiffies(j->reclaim_delay_ms));
}
+void bch2_journal_reclaim_work(struct work_struct *work)
+{
+ struct journal *j = container_of(to_delayed_work(work),
+ struct journal, reclaim_work);
+
+ mutex_lock(&j->reclaim_lock);
+ bch2_journal_reclaim(j);
+ mutex_unlock(&j->reclaim_lock);
+}
+
static int journal_flush_done(struct journal *j, u64 seq_to_flush)
{
int ret;
diff --git a/fs/bcachefs/journal_reclaim.h b/fs/bcachefs/journal_reclaim.h
index 71545ad3bd58..9bf982a17797 100644
--- a/fs/bcachefs/journal_reclaim.h
+++ b/fs/bcachefs/journal_reclaim.h
@@ -42,6 +42,7 @@ void bch2_journal_pin_add_if_older(struct journal *,
void bch2_journal_pin_flush(struct journal *, struct journal_entry_pin *);
void bch2_journal_do_discards(struct journal *);
+void bch2_journal_reclaim(struct journal *);
void bch2_journal_reclaim_work(struct work_struct *);
void bch2_journal_flush_pins(struct journal *, u64);