[PATCH RFC] nvme-multipath: fix diskstats for partitions

John Garry <[email protected]>
Newsgroups org.infradead.lists.linux-nvme
Message-ID <[email protected]>
From: John Garry <[email protected]>

Currently diskstats for partitions are never updated:
$ ./fio_read nvme1n1p1 # run traffic on /dev/nvme1n1p1
...
$ more /proc/diskstats | grep nvme1
 259       2 nvme1c1n1 49857 0 400344 768565 0 0 0 0 0 2334 768565 0 0 0 0 0 0
 259       3 nvme1n1 99710 0 800680 1599285 0 0 0 0 0 2346 1599285 0 0 0 0 0 0
 259       5 nvme1n1p1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 259       4 nvme1c2n1 49853 0 400336 831472 0 0 0 0 0 2315 831472 0 0 0 0 0 0

This is because we only ever update the diskstats for the multipath disk in
nvme_mpath_end_request(), and we never take into account that the original
bi_bdev may been a partition of this disk.

Functions bdev_start_io_acct() and bdev_start_io_acct() do handle
updating diskstats for a partition, in that they also update the whole
disk also (if a partition), so use the partition (if applicable) when
calling those functions.

Signed-off-by: John Garry <[email protected]>
---
Setting as an RFC as adding this extra bio field is not acceptable, but I
can't see how to lookup the original partition.

diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index c850a4bf73801..14d48cdc640c8 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -194,8 +194,12 @@ void nvme_mpath_start_request(struct request *rq)
 		return;
 
 	nvme_req(rq)->flags |= NVME_MPATH_IO_STATS;
-	nvme_req(rq)->start_time = bdev_start_io_acct(disk->part0, req_op(rq),
-						      jiffies);
+	if (bdev_is_partition(rq->bio->bi_orig))
+		nvme_req(rq)->start_time = bdev_start_io_acct(rq->bio->bi_orig, req_op(rq),
+							      jiffies);
+	else
+		nvme_req(rq)->start_time = bdev_start_io_acct(disk->part0, req_op(rq),
+							      jiffies);
 }
 EXPORT_SYMBOL_GPL(nvme_mpath_start_request);
 
@@ -208,7 +212,12 @@ void nvme_mpath_end_request(struct request *rq)
 
 	if (!(nvme_req(rq)->flags & NVME_MPATH_IO_STATS))
 		return;
-	bdev_end_io_acct(ns->head->disk->part0, req_op(rq),
+	if (bdev_is_partition(rq->bio->bi_orig))
+		bdev_end_io_acct(rq->bio->bi_orig, req_op(rq),
+				 blk_rq_bytes(rq) >> SECTOR_SHIFT,
+				 nvme_req(rq)->start_time);
+	else
+		bdev_end_io_acct(ns->head->disk->part0, req_op(rq),
 			 blk_rq_bytes(rq) >> SECTOR_SHIFT,
 			 nvme_req(rq)->start_time);
 }
@@ -543,6 +552,7 @@ static void nvme_ns_head_submit_bio(struct bio *bio)
 	srcu_idx = srcu_read_lock(&head->srcu);
 	ns = nvme_find_path(head);
 	if (likely(ns)) {
+		bio->bi_orig = bio->bi_bdev;
 		bio_set_dev(bio, ns->disk->part0);
 		/*
 		 * Use BIO_REMAPPED to skip bio_check_eod() when this bio
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 8808ee76e73c0..496005aff59b3 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -210,6 +210,7 @@ typedef unsigned int blk_qc_t;
 struct bio {
 	struct bio		*bi_next;	/* request queue link */
 	struct block_device	*bi_bdev;
+	struct block_device	*bi_orig;
 	blk_opf_t		bi_opf;		/* bottom bits REQ_OP, top bits
 						 * req_flags.
 						 */
-- 
2.43.7
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.