diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2016-09-18 06:19:23 -0800 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2016-10-07 12:37:08 -0800 |
commit | 1b66a322e59080363f758b3f45e3ecc0412f0e32 (patch) | |
tree | 7602c01e17743a0ed707cdeb4fe530a0a9153181 | |
parent | 10963e1bae5f9dab7f32104d9afe7b22b24306b5 (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.h | 3 | ||||
-rw-r--r-- | drivers/md/bcache/fs-io.c | 25 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 3 |
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; |