@@ -36,6 +36,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: March 2021
+Contact: Guoqing Jiang <guoqing.jiang@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>
@@ -1283,12 +1283,31 @@ static void blk_additional_latency(struct block_device *part, const int sgrp,
part_stat_inc(part, latency_table[idx][sgrp]);
}
+static void blk_additional_sector(struct block_device *part, const int sgrp,
+ struct request_queue *q, unsigned int sectors)
+{
+ unsigned int idx;
+
+ if (!blk_queue_io_extra_stat(q))
+ return;
+
+ 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]);
+}
+
static void blk_account_io_completion(struct request *req, unsigned int bytes)
{
if (req->part && blk_do_io_stat(req)) {
const int sgrp = op_stat_group(req_op(req));
part_stat_lock();
+ blk_additional_sector(req->part, sgrp, req->q,
+ bytes >> SECTOR_SHIFT);
part_stat_add(req->part, sectors[sgrp], bytes >> 9);
part_stat_unlock();
}
@@ -1341,6 +1360,7 @@ static unsigned long __part_start_io_acct(struct block_device *part,
update_io_ticks(part, now, false);
part_stat_inc(part, ios[sgrp]);
part_stat_add(part, sectors[sgrp], sectors);
+ blk_additional_sector(part, sgrp, part->bd_disk->queue, sectors);
part_stat_local_inc(part, in_flight[op_is_write(op)]);
part_stat_unlock();
@@ -1108,6 +1108,44 @@ static ssize_t io_latency_show(struct device *dev,
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 block_device *bdev = dev_to_bdev(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(bdev,
+ 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);
+
static struct attribute *disk_attrs[] = {
&dev_attr_range.attr,
&dev_attr_ext_range.attr,
@@ -1128,6 +1166,7 @@ static struct attribute *disk_attrs[] = {
&dev_attr_fail_timeout.attr,
#endif
&dev_attr_io_latency.attr,
+ &dev_attr_io_size.attr,
NULL
};
@@ -10,10 +10,11 @@ struct disk_stats {
unsigned long ios[NR_STAT_GROUPS];
unsigned long merges[NR_STAT_GROUPS];
/*
- * 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];
unsigned long io_ticks;
local_t in_flight[2];
};