From 24db24c749913f71cd90355528bad522cf197f62 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 31 Mar 2021 17:52:52 -0400 Subject: [PATCH] bcachefs: Don't make foreground writes wait behind journal reclaim too long Signed-off-by: Kent Overstreet Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_update_leaf.c | 33 +++++++++++++++++++++++++++------ fs/bcachefs/journal.c | 1 + fs/bcachefs/journal_reclaim.c | 6 ++++++ fs/bcachefs/journal_types.h | 1 + 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 8d0f469c808bd..a19a4a54a1ff2 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 87623ec8cf475..edbcbe7fb31f5 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 17af2bbeadeea..3ef42a47f60dc 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 8ad10e46dd5db..3db8c3760ccaa 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; -- 2.30.2