Commit 1f7056b7 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: Ensure copygc does not spin



If copygc does no work - finds no fragmented buckets - wait for a bit of
IO to happen.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent dc7a15fb
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -2085,6 +2085,17 @@ void bch2_recalc_capacity(struct bch_fs *c)
	closure_wake_up(&c->freelist_wait);
}

u64 bch2_min_rw_member_capacity(struct bch_fs *c)
{
	struct bch_dev *ca;
	unsigned i;
	u64 ret = U64_MAX;

	for_each_rw_member(ca, c, i)
		ret = min(ret, ca->mi.nbuckets * ca->mi.bucket_size);
	return ret;
}

static bool bch2_dev_has_open_write_point(struct bch_fs *c, struct bch_dev *ca)
{
	struct open_bucket *ob;
+1 −0
Original line number Diff line number Diff line
@@ -249,6 +249,7 @@ int bch2_dev_freespace_init(struct bch_fs *, struct bch_dev *, u64, u64);
int bch2_fs_freespace_init(struct bch_fs *);

void bch2_recalc_capacity(struct bch_fs *);
u64 bch2_min_rw_member_capacity(struct bch_fs *);

void bch2_dev_allocator_remove(struct bch_fs *, struct bch_dev *);
void bch2_dev_allocator_add(struct bch_fs *, struct bch_dev *);
+18 −2
Original line number Diff line number Diff line
@@ -188,7 +188,8 @@ static int bch2_copygc_get_buckets(struct moving_context *ctxt,

noinline
static int bch2_copygc(struct moving_context *ctxt,
		       struct buckets_in_flight *buckets_in_flight)
		       struct buckets_in_flight *buckets_in_flight,
		       bool *did_work)
{
	struct btree_trans *trans = ctxt->trans;
	struct bch_fs *c = trans->c;
@@ -224,6 +225,8 @@ static int bch2_copygc(struct moving_context *ctxt,
					     f->bucket.k.gen, data_opts);
		if (ret)
			goto err;

		*did_work = true;
	}
err:
	darray_exit(&buckets);
@@ -322,6 +325,8 @@ static int bch2_copygc_thread(void *arg)
			      false);

	while (!ret && !kthread_should_stop()) {
		bool did_work = false;

		bch2_trans_unlock(ctxt.trans);
		cond_resched();

@@ -352,10 +357,21 @@ static int bch2_copygc_thread(void *arg)
		c->copygc_wait = 0;

		c->copygc_running = true;
		ret = bch2_copygc(&ctxt, &buckets);
		ret = bch2_copygc(&ctxt, &buckets, &did_work);
		c->copygc_running = false;

		wake_up(&c->copygc_running_wq);

		if (!wait && !did_work) {
			u64 min_member_capacity = bch2_min_rw_member_capacity(c);

			if (min_member_capacity == U64_MAX)
				min_member_capacity = 128 * 2048;

			bch2_trans_unlock_long(ctxt.trans);
			bch2_kthread_io_clock_wait(clock, last + (min_member_capacity >> 6),
					MAX_SCHEDULE_TIMEOUT);
		}
	}

	move_buckets_wait(&ctxt, &buckets, true);
+4 −6
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0

#include "bcachefs.h"
#include "alloc_background.h"
#include "alloc_foreground.h"
#include "btree_iter.h"
#include "btree_update.h"
@@ -282,15 +283,12 @@ static int do_rebalance_scan(struct moving_context *ctxt, u64 inum, u64 cookie)
static void rebalance_wait(struct bch_fs *c)
{
	struct bch_fs_rebalance *r = &c->rebalance;
	struct bch_dev *ca;
	struct io_clock *clock = &c->io_clock[WRITE];
	u64 now = atomic64_read(&clock->now);
	u64 min_member_capacity = 128 * 2048;
	unsigned i;
	u64 min_member_capacity = bch2_min_rw_member_capacity(c);

	for_each_rw_member(ca, c, i)
		min_member_capacity = min(min_member_capacity,
					  ca->mi.nbuckets * ca->mi.bucket_size);
	if (min_member_capacity == U64_MAX)
		min_member_capacity = 128 * 2048;

	r->wait_iotime_end		= now + (min_member_capacity >> 6);