summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Callahan <michaelcallahan@fb.com>2018-07-18 07:47:40 -0400
committerJens Axboe <axboe@kernel.dk>2018-07-18 10:44:22 -0400
commitbdca3c87fb7ad1cc61d231d37eb0d8f90d001e0c (patch)
treea5890cef3e0fb586f2a2b2a366423e71af96d821
parentddcf35d397976421a4ec1d0d00fbcc027a8cb034 (diff)
block: Track DISCARD statistics and output them in stat and diskstat
Add tracking of REQ_OP_DISCARD ios to the partition statistics and append them to the various stat files in /sys as well as /proc/diskstats. These are tracked with the same four stats as reads and writes: Number of discard ios completed. Number of discard ios merged Number of discard sectors completed Milliseconds spent on discard requests This is done via adding a new STAT_DISCARD define to genhd.h and then using it to index that stat field for discard requests. tj: Refreshed on top of v4.17 and other previous updates. Signed-off-by: Michael Callahan <michaelcallahan@fb.com> Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Andy Newell <newella@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--Documentation/ABI/testing/procfs-diskstats10
-rw-r--r--Documentation/block/stat.txt28
-rw-r--r--Documentation/iostats.txt15
-rw-r--r--block/genhd.c13
-rw-r--r--block/partition-generic.c9
-rw-r--r--include/linux/blk_types.h8
-rw-r--r--include/linux/genhd.h3
7 files changed, 68 insertions, 18 deletions
diff --git a/Documentation/ABI/testing/procfs-diskstats b/Documentation/ABI/testing/procfs-diskstats
index f91a973a37fe..abac31d216de 100644
--- a/Documentation/ABI/testing/procfs-diskstats
+++ b/Documentation/ABI/testing/procfs-diskstats
@@ -5,6 +5,7 @@ Description:
5 The /proc/diskstats file displays the I/O statistics 5 The /proc/diskstats file displays the I/O statistics
6 of block devices. Each line contains the following 14 6 of block devices. Each line contains the following 14
7 fields: 7 fields:
8
8 1 - major number 9 1 - major number
9 2 - minor mumber 10 2 - minor mumber
10 3 - device name 11 3 - device name
@@ -19,4 +20,13 @@ Description:
19 12 - I/Os currently in progress 20 12 - I/Os currently in progress
20 13 - time spent doing I/Os (ms) 21 13 - time spent doing I/Os (ms)
21 14 - weighted time spent doing I/Os (ms) 22 14 - weighted time spent doing I/Os (ms)
23
24 Kernel 4.18+ appends four more fields for discard
25 tracking putting the total at 18:
26
27 15 - discards completed successfully
28 16 - discards merged
29 17 - sectors discarded
30 18 - time spent discarding
31
22 For more details refer to Documentation/iostats.txt 32 For more details refer to Documentation/iostats.txt
diff --git a/Documentation/block/stat.txt b/Documentation/block/stat.txt
index 0dbc946de2ea..0aace9cc536c 100644
--- a/Documentation/block/stat.txt
+++ b/Documentation/block/stat.txt
@@ -31,28 +31,32 @@ write ticks milliseconds total wait time for write requests
31in_flight requests number of I/Os currently in flight 31in_flight requests number of I/Os currently in flight
32io_ticks milliseconds total time this block device has been active 32io_ticks milliseconds total time this block device has been active
33time_in_queue milliseconds total wait time for all requests 33time_in_queue milliseconds total wait time for all requests
34discard I/Os requests number of discard I/Os processed
35discard merges requests number of discard I/Os merged with in-queue I/O
36discard sectors sectors number of sectors discarded
37discard ticks milliseconds total wait time for discard requests
34 38
35read I/Os, write I/Os 39read I/Os, write I/Os, discard I/0s
36===================== 40===================================
37 41
38These values increment when an I/O request completes. 42These values increment when an I/O request completes.
39 43
40read merges, write merges 44read merges, write merges, discard merges
41========================= 45=========================================
42 46
43These values increment when an I/O request is merged with an 47These values increment when an I/O request is merged with an
44already-queued I/O request. 48already-queued I/O request.
45 49
46read sectors, write sectors 50read sectors, write sectors, discard_sectors
47=========================== 51============================================
48 52
49These values count the number of sectors read from or written to this 53These values count the number of sectors read from, written to, or
50block device. The "sectors" in question are the standard UNIX 512-byte 54discarded from this block device. The "sectors" in question are the
51sectors, not any device- or filesystem-specific block size. The 55standard UNIX 512-byte sectors, not any device- or filesystem-specific
52counters are incremented when the I/O completes. 56block size. The counters are incremented when the I/O completes.
53 57
54read ticks, write ticks 58read ticks, write ticks, discard ticks
55======================= 59======================================
56 60
57These values count the number of milliseconds that I/O requests have 61These values count the number of milliseconds that I/O requests have
58waited on this block device. If there are multiple I/O requests waiting, 62waited on this block device. If there are multiple I/O requests waiting,
diff --git a/Documentation/iostats.txt b/Documentation/iostats.txt
index 04d394a2e06c..49df45f90e8a 100644
--- a/Documentation/iostats.txt
+++ b/Documentation/iostats.txt
@@ -31,6 +31,9 @@ Here are examples of these different formats::
31 3 0 hda 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160 31 3 0 hda 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160
32 3 1 hda1 35486 38030 38030 38030 32 3 1 hda1 35486 38030 38030 38030
33 33
34 4.18+ diskstats:
35 3 0 hda 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160 0 0 0 0
36
34On 2.4 you might execute ``grep 'hda ' /proc/partitions``. On 2.6+, you have 37On 2.4 you might execute ``grep 'hda ' /proc/partitions``. On 2.6+, you have
35a choice of ``cat /sys/block/hda/stat`` or ``grep 'hda ' /proc/diskstats``. 38a choice of ``cat /sys/block/hda/stat`` or ``grep 'hda ' /proc/diskstats``.
36 39
@@ -101,6 +104,18 @@ Field 11 -- weighted # of milliseconds spent doing I/Os
101 last update of this field. This can provide an easy measure of both 104 last update of this field. This can provide an easy measure of both
102 I/O completion time and the backlog that may be accumulating. 105 I/O completion time and the backlog that may be accumulating.
103 106
107Field 12 -- # of discards completed
108 This is the total number of discards completed successfully.
109
110Field 13 -- # of discards merged
111 See the description of field 2
112
113Field 14 -- # of sectors discarded
114 This is the total number of sectors discarded successfully.
115
116Field 15 -- # of milliseconds spent discarding
117 This is the total number of milliseconds spent by all discards (as
118 measured from __make_request() to end_that_request_last()).
104 119
105To avoid introducing performance bottlenecks, no locks are held while 120To avoid introducing performance bottlenecks, no locks are held while
106modifying these counters. This implies that minor inaccuracies may be 121modifying these counters. This implies that minor inaccuracies may be
diff --git a/block/genhd.c b/block/genhd.c
index 0711a800d0d4..8cc719a37b32 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1333,8 +1333,11 @@ static int diskstats_show(struct seq_file *seqf, void *v)
1333 part_round_stats(gp->queue, cpu, hd); 1333 part_round_stats(gp->queue, cpu, hd);
1334 part_stat_unlock(); 1334 part_stat_unlock();
1335 part_in_flight(gp->queue, hd, inflight); 1335 part_in_flight(gp->queue, hd, inflight);
1336 seq_printf(seqf, "%4d %7d %s %lu %lu %lu " 1336 seq_printf(seqf, "%4d %7d %s "
1337 "%u %lu %lu %lu %u %u %u %u\n", 1337 "%lu %lu %lu %u "
1338 "%lu %lu %lu %u "
1339 "%u %u %u "
1340 "%lu %lu %lu %u\n",
1338 MAJOR(part_devt(hd)), MINOR(part_devt(hd)), 1341 MAJOR(part_devt(hd)), MINOR(part_devt(hd)),
1339 disk_name(gp, hd->partno, buf), 1342 disk_name(gp, hd->partno, buf),
1340 part_stat_read(hd, ios[STAT_READ]), 1343 part_stat_read(hd, ios[STAT_READ]),
@@ -1347,7 +1350,11 @@ static int diskstats_show(struct seq_file *seqf, void *v)
1347 jiffies_to_msecs(part_stat_read(hd, ticks[STAT_WRITE])), 1350 jiffies_to_msecs(part_stat_read(hd, ticks[STAT_WRITE])),
1348 inflight[0], 1351 inflight[0],
1349 jiffies_to_msecs(part_stat_read(hd, io_ticks)), 1352 jiffies_to_msecs(part_stat_read(hd, io_ticks)),
1350 jiffies_to_msecs(part_stat_read(hd, time_in_queue)) 1353 jiffies_to_msecs(part_stat_read(hd, time_in_queue)),
1354 part_stat_read(hd, ios[STAT_DISCARD]),
1355 part_stat_read(hd, merges[STAT_DISCARD]),
1356 part_stat_read(hd, sectors[STAT_DISCARD]),
1357 jiffies_to_msecs(part_stat_read(hd, ticks[STAT_DISCARD]))
1351 ); 1358 );
1352 } 1359 }
1353 disk_part_iter_exit(&piter); 1360 disk_part_iter_exit(&piter);
diff --git a/block/partition-generic.c b/block/partition-generic.c
index 0ddb06722162..5a8975a1201c 100644
--- a/block/partition-generic.c
+++ b/block/partition-generic.c
@@ -130,7 +130,8 @@ ssize_t part_stat_show(struct device *dev,
130 return sprintf(buf, 130 return sprintf(buf,
131 "%8lu %8lu %8llu %8u " 131 "%8lu %8lu %8llu %8u "
132 "%8lu %8lu %8llu %8u " 132 "%8lu %8lu %8llu %8u "
133 "%8u %8u %8u" 133 "%8u %8u %8u "
134 "%8lu %8lu %8llu %8u"
134 "\n", 135 "\n",
135 part_stat_read(p, ios[STAT_READ]), 136 part_stat_read(p, ios[STAT_READ]),
136 part_stat_read(p, merges[STAT_READ]), 137 part_stat_read(p, merges[STAT_READ]),
@@ -142,7 +143,11 @@ ssize_t part_stat_show(struct device *dev,
142 jiffies_to_msecs(part_stat_read(p, ticks[STAT_WRITE])), 143 jiffies_to_msecs(part_stat_read(p, ticks[STAT_WRITE])),
143 inflight[0], 144 inflight[0],
144 jiffies_to_msecs(part_stat_read(p, io_ticks)), 145 jiffies_to_msecs(part_stat_read(p, io_ticks)),
145 jiffies_to_msecs(part_stat_read(p, time_in_queue))); 146 jiffies_to_msecs(part_stat_read(p, time_in_queue)),
147 part_stat_read(p, ios[STAT_DISCARD]),
148 part_stat_read(p, merges[STAT_DISCARD]),
149 (unsigned long long)part_stat_read(p, sectors[STAT_DISCARD]),
150 jiffies_to_msecs(part_stat_read(p, ticks[STAT_DISCARD])));
146} 151}
147 152
148ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr, 153ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr,
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 2960a96d833c..f6dfb30737d8 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -360,6 +360,7 @@ enum req_flag_bits {
360enum stat_group { 360enum stat_group {
361 STAT_READ, 361 STAT_READ,
362 STAT_WRITE, 362 STAT_WRITE,
363 STAT_DISCARD,
363 364
364 NR_STAT_GROUPS 365 NR_STAT_GROUPS
365}; 366};
@@ -401,8 +402,15 @@ static inline bool op_is_sync(unsigned int op)
401 (op & (REQ_SYNC | REQ_FUA | REQ_PREFLUSH)); 402 (op & (REQ_SYNC | REQ_FUA | REQ_PREFLUSH));
402} 403}
403 404
405static inline bool op_is_discard(unsigned int op)
406{
407 return (op & REQ_OP_MASK) == REQ_OP_DISCARD;
408}
409
404static inline int op_stat_group(unsigned int op) 410static inline int op_stat_group(unsigned int op)
405{ 411{
412 if (op_is_discard(op))
413 return STAT_DISCARD;
406 return op_is_write(op); 414 return op_is_write(op);
407} 415}
408 416
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index a75445446974..57864422a2c8 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -356,7 +356,8 @@ static inline void free_part_stats(struct hd_struct *part)
356 356
357#define part_stat_read_accum(part, field) \ 357#define part_stat_read_accum(part, field) \
358 (part_stat_read(part, field[STAT_READ]) + \ 358 (part_stat_read(part, field[STAT_READ]) + \
359 part_stat_read(part, field[STAT_WRITE])) 359 part_stat_read(part, field[STAT_WRITE]) + \
360 part_stat_read(part, field[STAT_DISCARD]))
360 361
361#define part_stat_add(cpu, part, field, addnd) do { \ 362#define part_stat_add(cpu, part, field, addnd) do { \
362 __part_stat_add((cpu), (part), field, addnd); \ 363 __part_stat_add((cpu), (part), field, addnd); \