From: Kent Overstreet <kent.overstreet@gmail.com>
Date: Thu, 3 Dec 2020 18:23:58 +0000 (-0500)
Subject: bcachefs: Check for errors in bch2_journal_reclaim()
X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=afa7cb0c36bd511362bcb03c6db8af74186176bf;p=linux.git

bcachefs: Check for errors in bch2_journal_reclaim()

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>
---

diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index 1c47d806fa9ca..e27ec0fbee2c5 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -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);
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c
index 1dabad6188702..4fd2b272e04ef 100644
--- a/fs/bcachefs/journal_reclaim.c
+++ b/fs/bcachefs/journal_reclaim.c
@@ -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);
diff --git a/fs/bcachefs/journal_reclaim.h b/fs/bcachefs/journal_reclaim.h
index e25355042e6e4..3404fef241ea1 100644
--- a/fs/bcachefs/journal_reclaim.h
+++ b/fs/bcachefs/journal_reclaim.h
@@ -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 *);