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-09-18 06:30:54 -0800
commit543524b43060f98bc95ca08cb8ef11d91d22e46b (patch)
treece2d40d52c33aabed5679fb5f4cad5f2a4c1f7cc
parent2bdac58adbf9ae6c69d292f707b86bca51471afe (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 7b5c4949f1bf..b5246e0e2383 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 f3558e573c07..77a6f1bc5916 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1099,6 +1099,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;