bcache: allow quick writeback when backing idle
authorMichael Lyle <mlyle@lyle.org>
Mon, 8 Jan 2018 20:21:24 +0000 (12:21 -0800)
committerJens Axboe <axboe@kernel.dk>
Mon, 8 Jan 2018 20:29:00 +0000 (13:29 -0700)
If the control system would wait for at least half a second, and there's
been no reqs hitting the backing disk for awhile: use an alternate mode
where we have at most one contiguous set of writebacks in flight at a
time. (But don't otherwise delay).  If front-end IO appears, it will
still be quick, as it will only have to contend with one real operation
in flight.  But otherwise, we'll be sending data to the backing disk as
quickly as it can accept it (with one op at a time).

Signed-off-by: Michael Lyle <mlyle@lyle.org>
Reviewed-by: Tang Junhui <tang.junhui@zte.com.cn>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/md/bcache/bcache.h
drivers/md/bcache/request.c
drivers/md/bcache/writeback.c

index 3be0fcc19b1f81564e4d282723b6abd60e043307..5f7b0b2513ccb68c8bf588fa837b7530309c1d03 100644 (file)
@@ -320,6 +320,13 @@ struct cached_dev {
         */
        atomic_t                has_dirty;
 
+       /*
+        * Set to zero by things that touch the backing volume-- except
+        * writeback.  Incremented by writeback.  Used to determine when to
+        * accelerate idle writeback.
+        */
+       atomic_t                backing_idle;
+
        struct bch_ratelimit    writeback_rate;
        struct delayed_work     writeback_rate_update;
 
index 52b4ce24f9e295607a7da64637e2bef17855730f..ddd941056f3c2ab638c9591c52ef9e4aa276c32d 100644 (file)
@@ -996,6 +996,7 @@ static blk_qc_t cached_dev_make_request(struct request_queue *q,
        struct cached_dev *dc = container_of(d, struct cached_dev, disk);
        int rw = bio_data_dir(bio);
 
+       atomic_set(&dc->backing_idle, 0);
        generic_start_io_acct(q, rw, bio_sectors(bio), &d->disk->part0);
 
        bio_set_dev(bio, dc->bdev);
index 6e1d2fde43dfa2746a3300d717f38ca8fcc28e43..f82ffb2e9b9be3893068fb84980ac5f091e8dcbe 100644 (file)
@@ -356,6 +356,27 @@ static void read_dirty(struct cached_dev *dc)
 
                delay = writeback_delay(dc, size);
 
+               /* If the control system would wait for at least half a
+                * second, and there's been no reqs hitting the backing disk
+                * for awhile: use an alternate mode where we have at most
+                * one contiguous set of writebacks in flight at a time.  If
+                * someone wants to do IO it will be quick, as it will only
+                * have to contend with one operation in flight, and we'll
+                * be round-tripping data to the backing disk as quickly as
+                * it can accept it.
+                */
+               if (delay >= HZ / 2) {
+                       /* 3 means at least 1.5 seconds, up to 7.5 if we
+                        * have slowed way down.
+                        */
+                       if (atomic_inc_return(&dc->backing_idle) >= 3) {
+                               /* Wait for current I/Os to finish */
+                               closure_sync(&cl);
+                               /* And immediately launch a new set. */
+                               delay = 0;
+                       }
+               }
+
                while (!kthread_should_stop() && delay) {
                        schedule_timeout_interruptible(delay);
                        delay = writeback_delay(dc, 0);