Commit 7b6759b1 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

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: 8e4d2803 ("bcachefs: Don't aggressively discard the journal")
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent b1c71cb4
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -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)
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 &&
	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);
	bool ret = __should_discard_bucket(j, ja);
	spin_unlock(&j->lock);

	return ret;