Skip to content

Commit b57e99b

Browse files
osandovaxboe
authored andcommitted
block: use nanosecond resolution for iostat
Klaus Kusche reported that the I/O busy time in /proc/diskstats was not updating properly on 4.18. This is because we started using ktime to track elapsed time, and we convert nanoseconds to jiffies when we update the partition counter. However, this gets rounded down, so any I/Os that take less than a jiffy are not accounted for. Previously in this case, the value of jiffies would sometimes increment while we were doing I/O, so at least some I/Os were accounted for. Let's convert the stats to use nanoseconds internally. We still report milliseconds as before, now more accurately than ever. The value is still truncated to 32 bits for backwards compatibility. Fixes: 522a777 ("block: consolidate struct request timestamp fields") Cc: stable@vger.kernel.org Reported-by: Klaus Kusche <klaus.kusche@computerix.info> Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent d611aaf commit b57e99b

File tree

5 files changed

+12
-11
lines changed

5 files changed

+12
-11
lines changed

block/bio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1684,7 +1684,7 @@ void generic_end_io_acct(struct request_queue *q, int req_op,
16841684
const int sgrp = op_stat_group(req_op);
16851685
int cpu = part_stat_lock();
16861686

1687-
part_stat_add(cpu, part, ticks[sgrp], duration);
1687+
part_stat_add(cpu, part, nsecs[sgrp], jiffies_to_nsecs(duration));
16881688
part_round_stats(q, cpu, part);
16891689
part_dec_in_flight(q, part, op_is_write(req_op));
16901690

block/blk-core.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2733,17 +2733,15 @@ void blk_account_io_done(struct request *req, u64 now)
27332733
* containing request is enough.
27342734
*/
27352735
if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) {
2736-
unsigned long duration;
27372736
const int sgrp = op_stat_group(req_op(req));
27382737
struct hd_struct *part;
27392738
int cpu;
27402739

2741-
duration = nsecs_to_jiffies(now - req->start_time_ns);
27422740
cpu = part_stat_lock();
27432741
part = req->part;
27442742

27452743
part_stat_inc(cpu, part, ios[sgrp]);
2746-
part_stat_add(cpu, part, ticks[sgrp], duration);
2744+
part_stat_add(cpu, part, nsecs[sgrp], now - req->start_time_ns);
27472745
part_round_stats(req->q, cpu, part);
27482746
part_dec_in_flight(req->q, part, rq_data_dir(req));
27492747

block/genhd.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,18 +1343,18 @@ static int diskstats_show(struct seq_file *seqf, void *v)
13431343
part_stat_read(hd, ios[STAT_READ]),
13441344
part_stat_read(hd, merges[STAT_READ]),
13451345
part_stat_read(hd, sectors[STAT_READ]),
1346-
jiffies_to_msecs(part_stat_read(hd, ticks[STAT_READ])),
1346+
(unsigned int)part_stat_read_msecs(hd, STAT_READ),
13471347
part_stat_read(hd, ios[STAT_WRITE]),
13481348
part_stat_read(hd, merges[STAT_WRITE]),
13491349
part_stat_read(hd, sectors[STAT_WRITE]),
1350-
jiffies_to_msecs(part_stat_read(hd, ticks[STAT_WRITE])),
1350+
(unsigned int)part_stat_read_msecs(hd, STAT_WRITE),
13511351
inflight[0],
13521352
jiffies_to_msecs(part_stat_read(hd, io_ticks)),
13531353
jiffies_to_msecs(part_stat_read(hd, time_in_queue)),
13541354
part_stat_read(hd, ios[STAT_DISCARD]),
13551355
part_stat_read(hd, merges[STAT_DISCARD]),
13561356
part_stat_read(hd, sectors[STAT_DISCARD]),
1357-
jiffies_to_msecs(part_stat_read(hd, ticks[STAT_DISCARD]))
1357+
(unsigned int)part_stat_read_msecs(hd, STAT_DISCARD)
13581358
);
13591359
}
13601360
disk_part_iter_exit(&piter);

block/partition-generic.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,18 +136,18 @@ ssize_t part_stat_show(struct device *dev,
136136
part_stat_read(p, ios[STAT_READ]),
137137
part_stat_read(p, merges[STAT_READ]),
138138
(unsigned long long)part_stat_read(p, sectors[STAT_READ]),
139-
jiffies_to_msecs(part_stat_read(p, ticks[STAT_READ])),
139+
(unsigned int)part_stat_read_msecs(p, STAT_READ),
140140
part_stat_read(p, ios[STAT_WRITE]),
141141
part_stat_read(p, merges[STAT_WRITE]),
142142
(unsigned long long)part_stat_read(p, sectors[STAT_WRITE]),
143-
jiffies_to_msecs(part_stat_read(p, ticks[STAT_WRITE])),
143+
(unsigned int)part_stat_read_msecs(p, STAT_WRITE),
144144
inflight[0],
145145
jiffies_to_msecs(part_stat_read(p, io_ticks)),
146146
jiffies_to_msecs(part_stat_read(p, time_in_queue)),
147147
part_stat_read(p, ios[STAT_DISCARD]),
148148
part_stat_read(p, merges[STAT_DISCARD]),
149149
(unsigned long long)part_stat_read(p, sectors[STAT_DISCARD]),
150-
jiffies_to_msecs(part_stat_read(p, ticks[STAT_DISCARD])));
150+
(unsigned int)part_stat_read_msecs(p, STAT_DISCARD));
151151
}
152152

153153
ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr,

include/linux/genhd.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@ struct partition {
8383
} __attribute__((packed));
8484

8585
struct disk_stats {
86+
u64 nsecs[NR_STAT_GROUPS];
8687
unsigned long sectors[NR_STAT_GROUPS];
8788
unsigned long ios[NR_STAT_GROUPS];
8889
unsigned long merges[NR_STAT_GROUPS];
89-
unsigned long ticks[NR_STAT_GROUPS];
9090
unsigned long io_ticks;
9191
unsigned long time_in_queue;
9292
};
@@ -354,6 +354,9 @@ static inline void free_part_stats(struct hd_struct *part)
354354

355355
#endif /* CONFIG_SMP */
356356

357+
#define part_stat_read_msecs(part, which) \
358+
div_u64(part_stat_read(part, nsecs[which]), NSEC_PER_MSEC)
359+
357360
#define part_stat_read_accum(part, field) \
358361
(part_stat_read(part, field[STAT_READ]) + \
359362
part_stat_read(part, field[STAT_WRITE]) + \

0 commit comments

Comments
 (0)