Commit 241e2636 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet
Browse files

bcachefs: Don't flush btree writes more aggressively because of btree key cache



We need to flush the btree key cache when it's too dirty, because
otherwise the shrinker won't be able to reclaim memory - this is done by
journal reclaim. But journal reclaim also kicks btree node writes: this
meant that btree node writes were getting kicked much too often just
because we needed to flush btree key cache keys.

This patch splits journal pins into two different lists, and teaches
journal reclaim to not flush btree node writes when it only needs to
flush key cache keys.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 9d8022db
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -473,8 +473,10 @@ bool bch2_trans_relock(struct btree_trans *trans)

	trans_for_each_iter(trans, iter)
		if (btree_iter_keep(trans, iter) &&
		    !bch2_btree_iter_relock(iter, true))
		    !bch2_btree_iter_relock(iter, true)) {
			trace_trans_restart_relock(trans->ip);
			return false;
		}
	return true;
}

+3 −4
Original line number Diff line number Diff line
@@ -445,9 +445,8 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans,
	return ret;
}

static int btree_key_cache_journal_flush(struct journal *j,
					 struct journal_entry_pin *pin,
					 u64 seq)
int bch2_btree_key_cache_journal_flush(struct journal *j,
				struct journal_entry_pin *pin, u64 seq)
{
	struct bch_fs *c = container_of(j, struct bch_fs, journal);
	struct bkey_cached *ck =
@@ -528,7 +527,7 @@ bool bch2_btree_insert_key_cached(struct btree_trans *trans,
	}

	bch2_journal_pin_update(&c->journal, trans->journal_res.seq,
				&ck->journal, btree_key_cache_journal_flush);
				&ck->journal, bch2_btree_key_cache_journal_flush);

	if (kick_reclaim)
		journal_reclaim_kick(&c->journal);
+3 −9
Original line number Diff line number Diff line
#ifndef _BCACHEFS_BTREE_KEY_CACHE_H
#define _BCACHEFS_BTREE_KEY_CACHE_H

static inline size_t bch2_nr_btree_keys_want_flush(struct bch_fs *c)
{
	size_t nr_dirty = atomic_long_read(&c->btree_key_cache.nr_dirty);
	size_t nr_keys = atomic_long_read(&c->btree_key_cache.nr_keys);
	size_t max_dirty = nr_keys / 4;

	return max_t(ssize_t, 0, nr_dirty - max_dirty);
}

static inline size_t bch2_nr_btree_keys_need_flush(struct bch_fs *c)
{
	size_t nr_dirty = atomic_long_read(&c->btree_key_cache.nr_dirty);
@@ -29,6 +20,9 @@ static inline bool bch2_btree_key_cache_must_wait(struct bch_fs *c)
		test_bit(JOURNAL_RECLAIM_STARTED, &c->journal.flags);
}

int bch2_btree_key_cache_journal_flush(struct journal *,
				struct journal_entry_pin *, u64);

struct bkey_cached *
bch2_btree_key_cache_find(struct bch_fs *, enum btree_id, struct bpos);

+8 −3
Original line number Diff line number Diff line
@@ -974,20 +974,25 @@ bch2_btree_update_start(struct btree_iter *iter, unsigned level,
		 * closure argument
		 */
		if (flags & BTREE_INSERT_NOUNLOCK) {
			trace_trans_restart_journal_preres_get(trans->ip);
			ret = -EINTR;
			goto err;
		}

		bch2_trans_unlock(trans);

		if (flags & BTREE_INSERT_JOURNAL_RECLAIM)
			goto err;
		if (flags & BTREE_INSERT_JOURNAL_RECLAIM) {
			bch2_btree_update_free(as);
			return ERR_PTR(ret);
		}

		ret = bch2_journal_preres_get(&c->journal, &as->journal_preres,
				BTREE_UPDATE_JOURNAL_RES,
				journal_flags);
		if (ret)
		if (ret) {
			trace_trans_restart_journal_preres_get(trans->ip);
			goto err;
		}

		if (!bch2_trans_relock(trans)) {
			ret = -EINTR;
+14 −16
Original line number Diff line number Diff line
@@ -59,21 +59,23 @@ journal_seq_to_buf(struct journal *j, u64 seq)
	return buf;
}

static void journal_pin_new_entry(struct journal *j, int count)
static void journal_pin_list_init(struct journal_entry_pin_list *p, int count)
{
	struct journal_entry_pin_list *p;
	INIT_LIST_HEAD(&p->list);
	INIT_LIST_HEAD(&p->key_cache_list);
	INIT_LIST_HEAD(&p->flushed);
	atomic_set(&p->count, count);
	p->devs.nr = 0;
}

static void journal_pin_new_entry(struct journal *j)
{
	/*
	 * The fifo_push() needs to happen at the same time as j->seq is
	 * incremented for journal_last_seq() to be calculated correctly
	 */
	atomic64_inc(&j->seq);
	p = fifo_push_ref(&j->pin);

	INIT_LIST_HEAD(&p->list);
	INIT_LIST_HEAD(&p->flushed);
	atomic_set(&p->count, count);
	p->devs.nr = 0;
	journal_pin_list_init(fifo_push_ref(&j->pin), 1);
}

static void bch2_journal_buf_init(struct journal *j)
@@ -192,7 +194,7 @@ static bool __journal_entry_close(struct journal *j)
	__bch2_journal_pin_put(j, le64_to_cpu(buf->data->seq));

	/* Initialize new buffer: */
	journal_pin_new_entry(j, 1);
	journal_pin_new_entry(j);

	bch2_journal_buf_init(j);

@@ -1030,12 +1032,8 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq,
	j->pin.back		= cur_seq;
	atomic64_set(&j->seq, cur_seq - 1);

	fifo_for_each_entry_ptr(p, &j->pin, seq) {
		INIT_LIST_HEAD(&p->list);
		INIT_LIST_HEAD(&p->flushed);
		atomic_set(&p->count, 1);
		p->devs.nr = 0;
	}
	fifo_for_each_entry_ptr(p, &j->pin, seq)
		journal_pin_list_init(p, 1);

	list_for_each_entry(i, journal_entries, list) {
		unsigned ptr;
@@ -1058,7 +1056,7 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq,
	set_bit(JOURNAL_STARTED, &j->flags);
	j->last_flush_write = jiffies;

	journal_pin_new_entry(j, 1);
	journal_pin_new_entry(j);

	j->reservations.idx = j->reservations.unwritten_idx = journal_cur_seq(j);

Loading