diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-03-31 17:52:52 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:58 -0400 |
commit | 24db24c749913f71cd90355528bad522cf197f62 (patch) | |
tree | c17da3fec4ad78a7a0b99e372ab0585d98d09cb6 | |
parent | 65bcd6579df322d0c6216a534c65ee41eda2b801 (diff) | |
download | linux-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.c | 33 | ||||
-rw-r--r-- | fs/bcachefs/journal.c | 1 | ||||
-rw-r--r-- | fs/bcachefs/journal_reclaim.c | 6 | ||||
-rw-r--r-- | 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 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; |