#!/bin/bash
# SPDX-License-Identifier: GPL-3.0+
# Copyright (C) 2023 Daniel Wagner, SUSE Labs
#
# Test queue count changes on reconnect

. tests/nvme/rc

DESCRIPTION="Test queue count changes on reconnect"

requires() {
	_nvme_requires
	_have_loop
	_require_nvme_trtype tcp rdma fc
	_require_min_cpus 2
}

nvmf_wait_for_state() {
	local def_state_timeout=5
	local subsys_name="$1"
	local state="$2"
	local timeout="${3:-$def_state_timeout}"
	local nvmedev
	local state_file
	local start_time
	local end_time

	nvmedev=$(_find_nvme_dev "${subsys_name}")
	state_file="/sys/class/nvme-fabrics/ctl/${nvmedev}/state"

	start_time=$(date +%s)
	while ! grep -q "${state}" "${state_file}"; do
		sleep 1
		end_time=$(date +%s)
		if (( end_time - start_time > timeout )); then
			echo "expected state \"${state}\" not " \
				"reached within ${timeout} seconds"
			return 1
		fi
	done

	return 0
}

nvmf_check_queue_count() {
	local subsys_name="$1"
	local queue_count="$2"
	local nvmedev
	local queue_count_file

	nvmedev=$(_find_nvme_dev "${subsys_name}")
	queue_count_file=$(cat /sys/class/nvme-fabrics/ctl/"${nvmedev}"/queue_count)

	queue_count=$((queue_count + 1))
	if [[ "${queue_count}" -ne "${queue_count_file}" ]]; then
		echo "expected queue count ${queue_count} not set"
		return 1
	fi

	return 0
}

set_nvmet_attr_qid_max() {
	local nvmet_subsystem="$1"
	local qid_max="$2"
	local cfs_path="${NVMET_CFS}/subsystems/${nvmet_subsystem}"

	echo "${qid_max}" > "${cfs_path}/attr_qid_max"
}

set_qid_max() {
	local port="$1"
	local subsys_name="$2"
	local qid_max="$3"

	set_nvmet_attr_qid_max "${subsys_name}" "${qid_max}"
	nvmf_wait_for_state "${subsys_name}" "live" || return 1
	nvmf_check_queue_count "${subsys_name}" "${qid_max}" || return 1

	return 0
}

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

	_setup_nvmet

	local cfs_path="${NVMET_CFS}/subsystems/${def_subsysnqn}"
	local skipped=false

	_nvmet_target_setup --blkdev file

	if [[ -f "${cfs_path}/attr_qid_max" ]] ; then
		_nvme_connect_subsys "${nvme_trtype}" "${def_subsysnqn}" \
					--hostnqn "${def_hostnqn}" \
					--hostid "${def_hostid}" \
					--keep-alive-tmo 1 \
					--reconnect-delay 2

		if ! nvmf_wait_for_state "${def_subsysnqn}" "live" ; then
			echo FAIL
		else
			set_qid_max "${port}" "${def_subsysnqn}" 1 || echo FAIL
			set_qid_max "${port}" "${def_subsysnqn}" 2 || echo FAIL
		fi

		_nvme_disconnect_subsys "${def_subsysnqn}"
	else
		SKIP_REASONS+=("missing attr_qid_max feature")
		skipped=true
	fi

	_nvmet_target_cleanup

	if [[ "${skipped}" = true ]] ; then
		return 1
	fi

	echo "Test complete"
}
