bcachefs: Fix a deadlock on journal reclaim

Flushing the btree key cache needs to use allocation reserves - journal
reclaim depends on flushing the btree key cache for making forward
progress, and the allocator and copygc depend on journal reclaim making
forward progress.

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 2021-04-20 17:09:25 -04:00 committed by Kent Overstreet
parent 6adaac0b95
commit f09517fc51
3 changed files with 19 additions and 2 deletions

View File

@ -386,12 +386,18 @@ retry:
goto evict; goto evict;
} }
/*
* Since journal reclaim depends on us making progress here, and the
* allocator/copygc depend on journal reclaim making progress, we need
* to be using alloc reserves:
* */
ret = bch2_btree_iter_traverse(b_iter) ?: ret = bch2_btree_iter_traverse(b_iter) ?:
bch2_trans_update(trans, b_iter, ck->k, BTREE_TRIGGER_NORUN) ?: bch2_trans_update(trans, b_iter, ck->k, BTREE_TRIGGER_NORUN) ?:
bch2_trans_commit(trans, NULL, NULL, bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_NOUNLOCK| BTREE_INSERT_NOUNLOCK|
BTREE_INSERT_NOCHECK_RW| BTREE_INSERT_NOCHECK_RW|
BTREE_INSERT_NOFAIL| BTREE_INSERT_NOFAIL|
BTREE_INSERT_USE_RESERVE|
(ck->journal.seq == journal_last_seq(j) (ck->journal.seq == journal_last_seq(j)
? BTREE_INSERT_JOURNAL_RESERVED ? BTREE_INSERT_JOURNAL_RESERVED
: 0)| : 0)|

View File

@ -634,7 +634,7 @@ static int __bch2_journal_reclaim(struct journal *j, bool direct)
msecs_to_jiffies(j->reclaim_delay_ms))) msecs_to_jiffies(j->reclaim_delay_ms)))
min_nr = 1; min_nr = 1;
if (j->prereserved.reserved * 2 > j->prereserved.remaining) if (j->prereserved.reserved * 4 > j->prereserved.remaining)
min_nr = 1; min_nr = 1;
if (fifo_free(&j->pin) <= 32) if (fifo_free(&j->pin) <= 32)

View File

@ -87,9 +87,20 @@ static enum data_cmd copygc_pred(struct bch_fs *c, void *arg,
if (i >= 0 && if (i >= 0 &&
p.ptr.offset < h->data[i].offset + ca->mi.bucket_size && p.ptr.offset < h->data[i].offset + ca->mi.bucket_size &&
p.ptr.gen == h->data[i].gen) { p.ptr.gen == h->data[i].gen) {
/*
* We need to use the journal reserve here, because
* - journal reclaim depends on btree key cache
* flushing to make forward progress,
* - which has to make forward progress when the
* journal is pre-reservation full,
* - and depends on allocation - meaning allocator and
* copygc
*/
data_opts->target = io_opts->background_target; data_opts->target = io_opts->background_target;
data_opts->nr_replicas = 1; data_opts->nr_replicas = 1;
data_opts->btree_insert_flags = BTREE_INSERT_USE_RESERVE; data_opts->btree_insert_flags = BTREE_INSERT_USE_RESERVE|
BTREE_INSERT_JOURNAL_RESERVED;
data_opts->rewrite_dev = p.ptr.dev; data_opts->rewrite_dev = p.ptr.dev;
if (p.has_ec) if (p.has_ec)