#!/bin/bash
# SPDX-License-Identifier: GPL-3.0+
# Copyright (C) 2018 Omar Sandoval
#
# Smoke test blk-mq timeout handling with null-blk.

. tests/block/rc
. common/null_blk

DESCRIPTION="run null-blk with blk-mq and timeout injection configured"

requires() {
	_have_null_blk && _have_module_param null_blk timeout
}

test() {
	echo "Running ${TEST_NAME}"

	local faultb=faultb0

	# Here, we fail 50% of I/Os.
	if ! _configure_null_blk "$faultb" timeout_inject/probability=50 \
	     timeout_inject/times=-1 timeout_inject/verbose=0 power=1 \
	     > /dev/null 2>&1; then
		rmdir /sys/kernel/config/nullb/"$faultb"
		if _module_file_exists null_blk; then
			faultb=nullb0

			# Fall back to set up with module parameter. The format
			# is "<interval>,<probability>,<space>,<times>"
			if ! _init_null_blk timeout='1,50,0,-1'; then
				echo "Configuring null_blk failed"
				return 1
			fi
		else
			SKIP_REASONS+=("requires fault injection via configfs or modular null_blk")
			return 1
		fi
	fi

	for sched in $(_io_schedulers "$faultb"); do
		echo "Testing $sched" >> "$FULL"
		echo "$sched" > /sys/block/"$faultb"/queue/scheduler
		# Do a bunch of I/Os which will timeout and then complete. The
		# only thing we're really testing here is that this doesn't
		# crash or hang.
		for ((i = 0; i < 100; i++)); do
			dd if=/dev/"$faultb" of=/dev/null bs=4K count=4 \
				iflag=direct status=none > /dev/null 2>&1 &
		done
		wait
	done

	_exit_null_blk

	echo "Test complete"
}
