summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-09-18 06:19:23 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-07 12:37:08 -0800
commit1b66a322e59080363f758b3f45e3ecc0412f0e32 (patch)
tree7602c01e17743a0ed707cdeb4fe530a0a9153181
parent10963e1bae5f9dab7f32104d9afe7b22b24306b5 (diff)
bcachefs: hacky writeback ratelimiting
Prevent writeback from queueing up tons and tons of writes and pinning all available memory. Probably going to improve this later, would be better to avoid sleeping with pages locked and the amount to queue shouldn't be hardcoded, but this should be a significant improvement for now.
-rw-r--r--drivers/md/bcache/bcache.h3
-rw-r--r--drivers/md/bcache/fs-io.c25
-rw-r--r--drivers/md/bcache/super.c3
3 files changed, 24 insertions, 7 deletions
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index d1d37fa8aa9d..318616955570 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -748,6 +748,9 @@ struct cache_set {
spinlock_t read_retry_lock;
/* FILESYSTEM */
+ wait_queue_head_t writeback_wait;
+ atomic_t writeback_pages;
+ unsigned writeback_pages_max;
atomic_long_t nr_inodes;
/* TIERING */
diff --git a/drivers/md/bcache/fs-io.c b/drivers/md/bcache/fs-io.c
index 6509545ba3c4..f59575892244 100644
--- a/drivers/md/bcache/fs-io.c
+++ b/drivers/md/bcache/fs-io.c
@@ -774,10 +774,14 @@ static void bch_writepage_io_done(struct closure *cl)
{
struct bch_writepage_io *io = container_of(cl,
struct bch_writepage_io, cl);
+ struct cache_set *c = io->op.op.c;
struct bio *bio = &io->bio.bio.bio;
struct bio_vec *bvec;
unsigned i;
+ atomic_sub(bio->bi_vcnt, &c->writeback_pages);
+ wake_up(&c->writeback_wait);
+
bio_for_each_segment_all(bvec, bio, i) {
struct page *page = bvec->bv_page;
@@ -829,6 +833,8 @@ static void bch_writepage_io_done(struct closure *cl)
static void bch_writepage_do_io(struct bch_writepage_io *io)
{
+ atomic_add(io->bio.bio.bio.bi_vcnt, &io->op.op.c->writeback_pages);
+
io->op.op.pos.offset = io->bio.bio.bio.bi_iter.bi_sector;
closure_call(&io->op.op.cl, bch_write, NULL, &io->cl);
@@ -843,22 +849,27 @@ static void bch_writepage_io_alloc(struct bch_writepage *w,
struct bch_inode_info *ei,
struct page *page)
{
-alloc_io:
+ struct cache_set *c = w->c;
+
if (!w->io) {
- struct bio *bio = bio_alloc_bioset(GFP_NOFS, BIO_MAX_PAGES,
- bch_writepage_bioset);
+alloc_io:
+ wait_event(c->writeback_wait,
+ atomic_read(&c->writeback_pages) < c->writeback_pages_max);
- w->io = container_of(bio, struct bch_writepage_io, bio.bio.bio);
+ w->io = container_of(bio_alloc_bioset(GFP_NOFS,
+ BIO_MAX_PAGES,
+ bch_writepage_bioset),
+ struct bch_writepage_io, bio.bio.bio);
closure_init(&w->io->cl, NULL);
w->io->op.ei = ei;
w->io->op.sectors_added = 0;
w->io->op.is_dio = false;
- bch_write_op_init(&w->io->op.op, w->c, &w->io->bio,
+ bch_write_op_init(&w->io->op.op, c, &w->io->bio,
(struct disk_reservation) {
- .nr_replicas = w->c->opts.data_replicas,
+ .nr_replicas = c->opts.data_replicas,
},
- foreground_write_point(w->c, ei->vfs_inode.i_ino),
+ foreground_write_point(c, ei->vfs_inode.i_ino),
POS(w->inum, 0),
&ei->journal_seq, 0);
w->io->op.op.index_update_fn = bchfs_write_index_update;
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 28daba296527..f2bbbcfe3691 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1100,6 +1100,9 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb,
c->congested_read_threshold_us = 2000;
c->congested_write_threshold_us = 20000;
c->error_limit = 16 << IO_ERROR_SHIFT;
+ init_waitqueue_head(&c->writeback_wait);
+
+ c->writeback_pages_max = (256 << 10) / PAGE_SIZE;
c->btree_flush_delay = 30;