bcachefs: Fix livelock in journal_entry_open()

When the journal is low on space, we might do discards from
journal_res_get() -> journal_entry_open().

Make sure we set j->can_discard correctly, so that if we're low on space
but not because discards aren't keeping up we don't livelock.

Fixes: 8e4d28036c ("bcachefs: Don't aggressively discard the journal")
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2025-05-13 12:55:44 -04:00
parent b1c71cb492
commit 7b6759b199

View File

@ -17,6 +17,8 @@
#include <linux/kthread.h>
#include <linux/sched/mm.h>
static bool __should_discard_bucket(struct journal *, struct journal_device *);
/* Free space calculations: */
static unsigned journal_space_from(struct journal_device *ja,
@ -203,8 +205,7 @@ void bch2_journal_space_available(struct journal *j)
ja->bucket_seq[ja->dirty_idx_ondisk] < j->last_seq_ondisk)
ja->dirty_idx_ondisk = (ja->dirty_idx_ondisk + 1) % ja->nr;
if (ja->discard_idx != ja->dirty_idx_ondisk)
can_discard = true;
can_discard |= __should_discard_bucket(j, ja);
max_entry_size = min_t(unsigned, max_entry_size, ca->mi.bucket_size);
nr_online++;
@ -264,13 +265,19 @@ void bch2_journal_space_available(struct journal *j)
/* Discards - last part of journal reclaim: */
static bool __should_discard_bucket(struct journal *j, struct journal_device *ja)
{
unsigned min_free = max(4, ja->nr / 8);
return bch2_journal_dev_buckets_available(j, ja, journal_space_discarded) <
min_free &&
ja->discard_idx != ja->dirty_idx_ondisk;
}
static bool should_discard_bucket(struct journal *j, struct journal_device *ja)
{
spin_lock(&j->lock);
unsigned min_free = max(4, ja->nr / 8);
bool ret = bch2_journal_dev_buckets_available(j, ja, journal_space_discarded) < min_free &&
ja->discard_idx != ja->dirty_idx_ondisk;
bool ret = __should_discard_bucket(j, ja);
spin_unlock(&j->lock);
return ret;