#!/bin/bash
# SPDX-License-Identifier: GPL-3.0+
# Copyright (C) 2018 Omar Sandoval
#
# Test the iostats counters for time spent doing I/O where each I/O takes < 1
# jiffy. Regression test for commit b57e99b4b8b0 ("block: use nanosecond
# resolution for iostat").

. tests/block/rc
. common/null_blk

DESCRIPTION="do I/O faster than a jiffy and check iostats times"
QUICK=1

requires() {
	_have_null_blk
}

init_times() {
	init_read_ms="$(awk '{ print $4 }' /sys/block/nullb1/stat)"
	init_write_ms="$(awk '{ print $8 }' /sys/block/nullb1/stat)"
}

show_times() {
	read_ms="$(awk '{ print $4 }' /sys/block/nullb1/stat)"
	write_ms="$(awk '{ print $8 }' /sys/block/nullb1/stat)"

	# Print rounded to the nearest second
	printf 'read %d s\n' $(((read_ms - init_read_ms + 500) / 1000))
	printf 'write %d s\n' $(((write_ms - init_write_ms + 500) / 1000))
}

test() {
	local init_read_ms init_write_ms read_ms write_ms

	echo "Running ${TEST_NAME}"

	# The maximum value for CONFIG_HZ is 1000. I.e., a tick is one
	# millisecond. So, make each I/O take half a millisecond.
	if ! _configure_null_blk nullb1 irqmode=2 completion_nsec=500000 \
			power=1; then
		return 1
	fi

	init_times
	show_times

	# 1500 * 0.5 ms is 0.75 seconds, allowing for some overhead so
	# that it rounds to one second.
	dd if=/dev/nullb1 of=/dev/null bs=4096 iflag=direct count=1500 status=none
	show_times

	dd if=/dev/zero of=/dev/nullb1 bs=4096 oflag=direct count=1500 status=none
	show_times

	# 1800 * 0.5 ms is 0.9 seconds.
	dd if=/dev/nullb1 of=/dev/null bs=4096 iflag=direct count=1500 status=none &
	dd if=/dev/zero of=/dev/nullb1 bs=4096 oflag=direct count=1800 status=none &
	dd if=/dev/zero of=/dev/nullb1 bs=4096 oflag=direct count=1800 status=none &
	wait
	show_times

	_exit_null_blk

	unset init_read_ms init_write_ms read_ms write_ms

	echo "Test complete"
}
