bcachefs: Don't make foreground writes wait behind journal reclaim too long
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 31 Mar 2021 21:52:52 +0000 (17:52 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:58 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_update_leaf.c
fs/bcachefs/journal.c
fs/bcachefs/journal_reclaim.c
fs/bcachefs/journal_types.h

index 8d0f469c808bd7c6dbb3226f2ffa748643a3a65c..a19a4a54a1ff28d0b1811cabd6ba641500ecfbd0 100644 (file)
@@ -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);
index 87623ec8cf4755de034e960429b9e6bcf5978b6f..edbcbe7fb31f59aeb200fa3b7e86477dbad44cdb 100644 (file)
@@ -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);
index 17af2bbeadeea1a4634dffda9a45b4912387e473..3ef42a47f60dc26b1bab5b7fa86350612883d137 100644 (file)
@@ -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);
index 8ad10e46dd5dbeb56c3d9b1e3994f1ee00ed7f96..3db8c3760ccaafc5db5a54be9047443919ca6888 100644 (file)
@@ -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;