mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 23:39:18 +00:00
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: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
dc7a15fb90
commit
1f7056b735
@ -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);
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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)
|
|||||||
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);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user