[RFC blktests v1 1/1] nvme/050: test DNR handling on reconnect

From: Daniel Wagner
Date: Wed Jun 21 2023 - 11:58:49 EST


When the host gets disconnected and tries to reconnect,
it should honor the DNR bit and do not retry to connect
with the same parameters.

Signed-off-by: Daniel Wagner <dwagner@xxxxxxx>
---
tests/nvme/050 | 126 +++++++++++++++++++++++++++++++++++++++++++++
tests/nvme/050.out | 2 +
2 files changed, 128 insertions(+)
create mode 100644 tests/nvme/050
create mode 100644 tests/nvme/050.out

diff --git a/tests/nvme/050 b/tests/nvme/050
new file mode 100644
index 000000000000..d33eb24e2f13
--- /dev/null
+++ b/tests/nvme/050
@@ -0,0 +1,126 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-3.0+
+# Copyright (C) 2023 SUSE LLC
+#
+# Test DNR is handled on connnect attempt with invalid arguments.
+
+. tests/nvme/rc
+
+DESCRIPTION="test DNR is handled on connect attempt with invalid arguments"
+
+requires() {
+ _nvme_requires
+ _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_wait_for_ctrl_delete() {
+ local def_state_timeout=5
+ local nvmedev="$1"
+ local timeout="${2:-$def_state_timeout}"
+ local ctrl="/sys/class/nvme-fabrics/ctl/${nvmedev}/state"
+ local start_time
+ local end_time
+
+ start_time=$(date +%s)
+ while [ -f "${ctrl}" ]; do
+ sleep 1
+ end_time=$(date +%s)
+ if (( end_time - start_time > timeout )); then
+ echo "controller \"${nvmedev}\" not deleted" \
+ "within ${timeout} seconds"
+ return 1
+ fi
+ done
+
+ 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"
+}
+
+test() {
+ echo "Running ${TEST_NAME}"
+
+ _setup_nvmet
+
+ local port
+ local loop_dev
+ local file_path="$TMPDIR/img"
+ local subsys_name="blktests-subsystem-1"
+ local hostid="77b49aba-06b4-431a-9af8-75e318740f1a"
+ local hostnqn="nqn.2014-08.org.nvmexpress:uuid:${hostid}"
+ local cfs_path="${NVMET_CFS}/subsystems/${subsys_name}"
+ local nvmedev
+
+ truncate -s "${nvme_img_size}" "${file_path}"
+
+ loop_dev="$(losetup -f --show "${file_path}")"
+
+ _create_nvmet_subsystem "${subsys_name}" "${loop_dev}" \
+ "91fdba0d-f87b-4c25-b80f-db7be1418b9e"
+ port="$(_create_nvmet_port "${nvme_trtype}")"
+ _add_nvmet_subsys_to_port "${port}" "${subsys_name}"
+
+ _nvme_connect_subsys "${nvme_trtype}" "${subsys_name}" \
+ --hostnqn "${hostnqn}" \
+ --reconnect-delay 1 \
+ --ctrl-loss-tmo 10
+
+ nvmf_wait_for_state "${subsys_name}" "live"
+ nvmedev=$(_find_nvme_dev "${subsys_name}")
+
+ # Only allow connects from ${def_hostnqn}
+ echo 0 > "${cfs_path}/attr_allow_any_host"
+
+ # Force a reconnect
+ set_nvmet_attr_qid_max "${subsys_name}" 1
+
+ # The reconnect fails with the DNR bit set
+ # Thus the host should remove the controller
+ nvmf_wait_for_ctrl_delete "${nvmedev}"
+
+ _nvme_disconnect_subsys "${subsys_name}" >> "$FULL" 2>&1
+
+ _remove_nvmet_subsystem_from_port "${port}" "${subsys_name}"
+ _remove_nvmet_subsystem "${subsys_name}"
+ _remove_nvmet_port "${port}"
+
+ losetup -d "${loop_dev}"
+
+ rm "${file_path}"
+
+ echo "Test complete"
+}
diff --git a/tests/nvme/050.out b/tests/nvme/050.out
new file mode 100644
index 000000000000..b78b05f78424
--- /dev/null
+++ b/tests/nvme/050.out
@@ -0,0 +1,2 @@
+Running nvme/050
+Test complete
--
2.41.0