[RFC PATCH blktests v1] nvme: check user queue limits across namespace rescans

Yao Sang <[email protected]>
Newsgroups org.infradead.lists.linux-nvme
Message-ID <[email protected]>
NVMe namespace rescans should not reset queue user caps on the namespace
head. Add a regression test that lowers max_sectors_kb, optionally lowers
discard_max_bytes, optionally disables write_zeroes_unmap_max_bytes, runs
nvme ns-rescan, and verifies that the user values are preserved.

Mark the test as zoned-capable so it can run on ZNS devices as well.

Signed-off-by: Yao Sang <[email protected]>
---
 tests/nvme/068     | 151 +++++++++++++++++++++++++++++++++++++++++++++
 tests/nvme/068.out |   2 +
 2 files changed, 153 insertions(+)
 create mode 100755 tests/nvme/068
 create mode 100644 tests/nvme/068.out

diff --git a/tests/nvme/068 b/tests/nvme/068
new file mode 100755
index 0000000..a7786db
--- /dev/null
+++ b/tests/nvme/068
@@ -0,0 +1,151 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-3.0+
+#
+# Test queue user limits across NVMe namespace rescans.
+
+. tests/nvme/rc
+
+DESCRIPTION="check queue user limits across NVMe namespace rescans"
+QUICK=1
+CAN_BE_ZONED=1
+
+requires() {
+	_nvme_requires
+	_have_program nvme
+}
+
+_test_dev_nvme_ctrl_dev() {
+	local ctrl
+
+	ctrl="$(_nvme_get_ctrl_list | head -n 1)"
+	if [[ -z "$ctrl" ]]; then
+		return 1
+	fi
+
+	echo "/dev/$(basename "$ctrl")"
+}
+
+device_requires() {
+	local ctrl_dev
+
+	_require_test_dev_is_nvme
+	_require_test_dev_sysfs queue/max_sectors_kb queue/max_hw_sectors_kb
+
+	if ! ctrl_dev="$(_test_dev_nvme_ctrl_dev)"; then
+		SKIP_REASONS+=("unable to find NVMe controller for $TEST_DEV")
+		return 1
+	fi
+	if [[ ! -c "$ctrl_dev" ]]; then
+		SKIP_REASONS+=("$ctrl_dev is not a character device")
+		return 1
+	fi
+}
+
+_cleanup_queue_limits() {
+	if [[ -z "${nvme068_queue_path:-}" ]]; then
+		return
+	fi
+
+	echo "$nvme068_max_sectors_kb" > "$nvme068_queue_path/max_sectors_kb"
+	if [[ -n "${nvme068_discard_max_bytes:-}" ]]; then
+		echo "$nvme068_discard_max_bytes" > \
+			"$nvme068_queue_path/discard_max_bytes"
+	fi
+	if [[ -n "${nvme068_wzeroes_unmap_max_bytes:-}" ]]; then
+		echo "$nvme068_wzeroes_unmap_max_bytes" > \
+			"$nvme068_queue_path/write_zeroes_unmap_max_bytes"
+	fi
+}
+
+_check_queue_limit() {
+	local queue_path=$1
+	local attr=$2
+	local expected=$3
+	local actual
+
+	actual="$(cat "$queue_path/$attr")"
+	if [[ "$actual" -ne "$expected" ]]; then
+		echo "ERROR: $attr changed from $expected to $actual"
+	fi
+}
+
+test_device() {
+	local queue_path="$TEST_DEV_SYSFS/queue"
+	local ctrl_dev
+	local max_hw_sectors_kb
+	local max_sectors_kb
+	local discard_hw_bytes
+	local discard_granularity
+	local discard_max_bytes=""
+	local wzeroes_unmap_hw_bytes
+	local wzeroes_unmap_max_bytes=""
+
+	echo "Running ${TEST_NAME}"
+
+	ctrl_dev="$(_test_dev_nvme_ctrl_dev)"
+	nvme068_queue_path="$queue_path"
+	nvme068_max_sectors_kb="$(cat "$queue_path/max_sectors_kb")"
+	nvme068_discard_max_bytes=""
+	nvme068_wzeroes_unmap_max_bytes=""
+	_register_test_cleanup _cleanup_queue_limits
+
+	max_hw_sectors_kb="$(cat "$queue_path/max_hw_sectors_kb")"
+	max_sectors_kb=$((max_hw_sectors_kb / 2))
+	if ((max_sectors_kb == 0)); then
+		max_sectors_kb=1
+	fi
+
+	if [[ -e "$queue_path/discard_max_bytes" &&
+	      -e "$queue_path/discard_max_hw_bytes" &&
+	      -e "$queue_path/discard_granularity" ]]; then
+		nvme068_discard_max_bytes="$(cat "$queue_path/discard_max_bytes")"
+		if echo "$nvme068_discard_max_bytes" > \
+				"$queue_path/discard_max_bytes" 2>/dev/null; then
+			discard_hw_bytes="$(cat "$queue_path/discard_max_hw_bytes")"
+			discard_granularity="$(cat "$queue_path/discard_granularity")"
+			if ((discard_granularity > 0 &&
+			     discard_hw_bytes >= discard_granularity * 2)); then
+				discard_max_bytes=$(((discard_hw_bytes / 2) /
+					discard_granularity * discard_granularity))
+			fi
+		else
+			nvme068_discard_max_bytes=""
+		fi
+	fi
+
+	if [[ -e "$queue_path/write_zeroes_unmap_max_bytes" &&
+	      -e "$queue_path/write_zeroes_unmap_max_hw_bytes" ]]; then
+		nvme068_wzeroes_unmap_max_bytes="$(<"$queue_path/write_zeroes_unmap_max_bytes")"
+		wzeroes_unmap_hw_bytes="$(<"$queue_path/write_zeroes_unmap_max_hw_bytes")"
+		if ((wzeroes_unmap_hw_bytes > 0)); then
+			wzeroes_unmap_max_bytes=0
+		fi
+	fi
+
+	echo "$max_sectors_kb" > "$queue_path/max_sectors_kb"
+	if [[ -n "$discard_max_bytes" ]]; then
+		echo "$discard_max_bytes" > "$queue_path/discard_max_bytes"
+	fi
+	if [[ -n "$wzeroes_unmap_max_bytes" ]]; then
+		echo "$wzeroes_unmap_max_bytes" > \
+			"$queue_path/write_zeroes_unmap_max_bytes"
+	fi
+
+	if ! nvme ns-rescan "$ctrl_dev" >> "$FULL" 2>&1; then
+		echo "ERROR: ns-rescan failed"
+	fi
+
+	_check_queue_limit "$queue_path" max_sectors_kb "$max_sectors_kb"
+	if [[ -n "$discard_max_bytes" ]]; then
+		_check_queue_limit "$queue_path" discard_max_bytes \
+			"$discard_max_bytes"
+	fi
+	if [[ -n "$wzeroes_unmap_max_bytes" ]]; then
+		_check_queue_limit "$queue_path" write_zeroes_unmap_max_bytes \
+			"$wzeroes_unmap_max_bytes"
+	fi
+
+	_cleanup_queue_limits
+
+	echo "Test complete"
+}
diff --git a/tests/nvme/068.out b/tests/nvme/068.out
new file mode 100644
index 0000000..28407c6
--- /dev/null
+++ b/tests/nvme/068.out
@@ -0,0 +1,2 @@
+Running nvme/068
+Test complete
-- 
2.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.