summaryrefslogtreecommitdiff
path: root/fs/bcachefs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-04-20 17:09:25 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:01 -0400
commitf09517fc5136ad2ea67b6f332ed2445f053ccfe6 (patch)
tree67e6bbf58fb4ce196e2c9b6efbc8df4dda5426bf /fs/bcachefs
parent6adaac0b95dd39da290f6006822fbf7560d2d1b5 (diff)
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>
Diffstat (limited to 'fs/bcachefs')
-rw-r--r--fs/bcachefs/btree_key_cache.c6
-rw-r--r--fs/bcachefs/journal_reclaim.c2
-rw-r--r--fs/bcachefs/movinggc.c13
3 files changed, 19 insertions, 2 deletions
diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c
index ac844f47b8dd..0716c3314a36 100644
--- a/fs/bcachefs/btree_key_cache.c
+++ b/fs/bcachefs/btree_key_cache.c
@@ -386,12 +386,18 @@ retry:
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) ?:
bch2_trans_update(trans, b_iter, ck->k, BTREE_TRIGGER_NORUN) ?:
bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_NOUNLOCK|
BTREE_INSERT_NOCHECK_RW|
BTREE_INSERT_NOFAIL|
+ BTREE_INSERT_USE_RESERVE|
(ck->journal.seq == journal_last_seq(j)
? BTREE_INSERT_JOURNAL_RESERVED
: 0)|
diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c
index e2086c76d104..416f8611f008 100644
--- a/fs/bcachefs/journal_reclaim.c
+++ b/fs/bcachefs/journal_reclaim.c
@@ -634,7 +634,7 @@ static int __bch2_journal_reclaim(struct journal *j, bool direct)
msecs_to_jiffies(j->reclaim_delay_ms)))
min_nr = 1;
- if (j->prereserved.reserved * 2 > j->prereserved.remaining)
+ if (j->prereserved.reserved * 4 > j->prereserved.remaining)
min_nr = 1;
if (fifo_free(&j->pin) <= 32)
diff --git a/fs/bcachefs/movinggc.c b/fs/bcachefs/movinggc.c
index 3d57a72e63e4..f9146ccd70ef 100644
--- a/fs/bcachefs/movinggc.c
+++ b/fs/bcachefs/movinggc.c
@@ -87,9 +87,20 @@ static enum data_cmd copygc_pred(struct bch_fs *c, void *arg,
if (i >= 0 &&
p.ptr.offset < h->data[i].offset + ca->mi.bucket_size &&
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->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;
if (p.has_ec)