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

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
...@@ -2085,6 +2085,17 @@ void bch2_recalc_capacity(struct bch_fs *c) ...@@ -2085,6 +2085,17 @@ void bch2_recalc_capacity(struct bch_fs *c)
closure_wake_up(&c->freelist_wait); 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) static bool bch2_dev_has_open_write_point(struct bch_fs *c, struct bch_dev *ca)
{ {
struct open_bucket *ob; struct open_bucket *ob;
......
...@@ -249,6 +249,7 @@ int bch2_dev_freespace_init(struct bch_fs *, struct bch_dev *, u64, u64); ...@@ -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 *); int bch2_fs_freespace_init(struct bch_fs *);
void bch2_recalc_capacity(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_remove(struct bch_fs *, struct bch_dev *);
void bch2_dev_allocator_add(struct bch_fs *, struct bch_dev *); void bch2_dev_allocator_add(struct bch_fs *, struct bch_dev *);
......
...@@ -188,7 +188,8 @@ static int bch2_copygc_get_buckets(struct moving_context *ctxt, ...@@ -188,7 +188,8 @@ static int bch2_copygc_get_buckets(struct moving_context *ctxt,
noinline noinline
static int bch2_copygc(struct moving_context *ctxt, 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 btree_trans *trans = ctxt->trans;
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
...@@ -224,6 +225,8 @@ static int bch2_copygc(struct moving_context *ctxt, ...@@ -224,6 +225,8 @@ static int bch2_copygc(struct moving_context *ctxt,
f->bucket.k.gen, data_opts); f->bucket.k.gen, data_opts);
if (ret) if (ret)
goto err; goto err;
*did_work = true;
} }
err: err:
darray_exit(&buckets); darray_exit(&buckets);
...@@ -322,6 +325,8 @@ static int bch2_copygc_thread(void *arg) ...@@ -322,6 +325,8 @@ static int bch2_copygc_thread(void *arg)
false); false);
while (!ret && !kthread_should_stop()) { while (!ret && !kthread_should_stop()) {
bool did_work = false;
bch2_trans_unlock(ctxt.trans); bch2_trans_unlock(ctxt.trans);
cond_resched(); cond_resched();
...@@ -352,10 +357,21 @@ static int bch2_copygc_thread(void *arg) ...@@ -352,10 +357,21 @@ static int bch2_copygc_thread(void *arg)
c->copygc_wait = 0; c->copygc_wait = 0;
c->copygc_running = true; c->copygc_running = true;
ret = bch2_copygc(&ctxt, &buckets); ret = bch2_copygc(&ctxt, &buckets, &did_work);
c->copygc_running = false; c->copygc_running = false;
wake_up(&c->copygc_running_wq); 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); move_buckets_wait(&ctxt, &buckets, true);
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include "bcachefs.h" #include "bcachefs.h"
#include "alloc_background.h"
#include "alloc_foreground.h" #include "alloc_foreground.h"
#include "btree_iter.h" #include "btree_iter.h"
#include "btree_update.h" #include "btree_update.h"
...@@ -282,15 +283,12 @@ static int do_rebalance_scan(struct moving_context *ctxt, u64 inum, u64 cookie) ...@@ -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) static void rebalance_wait(struct bch_fs *c)
{ {
struct bch_fs_rebalance *r = &c->rebalance; struct bch_fs_rebalance *r = &c->rebalance;
struct bch_dev *ca;
struct io_clock *clock = &c->io_clock[WRITE]; struct io_clock *clock = &c->io_clock[WRITE];
u64 now = atomic64_read(&clock->now); u64 now = atomic64_read(&clock->now);
u64 min_member_capacity = 128 * 2048; u64 min_member_capacity = bch2_min_rw_member_capacity(c);
unsigned i;
for_each_rw_member(ca, c, i) if (min_member_capacity == U64_MAX)
min_member_capacity = min(min_member_capacity, min_member_capacity = 128 * 2048;
ca->mi.nbuckets * ca->mi.bucket_size);
r->wait_iotime_end = now + (min_member_capacity >> 6); r->wait_iotime_end = now + (min_member_capacity >> 6);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment