Commit 05b2399b authored by Zhang Wensheng's avatar Zhang Wensheng Committed by Zheng Zengkai
Browse files

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: default avatarZhang Wensheng <zhangwensheng5@huawei.com>
Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
Reviewed-by: default avatarJason Yan <yanaijie@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent e45f1890
Loading
Loading
Loading
Loading
+26 −2
Original line number Diff line number Diff line
@@ -62,6 +62,21 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);

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
 */
@@ -1258,10 +1273,15 @@ void update_io_ticks(struct hd_struct *part, unsigned long now, bool end)
	unsigned long stamp;
again:
	stamp = READ_ONCE(part->stamp);
	if (unlikely(time_after(now, stamp))) {
		if (likely(cmpxchg(&part->stamp, stamp, now) == stamp))
	if (unlikely(time_after(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);
		}
	}
	if (part->partno) {
		part = &part_to_disk(part)->part0;
		goto again;
@@ -1318,6 +1338,8 @@ void blk_account_io_done(struct request *req, u64 now)
#else
		part_stat_add(part, nsecs[sgrp], now - req->start_time_ns);
#endif
		if (precise_iostat)
			part_stat_local_dec(part, in_flight[rq_data_dir(req)]);
		part_stat_unlock();

		hd_struct_put(part);
@@ -1333,6 +1355,8 @@ void blk_account_io_start(struct request *rq)

	part_stat_lock();
	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();
}

+2 −0
Original line number Diff line number Diff line
@@ -696,6 +696,8 @@ static void blk_account_io_merge_request(struct request *req)
	if (blk_do_io_stat(req)) {
		part_stat_lock();
		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();

		hd_struct_put(req->part);
+1 −1
Original line number Diff line number Diff line
@@ -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;
	int cpu;
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/pm.h>
#include <linux/sbitmap.h>

extern bool precise_iostat;
struct module;
struct scsi_ioctl_command;

+1 −0
Original line number Diff line number Diff line
@@ -304,6 +304,7 @@ extern void disk_part_iter_exit(struct disk_part_iter *piter);
extern bool disk_has_partitions(struct gendisk *disk);

/* block/genhd.c */
extern unsigned int part_in_flight(struct hd_struct *part);
extern void device_add_disk(struct device *parent, struct gendisk *disk,
			    const struct attribute_group **groups);
static inline void add_disk(struct gendisk *disk)