aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/bcache/request.c
diff options
context:
space:
mode:
authorTang Junhui <tang.junhui@zte.com.cn>2018-03-18 20:36:19 -0400
committerJens Axboe <axboe@kernel.dk>2018-03-18 22:15:20 -0400
commitbc082a55d25c837341709accaf11311c3a9af727 (patch)
tree4a3bf3286ad08651cda3698ceff5799d4b7d9b87 /drivers/md/bcache/request.c
parent7e027ca4b534b6b99a7c0471e13ba075ffa3f482 (diff)
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) Changelog: v2: fix typo. v1: the initial version. Signed-off-by: Tang Junhui <tang.junhui@zte.com.cn> Reviewed-by: Coly Li <colyli@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.com> Reviewed-by: Michael Lyle <mlyle@lyle.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/md/bcache/request.c')
-rw-r--r--drivers/md/bcache/request.c58
1 files changed, 51 insertions, 7 deletions
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 7aca308bee5b..5c8ae69c8502 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)
986 continue_at(cl, cached_dev_bio_complete, NULL); 986 continue_at(cl, cached_dev_bio_complete, NULL);
987} 987}
988 988
989struct detached_dev_io_private {
990 struct bcache_device *d;
991 unsigned long start_time;
992 bio_end_io_t *bi_end_io;
993 void *bi_private;
994};
995
996static void detached_dev_end_io(struct bio *bio)
997{
998 struct detached_dev_io_private *ddip;
999
1000 ddip = bio->bi_private;
1001 bio->bi_end_io = ddip->bi_end_io;
1002 bio->bi_private = ddip->bi_private;
1003
1004 generic_end_io_acct(ddip->d->disk->queue,
1005 bio_data_dir(bio),
1006 &ddip->d->disk->part0, ddip->start_time);
1007
1008 kfree(ddip);
1009
1010 bio->bi_end_io(bio);
1011}
1012
1013static void detached_dev_do_request(struct bcache_device *d, struct bio *bio)
1014{
1015 struct detached_dev_io_private *ddip;
1016 struct cached_dev *dc = container_of(d, struct cached_dev, disk);
1017
1018 /*
1019 * no need to call closure_get(&dc->disk.cl),
1020 * because upper layer had already opened bcache device,
1021 * which would call closure_get(&dc->disk.cl)
1022 */
1023 ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO);
1024 ddip->d = d;
1025 ddip->start_time = jiffies;
1026 ddip->bi_end_io = bio->bi_end_io;
1027 ddip->bi_private = bio->bi_private;
1028 bio->bi_end_io = detached_dev_end_io;
1029 bio->bi_private = ddip;
1030
1031 if ((bio_op(bio) == REQ_OP_DISCARD) &&
1032 !blk_queue_discard(bdev_get_queue(dc->bdev)))
1033 bio->bi_end_io(bio);
1034 else
1035 generic_make_request(bio);
1036}
1037
989/* Cached devices - read & write stuff */ 1038/* Cached devices - read & write stuff */
990 1039
991static blk_qc_t cached_dev_make_request(struct request_queue *q, 1040static 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,
1028 else 1077 else
1029 cached_dev_read(dc, s); 1078 cached_dev_read(dc, s);
1030 } 1079 }
1031 } else { 1080 } else
1032 if ((bio_op(bio) == REQ_OP_DISCARD) && 1081 detached_dev_do_request(d, bio);
1033 !blk_queue_discard(bdev_get_queue(dc->bdev)))
1034 bio_endio(bio);
1035 else
1036 generic_make_request(bio);
1037 }
1038 1082
1039 return BLK_QC_T_NONE; 1083 return BLK_QC_T_NONE;
1040} 1084}