bcachefs: Check for errors in bch2_journal_reclaim()
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 3 Dec 2020 18:23:58 +0000 (13:23 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:49 +0000 (17:08 -0400)
If the journal is halted, journal reclaim won't necessarily be able to
make any forward progress, and won't accomplish anything anyways - we
should bail out so that we don't get stuck looping in reclaim when the
caches are too dirty and we should be shutting down.

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_reclaim.c
fs/bcachefs/journal_reclaim.h

index 1c47d806fa9ca8ce002b1b8bbe2f6ece828d8b70..e27ec0fbee2c5d6042dcf6db69061541ae8f3eb0 100644 (file)
@@ -659,13 +659,13 @@ int bch2_trans_commit_error(struct btree_trans *trans,
        case BTREE_INSERT_NEED_JOURNAL_RECLAIM:
                bch2_trans_unlock(trans);
 
-               while (bch2_btree_key_cache_must_wait(c)) {
+               do {
                        mutex_lock(&c->journal.reclaim_lock);
-                       bch2_journal_reclaim(&c->journal);
+                       ret = bch2_journal_reclaim(&c->journal);
                        mutex_unlock(&c->journal.reclaim_lock);
-               }
+               } while (!ret && bch2_btree_key_cache_must_wait(c));
 
-               if (bch2_trans_relock(trans))
+               if (!ret && bch2_trans_relock(trans))
                        return 0;
 
                trace_trans_restart_journal_reclaim(trans->ip);
index 1dabad61887024374e1be57de95fa7c40a4cfe9d..4fd2b272e04ef076a47eb7c63f38058ad6670315 100644 (file)
@@ -485,13 +485,14 @@ static u64 journal_seq_to_flush(struct journal *j)
  * 512 journal entries or 25% of all journal buckets, then
  * journal_next_bucket() should not stall.
  */
-static void __bch2_journal_reclaim(struct journal *j, bool direct)
+static int __bch2_journal_reclaim(struct journal *j, bool direct)
 {
        struct bch_fs *c = container_of(j, struct bch_fs, journal);
        bool kthread = (current->flags & PF_KTHREAD) != 0;
        u64 seq_to_flush, nr_flushed = 0;
        size_t min_nr;
        unsigned flags;
+       int ret = 0;
 
        /*
         * We can't invoke memory reclaim while holding the reclaim_lock -
@@ -506,6 +507,11 @@ static void __bch2_journal_reclaim(struct journal *j, bool direct)
                if (kthread && kthread_should_stop())
                        break;
 
+               if (bch2_journal_error(j)) {
+                       ret = -EIO;
+                       break;
+               }
+
                bch2_journal_do_discards(j);
 
                seq_to_flush = journal_seq_to_flush(j);
@@ -547,27 +553,30 @@ static void __bch2_journal_reclaim(struct journal *j, bool direct)
        } while (min_nr);
 
        memalloc_noreclaim_restore(flags);
+
+       return ret;
 }
 
-void bch2_journal_reclaim(struct journal *j)
+int bch2_journal_reclaim(struct journal *j)
 {
-       __bch2_journal_reclaim(j, true);
+       return __bch2_journal_reclaim(j, true);
 }
 
 static int bch2_journal_reclaim_thread(void *arg)
 {
        struct journal *j = arg;
        unsigned long next;
+       int ret = 0;
 
        set_freezable();
 
        kthread_wait_freezable(test_bit(JOURNAL_RECLAIM_STARTED, &j->flags));
 
-       while (!kthread_should_stop()) {
+       while (!ret && !kthread_should_stop()) {
                j->reclaim_kicked = false;
 
                mutex_lock(&j->reclaim_lock);
-               __bch2_journal_reclaim(j, false);
+               ret = __bch2_journal_reclaim(j, false);
                mutex_unlock(&j->reclaim_lock);
 
                next = j->last_flushed + msecs_to_jiffies(j->reclaim_delay_ms);
index e25355042e6e4c7a6d821fbbecd026eac753276b..3404fef241ea1eb22eedf55dc52efd20c4aec6ed 100644 (file)
@@ -73,7 +73,7 @@ static inline void bch2_journal_pin_update(struct journal *j, u64 seq,
 void bch2_journal_pin_flush(struct journal *, struct journal_entry_pin *);
 
 void bch2_journal_do_discards(struct journal *);
-void bch2_journal_reclaim(struct journal *);
+int bch2_journal_reclaim(struct journal *);
 
 void bch2_journal_reclaim_stop(struct journal *);
 int bch2_journal_reclaim_start(struct journal *);