@@ -32,6 +32,15 @@ Description:
the statistics of I/O latency for each type (read, write,
discard and flush)which have happened to the disk.
+What: /sys/block/<disk>/io_size
+Date: August 2020
+Contact: Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
+Description:
+ The /sys/block/<disk>/io_size files displays the I/O
+ size of disk <disk>. With it, it is convenient to know
+ the statistics of I/O size for each type (read, write,
+ discard and flush) which have happened to the disk.
+
What: /sys/block/<disk>/<part>/stat
Date: February 2008
Contact: Jerome Marchand <jmarchan@redhat.com>
@@ -180,7 +180,8 @@ config BLK_ADDITIONAL_DISKSTAT
bool "Block layer additional diskstat"
default n
help
- Enabling this option adds io latency statistics for each block device.
+ Enabling this option adds io latency and io size statistics for each
+ block device.
If unsure, say N.
@@ -1438,6 +1438,22 @@ static void blk_additional_latency(struct hd_struct *part, const int sgrp,
#endif
}
+static void blk_additional_sector(struct hd_struct *part, const int sgrp,
+ unsigned int sectors)
+{
+#ifdef CONFIG_BLK_ADDITIONAL_DISKSTAT
+ unsigned int idx;
+
+ if (sectors == 1)
+ idx = 0;
+ else
+ idx = ilog2(sectors);
+
+ idx = (idx > (ADD_STAT_NUM - 1)) ? (ADD_STAT_NUM - 1) : idx;
+ part_stat_inc(part, size_table[idx][sgrp]);
+#endif
+}
+
static void blk_account_io_completion(struct request *req, unsigned int bytes)
{
if (req->part && blk_do_io_stat(req)) {
@@ -1446,6 +1462,7 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes)
part_stat_lock();
part = req->part;
+ blk_additional_sector(part, sgrp, bytes >> SECTOR_SHIFT);
part_stat_add(part, sectors[sgrp], bytes >> 9);
part_stat_unlock();
}
@@ -1499,6 +1516,7 @@ unsigned long disk_start_io_acct(struct gendisk *disk, unsigned int sectors,
update_io_ticks(part, now, false);
part_stat_inc(part, ios[sgrp]);
part_stat_add(part, sectors[sgrp], sectors);
+ blk_additional_sector(part, sgrp, sectors);
part_stat_local_inc(part, in_flight[op_is_write(op)]);
part_stat_unlock();
@@ -1454,6 +1454,42 @@ static ssize_t io_latency_show(struct device *dev, struct device_attribute *attr
static struct device_attribute dev_attr_io_latency =
__ATTR(io_latency, 0444, io_latency_show, NULL);
+
+static ssize_t io_size_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct hd_struct *p = dev_to_part(dev);
+ size_t count = 0;
+ int i, sgrp;
+
+ for (i = 0; i < ADD_STAT_NUM; i++) {
+ unsigned int from, to;
+
+ if (i == ADD_STAT_NUM - 1) {
+ from = 2 << (i - 2);
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ " >=%5d KB: ", from);
+ } else {
+ if (i < 2) {
+ from = i;
+ to = i + 1;
+ } else {
+ from = 2 << (i - 2);
+ to = 2 << (i - 1);
+ }
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ "[%5d - %-5d) KB: ", from, to);
+ }
+ for (sgrp = 0; sgrp < NR_STAT_GROUPS; sgrp++)
+ count += scnprintf(buf + count, PAGE_SIZE - count, "%lu ",
+ part_stat_read(p, size_table[i][sgrp]));
+ count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
+ }
+
+ return count;
+}
+
+static struct device_attribute dev_attr_io_size =
+ __ATTR(io_size, 0444, io_size_show, NULL);
#endif
static struct attribute *disk_attrs[] = {
@@ -1477,6 +1513,7 @@ static struct attribute *disk_attrs[] = {
#endif
#ifdef CONFIG_BLK_ADDITIONAL_DISKSTAT
&dev_attr_io_latency.attr,
+ &dev_attr_io_size.attr,
#endif
NULL
};
@@ -11,10 +11,11 @@ struct disk_stats {
unsigned long merges[NR_STAT_GROUPS];
#ifdef CONFIG_BLK_ADDITIONAL_DISKSTAT
/*
- * We measure latency (ms) for 1, 2, ..., 1024 and >=1024.
+ * We measure latency (ms) and size (KB) for 1, 2, ..., 1024 and >=1024.
*/
#define ADD_STAT_NUM 12
unsigned long latency_table[ADD_STAT_NUM][NR_STAT_GROUPS];
+ unsigned long size_table[ADD_STAT_NUM][NR_STAT_GROUPS];
#endif
unsigned long io_ticks;
local_t in_flight[2];