| From 64c41825d56a1a0a7f7b468606a08bf6a86c21ba Mon Sep 17 00:00:00 2001 |
| From: Tang Junhui <tang.junhui@zte.com.cn> |
| Date: Tue, 9 Jan 2018 10:27:11 +0800 |
| Subject: [PATCH v5 07/10] bcache: fix inaccurate io state for detached bcache |
| devices |
| |
| When we run IO in a detached device, and run iostat to shows IO status, |
| normally it will show like bellow (Omitted some fields): |
| Device: ... avgrq-sz avgqu-sz await r_await w_await svctm %util |
| sdd ... 15.89 0.53 1.82 0.20 2.23 1.81 52.30 |
| bcache0 ... 15.89 115.42 0.00 0.00 0.00 2.40 69.60 |
| but after IO stopped, there are still very big avgqu-sz and %util |
| values as bellow: |
| Device: ... avgrq-sz avgqu-sz await r_await w_await svctm %util |
| bcache0 ... 0 5326.32 0.00 0.00 0.00 0.00 100.10 |
| |
| The reason for this issue is that, only generic_start_io_acct() called |
| and no generic_end_io_acct() called for detached device in |
| cached_dev_make_request(). See the code: |
| //start generic_start_io_acct() |
| generic_start_io_acct(q, rw, bio_sectors(bio), &d->disk->part0); |
| if (cached_dev_get(dc)) { |
| //will callback generic_end_io_acct() |
| } |
| else { |
| //will not call generic_end_io_acct() |
| } |
| |
| This patch calls generic_end_io_acct() in the end of IO for detached |
| devices, so we can show IO state correctly. |
| |
| (Modified to use GFP_NOIO in kzalloc() by Coly Li) |
| |
| Signed-off-by: Tang Junhui <tang.junhui@zte.com.cn> |
| Reviewed-by: Coly Li <colyli@suse.de> |
| Reviewed-by: Hannes Reinecke <hare@suse.com> |
| --- |
| drivers/md/bcache/request.c | 58 +++++++++++++++++++++++++++++++++++++++------ |
| 1 file changed, 51 insertions(+), 7 deletions(-) |
| |
| diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c |
| index 02296bda6384..e09c5ae745be 100644 |
| --- a/drivers/md/bcache/request.c |
| +++ b/drivers/md/bcache/request.c |
| @@ -986,6 +986,55 @@ static void cached_dev_nodata(struct closure *cl) |
| continue_at(cl, cached_dev_bio_complete, NULL); |
| } |
| |
| +struct detached_dev_io_private { |
| + struct bcache_device *d; |
| + unsigned long start_time; |
| + bio_end_io_t *bi_end_io; |
| + void *bi_private; |
| +}; |
| + |
| +static void detatched_dev_end_io(struct bio *bio) |
| +{ |
| + struct detached_dev_io_private *ddip; |
| + |
| + ddip = bio->bi_private; |
| + bio->bi_end_io = ddip->bi_end_io; |
| + bio->bi_private = ddip->bi_private; |
| + |
| + generic_end_io_acct(ddip->d->disk->queue, |
| + bio_data_dir(bio), |
| + &ddip->d->disk->part0, ddip->start_time); |
| + |
| + kfree(ddip); |
| + |
| + bio->bi_end_io(bio); |
| +} |
| + |
| +static void detached_dev_do_request(struct bcache_device *d, struct bio *bio) |
| +{ |
| + struct detached_dev_io_private *ddip; |
| + struct cached_dev *dc = container_of(d, struct cached_dev, disk); |
| + |
| + /* |
| + * no need to call closure_get(&dc->disk.cl), |
| + * because upper layer had already opened bcache device, |
| + * which would call closure_get(&dc->disk.cl) |
| + */ |
| + ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO); |
| + ddip->d = d; |
| + ddip->start_time = jiffies; |
| + ddip->bi_end_io = bio->bi_end_io; |
| + ddip->bi_private = bio->bi_private; |
| + bio->bi_end_io = detatched_dev_end_io; |
| + bio->bi_private = ddip; |
| + |
| + if ((bio_op(bio) == REQ_OP_DISCARD) && |
| + !blk_queue_discard(bdev_get_queue(dc->bdev))) |
| + bio->bi_end_io(bio); |
| + else |
| + generic_make_request(bio); |
| +} |
| + |
| /* Cached devices - read & write stuff */ |
| |
| static blk_qc_t cached_dev_make_request(struct request_queue *q, |
| @@ -1028,13 +1077,8 @@ static blk_qc_t cached_dev_make_request(struct request_queue *q, |
| else |
| cached_dev_read(dc, s); |
| } |
| - } else { |
| - if ((bio_op(bio) == REQ_OP_DISCARD) && |
| - !blk_queue_discard(bdev_get_queue(dc->bdev))) |
| - bio_endio(bio); |
| - else |
| - generic_make_request(bio); |
| - } |
| + } else |
| + detached_dev_do_request(d, bio); |
| |
| return BLK_QC_T_NONE; |
| } |
| -- |
| 2.16.1 |
| |