提交 05b2399b 编写于 作者: Z Zhang Wensheng 提交者: Zheng Zengkai

block: fix inaccurate io_ticks by set 'precise_iostat'

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I5X6RT
CVE: NA

--------------------------------

After introducing commit 5b18b5a7 ("block: delete part_round_stats
and switch to less precise counting"), '%util' accounted by iostat
will be over reality data. In fact, the device is quite idle, but
iostat may show '%util' as a big number (e.g. 50%). It can produce by fio:

fio --name=1 --direct=1 --bs=4k --rw=read --filename=/dev/sda \
	   --thinktime=4ms --runtime=180
We fix this by using a switch(precise_iostat=1) to control whether or not
acconut ioticks precisely.

fixes: 5b18b5a7 ("block: delete part_round_stats and switch to less precise counting")
Signed-off-by: NZhang Wensheng <zhangwensheng5@huawei.com>
Signed-off-by: NYu Kuai <yukuai3@huawei.com>
Reviewed-by: NJason Yan <yanaijie@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 e45f1890
...@@ -62,6 +62,21 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug); ...@@ -62,6 +62,21 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
DEFINE_IDA(blk_queue_ida); DEFINE_IDA(blk_queue_ida);
bool precise_iostat;
static int __init precise_iostat_setup(char *str)
{
bool precise;
if (!strtobool(str, &precise)) {
precise_iostat = precise;
pr_info("precise iostat %d\n", precise_iostat);
}
return 1;
}
__setup("precise_iostat=", precise_iostat_setup);
/* /*
* For queue allocation * For queue allocation
*/ */
...@@ -1258,9 +1273,14 @@ void update_io_ticks(struct hd_struct *part, unsigned long now, bool end) ...@@ -1258,9 +1273,14 @@ void update_io_ticks(struct hd_struct *part, unsigned long now, bool end)
unsigned long stamp; unsigned long stamp;
again: again:
stamp = READ_ONCE(part->stamp); stamp = READ_ONCE(part->stamp);
if (unlikely(time_after(now, stamp))) { if (unlikely(time_after(now, stamp)) &&
if (likely(cmpxchg(&part->stamp, stamp, now) == stamp)) likely(cmpxchg(&part->stamp, stamp, now) == stamp)) {
if (precise_iostat) {
if (end || part_in_flight(part))
__part_stat_add(part, io_ticks, now - stamp);
} else {
__part_stat_add(part, io_ticks, end ? now - stamp : 1); __part_stat_add(part, io_ticks, end ? now - stamp : 1);
}
} }
if (part->partno) { if (part->partno) {
part = &part_to_disk(part)->part0; part = &part_to_disk(part)->part0;
...@@ -1318,6 +1338,8 @@ void blk_account_io_done(struct request *req, u64 now) ...@@ -1318,6 +1338,8 @@ void blk_account_io_done(struct request *req, u64 now)
#else #else
part_stat_add(part, nsecs[sgrp], now - req->start_time_ns); part_stat_add(part, nsecs[sgrp], now - req->start_time_ns);
#endif #endif
if (precise_iostat)
part_stat_local_dec(part, in_flight[rq_data_dir(req)]);
part_stat_unlock(); part_stat_unlock();
hd_struct_put(part); hd_struct_put(part);
...@@ -1333,6 +1355,8 @@ void blk_account_io_start(struct request *rq) ...@@ -1333,6 +1355,8 @@ void blk_account_io_start(struct request *rq)
part_stat_lock(); part_stat_lock();
update_io_ticks(rq->part, jiffies, false); update_io_ticks(rq->part, jiffies, false);
if (precise_iostat)
part_stat_local_inc(rq->part, in_flight[rq_data_dir(rq)]);
part_stat_unlock(); part_stat_unlock();
} }
......
...@@ -696,6 +696,8 @@ static void blk_account_io_merge_request(struct request *req) ...@@ -696,6 +696,8 @@ static void blk_account_io_merge_request(struct request *req)
if (blk_do_io_stat(req)) { if (blk_do_io_stat(req)) {
part_stat_lock(); part_stat_lock();
part_stat_inc(req->part, merges[op_stat_group(req_op(req))]); part_stat_inc(req->part, merges[op_stat_group(req_op(req))]);
if (precise_iostat)
part_stat_local_dec(req->part, in_flight[rq_data_dir(req)]);
part_stat_unlock(); part_stat_unlock();
hd_struct_put(req->part); hd_struct_put(req->part);
......
...@@ -112,7 +112,7 @@ static void part_stat_read_all(struct hd_struct *part, struct disk_stats *stat) ...@@ -112,7 +112,7 @@ static void part_stat_read_all(struct hd_struct *part, struct disk_stats *stat)
} }
} }
static unsigned int part_in_flight(struct hd_struct *part) unsigned int part_in_flight(struct hd_struct *part)
{ {
unsigned int inflight = 0; unsigned int inflight = 0;
int cpu; int cpu;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/sbitmap.h> #include <linux/sbitmap.h>
extern bool precise_iostat;
struct module; struct module;
struct scsi_ioctl_command; struct scsi_ioctl_command;
......
...@@ -304,6 +304,7 @@ extern void disk_part_iter_exit(struct disk_part_iter *piter); ...@@ -304,6 +304,7 @@ extern void disk_part_iter_exit(struct disk_part_iter *piter);
extern bool disk_has_partitions(struct gendisk *disk); extern bool disk_has_partitions(struct gendisk *disk);
/* block/genhd.c */ /* block/genhd.c */
extern unsigned int part_in_flight(struct hd_struct *part);
extern void device_add_disk(struct device *parent, struct gendisk *disk, extern void device_add_disk(struct device *parent, struct gendisk *disk,
const struct attribute_group **groups); const struct attribute_group **groups);
static inline void add_disk(struct gendisk *disk) static inline void add_disk(struct gendisk *disk)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册