[PATCH] block: enable passthrough command statistics

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Keith Busch <kbusch@xxxxxxxxxx>

Applications using the passthrough interfaces for advance protocol IO
want to continue seeing the disk stats. These requests had been fenced
off from this block layer feature. While the block layer doesn't
necessarily know what a passthrough command does, we do know the data
size and direction, which is enough to account for the command's stats.

Since tracking these has the potential to produce unexpected results,
the passthrough stats are locked behind a new queue feature flag that
needs to be enabled using the /sys/block/<dev>/queue/iostats attribute.

Signed-off-by: Keith Busch <kbusch@xxxxxxxxxx>
---
This is based off the recently created for-6.13/block tree here:

  https://git.kernel.dk/cgit/linux-block/log/?h=for-6.13/block

 Documentation/ABI/stable/sysfs-block |  4 +++-
 block/blk-mq.c                       | 17 +++++++++++++-
 block/blk-sysfs.c                    | 35 +++++++++++++++++++++++++++-
 include/linux/blkdev.h               |  4 ++++
 4 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/stable/sysfs-block b/Documentation/ABI/stable/sysfs-block
index cea8856f798dd..bcf6ebedc9199 100644
--- a/Documentation/ABI/stable/sysfs-block
+++ b/Documentation/ABI/stable/sysfs-block
@@ -422,7 +422,9 @@ Date:		January 2009
 Contact:	linux-block@xxxxxxxxxxxxxxx
 Description:
 		[RW] This file is used to control (on/off) the iostats
-		accounting of the disk.
+		accounting of the disk. Set to 0 to disable all stats. Set to 1
+		to enable block IO stats. Set to 2 to enable passthrough stats
+		in addition to block IO.
 
 
 What:		/sys/block/<disk>/queue/logical_block_size
diff --git a/block/blk-mq.c b/block/blk-mq.c
index ee6cde39e52b7..55809f4bd09e3 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -994,13 +994,28 @@ static inline void blk_account_io_done(struct request *req, u64 now)
 	}
 }
 
+static inline bool blk_rq_passthrough_stats(struct request *req)
+{
+	struct bio *bio = req->bio;
+
+	if (!blk_queue_passthrough_stat(req->q))
+		return false;
+	if (!bio)
+		return false;
+	if (!bio->bi_bdev)
+		return false;
+	if (blk_rq_bytes(req) & (bdev_logical_block_size(bio->bi_bdev) - 1))
+		return false;
+	return true;
+}
+
 static inline void blk_account_io_start(struct request *req)
 {
 	trace_block_io_start(req);
 
 	if (!blk_queue_io_stat(req->q))
 		return;
-	if (blk_rq_is_passthrough(req))
+	if (blk_rq_is_passthrough(req) && !blk_rq_passthrough_stats(req))
 		return;
 
 	req->rq_flags |= RQF_IO_STAT;
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index e85941bec857b..99f438beb6c67 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -246,7 +246,6 @@ static ssize_t queue_##_name##_store(struct gendisk *disk,		\
 
 QUEUE_SYSFS_FEATURE(rotational, BLK_FEAT_ROTATIONAL)
 QUEUE_SYSFS_FEATURE(add_random, BLK_FEAT_ADD_RANDOM)
-QUEUE_SYSFS_FEATURE(iostats, BLK_FEAT_IO_STAT)
 QUEUE_SYSFS_FEATURE(stable_writes, BLK_FEAT_STABLE_WRITES);
 
 #define QUEUE_SYSFS_FEATURE_SHOW(_name, _feature)			\
@@ -272,6 +271,40 @@ static ssize_t queue_nr_zones_show(struct gendisk *disk, char *page)
 	return queue_var_show(disk_nr_zones(disk), page);
 }
 
+static ssize_t queue_iostats_show(struct gendisk *disk, char *page)
+{
+	return queue_var_show((bool)blk_queue_passthrough_stat(disk->queue) +
+			      (bool)blk_queue_io_stat(disk->queue), page);
+}
+
+static ssize_t queue_iostats_store(struct gendisk *disk, const char *page,
+				   size_t count)
+{
+	struct queue_limits lim;
+	unsigned long ios;
+	ssize_t ret;
+
+	ret = queue_var_store(&ios, page, count);
+	if (ret < 0)
+		return ret;
+
+	lim = queue_limits_start_update(disk->queue);
+	if (!ios)
+		lim.features &= ~(BLK_FEAT_IO_STAT | BLK_FEAT_PASSTHROUGH_STAT);
+	else if (ios == 2)
+		lim.features |= BLK_FEAT_IO_STAT | BLK_FEAT_PASSTHROUGH_STAT;
+	else if (ios == 1) {
+		lim.features |= BLK_FEAT_IO_STAT;
+		lim.features &= ~BLK_FEAT_PASSTHROUGH_STAT;
+	}
+
+	ret = queue_limits_commit_update(disk->queue, &lim);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
 static ssize_t queue_nomerges_show(struct gendisk *disk, char *page)
 {
 	return queue_var_show((blk_queue_nomerges(disk->queue) << 1) |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 50c3b959da281..9a66334a6e356 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -332,6 +332,8 @@ typedef unsigned int __bitwise blk_features_t;
 #define BLK_FEAT_RAID_PARTIAL_STRIPES_EXPENSIVE \
 	((__force blk_features_t)(1u << 15))
 
+#define BLK_FEAT_PASSTHROUGH_STAT	((__force blk_features_t)(1u << 16))
+
 /*
  * Flags automatically inherited when stacking limits.
  */
@@ -617,6 +619,8 @@ void blk_queue_flag_clear(unsigned int flag, struct request_queue *q);
 	test_bit(QUEUE_FLAG_NOXMERGES, &(q)->queue_flags)
 #define blk_queue_nonrot(q)	(!((q)->limits.features & BLK_FEAT_ROTATIONAL))
 #define blk_queue_io_stat(q)	((q)->limits.features & BLK_FEAT_IO_STAT)
+#define blk_queue_passthrough_stat(q)	\
+	((q)->limits.features & BLK_FEAT_PASSTHROUGH_STAT)
 #define blk_queue_dax(q)	((q)->limits.features & BLK_FEAT_DAX)
 #define blk_queue_pci_p2pdma(q)	((q)->limits.features & BLK_FEAT_PCI_P2PDMA)
 #ifdef CONFIG_BLK_RQ_ALLOC_TIME
-- 
2.43.5






[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux