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>
This commit is contained in:
Kent Overstreet 2020-12-03 13:23:58 -05:00 committed by Kent Overstreet
parent 33c74e4119
commit afa7cb0c36
3 changed files with 19 additions and 10 deletions

View File

@ -659,13 +659,13 @@ int bch2_trans_commit_error(struct btree_trans *trans,
case BTREE_INSERT_NEED_JOURNAL_RECLAIM: case BTREE_INSERT_NEED_JOURNAL_RECLAIM:
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
while (bch2_btree_key_cache_must_wait(c)) { do {
mutex_lock(&c->journal.reclaim_lock); mutex_lock(&c->journal.reclaim_lock);
bch2_journal_reclaim(&c->journal); ret = bch2_journal_reclaim(&c->journal);
mutex_unlock(&c->journal.reclaim_lock); 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; return 0;
trace_trans_restart_journal_reclaim(trans->ip); trace_trans_restart_journal_reclaim(trans->ip);

View File

@ -485,13 +485,14 @@ static u64 journal_seq_to_flush(struct journal *j)
* 512 journal entries or 25% of all journal buckets, then * 512 journal entries or 25% of all journal buckets, then
* journal_next_bucket() should not stall. * 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); struct bch_fs *c = container_of(j, struct bch_fs, journal);
bool kthread = (current->flags & PF_KTHREAD) != 0; bool kthread = (current->flags & PF_KTHREAD) != 0;
u64 seq_to_flush, nr_flushed = 0; u64 seq_to_flush, nr_flushed = 0;
size_t min_nr; size_t min_nr;
unsigned flags; unsigned flags;
int ret = 0;
/* /*
* We can't invoke memory reclaim while holding the reclaim_lock - * 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()) if (kthread && kthread_should_stop())
break; break;
if (bch2_journal_error(j)) {
ret = -EIO;
break;
}
bch2_journal_do_discards(j); bch2_journal_do_discards(j);
seq_to_flush = journal_seq_to_flush(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); } while (min_nr);
memalloc_noreclaim_restore(flags); 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) static int bch2_journal_reclaim_thread(void *arg)
{ {
struct journal *j = arg; struct journal *j = arg;
unsigned long next; unsigned long next;
int ret = 0;
set_freezable(); set_freezable();
kthread_wait_freezable(test_bit(JOURNAL_RECLAIM_STARTED, &j->flags)); kthread_wait_freezable(test_bit(JOURNAL_RECLAIM_STARTED, &j->flags));
while (!kthread_should_stop()) { while (!ret && !kthread_should_stop()) {
j->reclaim_kicked = false; j->reclaim_kicked = false;
mutex_lock(&j->reclaim_lock); mutex_lock(&j->reclaim_lock);
__bch2_journal_reclaim(j, false); ret = __bch2_journal_reclaim(j, false);
mutex_unlock(&j->reclaim_lock); mutex_unlock(&j->reclaim_lock);
next = j->last_flushed + msecs_to_jiffies(j->reclaim_delay_ms); next = j->last_flushed + msecs_to_jiffies(j->reclaim_delay_ms);

View 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_pin_flush(struct journal *, struct journal_entry_pin *);
void bch2_journal_do_discards(struct journal *); 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 *); void bch2_journal_reclaim_stop(struct journal *);
int bch2_journal_reclaim_start(struct journal *); int bch2_journal_reclaim_start(struct journal *);