summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-03-31 17:52:52 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:58 -0400
commit24db24c749913f71cd90355528bad522cf197f62 (patch)
treec17da3fec4ad78a7a0b99e372ab0585d98d09cb6
parent65bcd6579df322d0c6216a534c65ee41eda2b801 (diff)
downloadlinux-stable-24db24c749913f71cd90355528bad522cf197f62.tar.gz
linux-stable-24db24c749913f71cd90355528bad522cf197f62.tar.bz2
linux-stable-24db24c749913f71cd90355528bad522cf197f62.zip
bcachefs: Don't make foreground writes wait behind journal reclaim too long
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/btree_update_leaf.c33
-rw-r--r--fs/bcachefs/journal.c1
-rw-r--r--fs/bcachefs/journal_reclaim.c6
-rw-r--r--fs/bcachefs/journal_types.h1
4 files changed, 35 insertions, 6 deletions
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index 8d0f469c808b..a19a4a54a1ff 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -586,6 +586,28 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans,
return 0;
}
+static int journal_reclaim_wait_done(struct bch_fs *c)
+{
+ int ret;
+
+ ret = bch2_journal_error(&c->journal);
+ if (ret)
+ return ret;
+
+ ret = !bch2_btree_key_cache_must_wait(c);
+ if (ret)
+ return ret;
+
+ if (mutex_trylock(&c->journal.reclaim_lock)) {
+ ret = bch2_journal_reclaim(&c->journal);
+ mutex_unlock(&c->journal.reclaim_lock);
+ }
+
+ if (!ret)
+ ret = !bch2_btree_key_cache_must_wait(c);
+ return ret;
+}
+
static noinline
int bch2_trans_commit_error(struct btree_trans *trans,
struct btree_insert_entry *i,
@@ -668,13 +690,12 @@ int bch2_trans_commit_error(struct btree_trans *trans,
case BTREE_INSERT_NEED_JOURNAL_RECLAIM:
bch2_trans_unlock(trans);
- do {
- mutex_lock(&c->journal.reclaim_lock);
- ret = bch2_journal_reclaim(&c->journal);
- mutex_unlock(&c->journal.reclaim_lock);
- } while (!ret && bch2_btree_key_cache_must_wait(c));
+ wait_event(c->journal.reclaim_wait,
+ (ret = journal_reclaim_wait_done(c)));
+ if (ret < 0)
+ return ret;
- if (!ret && bch2_trans_relock(trans))
+ if (bch2_trans_relock(trans))
return 0;
trace_trans_restart_journal_reclaim(trans->ip);
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index 87623ec8cf47..edbcbe7fb31f 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -1116,6 +1116,7 @@ int bch2_fs_journal_init(struct journal *j)
spin_lock_init(&j->err_lock);
init_waitqueue_head(&j->wait);
INIT_DELAYED_WORK(&j->write_work, journal_write_work);
+ init_waitqueue_head(&j->reclaim_wait);
init_waitqueue_head(&j->pin_flush_wait);
mutex_init(&j->reclaim_lock);
mutex_init(&j->discard_lock);
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c
index 17af2bbeadee..3ef42a47f60d 100644
--- a/fs/bcachefs/journal_reclaim.c
+++ b/fs/bcachefs/journal_reclaim.c
@@ -604,6 +604,9 @@ static int __bch2_journal_reclaim(struct journal *j, bool direct)
min_nr = max(min_nr, bch2_nr_btree_keys_want_flush(c));
+ /* Don't do too many without delivering wakeup: */
+ min_nr = min(min_nr, 128UL);
+
trace_journal_reclaim_start(c,
min_nr,
j->prereserved.reserved,
@@ -620,6 +623,9 @@ static int __bch2_journal_reclaim(struct journal *j, bool direct)
else
j->nr_background_reclaim += nr_flushed;
trace_journal_reclaim_finish(c, nr_flushed);
+
+ if (nr_flushed)
+ wake_up(&j->reclaim_wait);
} while (min_nr && nr_flushed);
memalloc_noreclaim_restore(flags);
diff --git a/fs/bcachefs/journal_types.h b/fs/bcachefs/journal_types.h
index 8ad10e46dd5d..3db8c3760cca 100644
--- a/fs/bcachefs/journal_types.h
+++ b/fs/bcachefs/journal_types.h
@@ -243,6 +243,7 @@ struct journal {
spinlock_t err_lock;
struct mutex reclaim_lock;
+ wait_queue_head_t reclaim_wait;
struct task_struct *reclaim_thread;
bool reclaim_kicked;
u64 nr_direct_reclaim;