* [PATCH blktests] nvme/075: test the per-queue io_cpu sysfs attribute
[not found] <20261023230426.6425-1-saravanand@crusoe.ai>
@ 2026-10-23 23:08 ` Saravanan D
2026-10-29 11:50 ` Shin'ichiro Kawasaki
0 siblings, 1 reply; 2+ messages in thread
From: Saravanan D @ 2026-10-23 23:08 UTC (permalink / raw)
To: linux-block
Cc: shinichiro.kawasaki, linux-nvme, dwagner, hare, nilay, sagi,
kbusch, iyamahata, kiyer, ganbalagane, sjpark, bchen, Saravanan D
nvme-tcp exposes /sys/class/nvme/nvmeX/queues/<qid>/io_cpu and managed,
so a control plane can choose the CPU that runs each I/O queue's socket
work [1]. Test that
- io_cpu reads back a written CPU and rejects invalid values
- managed is read only and turns 0 once io_cpu is written
- an assignment survives a controller reset
- the queue directories follow the queue count as attr_qid_max
shrinks and grows it
- removing the controller while io_cpu is written completes
The test skips when the kernel does not have the attribute.
[1] https://lore.kernel.org/linux-nvme/20261018010059.83120-1-saravanand@crusoe.ai/
Assisted-by: Claude:claude-opus-5-5 [Claude Code]
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
---
This tests the kernel series in the parent thread, which is under
review on linux-nvme.
tests/nvme/075 | 185 +++++++++++++++++++++++++++++++++++++++++++++
tests/nvme/075.out | 2 +
2 files changed, 187 insertions(+)
create mode 100755 tests/nvme/075
create mode 100644 tests/nvme/075.out
diff --git a/tests/nvme/075 b/tests/nvme/075
new file mode 100755
index 0000000..0b4bce5
--- /dev/null
+++ b/tests/nvme/075
@@ -0,0 +1,185 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-3.0+
+# Copyright (C) 2026 Saravanan D <saravanand@crusoe.ai>
+#
+# Test the per-queue io_cpu sysfs attribute of nvme-tcp
+
+. tests/nvme/rc
+
+DESCRIPTION="test the per-queue io_cpu sysfs attribute"
+
+requires() {
+ _nvme_requires
+ _have_loop
+ _require_nvme_trtype tcp
+ _require_min_cpus 2
+}
+
+set_conditions() {
+ _set_nvme_trtype "$@"
+}
+
+# last CPU in the online list, and the first CPU id past the possible ones
+last_online_cpu() {
+ awk -F'[-,]' '{ print $NF }' /sys/devices/system/cpu/online
+}
+
+first_impossible_cpu() {
+ echo $(( $(awk -F'[-,]' '{ print $NF }' /sys/devices/system/cpu/possible) + 1 ))
+}
+
+nr_queue_dirs() {
+ local nvmedev="$1"
+
+ find "/sys/class/nvme/${nvmedev}/queues" -mindepth 1 -maxdepth 1 \
+ -type d 2>/dev/null | wc -l
+}
+
+expect_attr() {
+ local file="$1"
+ local expected="$2"
+ local value
+
+ value=$(cat "${file}")
+ if [[ "${value}" != "${expected}" ]]; then
+ echo "${file}: read ${value}, expected ${expected}"
+ return 1
+ fi
+ return 0
+}
+
+test_read_write() {
+ local qdir="$1"
+ local cpu="$2"
+ local bad
+
+ expect_attr "${qdir}/1/managed" 1
+
+ echo "${cpu}" > "${qdir}/1/io_cpu"
+ expect_attr "${qdir}/1/io_cpu" "${cpu}"
+ expect_attr "${qdir}/1/managed" 0
+
+ for bad in "$(first_impossible_cpu)" -2 abc 0x1; do
+ if { echo "${bad}" > "${qdir}/1/io_cpu"; } 2>/dev/null; then
+ echo "io_cpu accepted ${bad}"
+ fi
+ done
+ expect_attr "${qdir}/1/io_cpu" "${cpu}"
+
+ if { echo 1 > "${qdir}/1/managed"; } 2>/dev/null; then
+ echo "managed is writable"
+ fi
+
+ echo unbound > "${qdir}/2/io_cpu"
+ expect_attr "${qdir}/2/io_cpu" -1
+ echo -1 > "${qdir}/2/io_cpu"
+ expect_attr "${qdir}/2/io_cpu" -1
+ expect_attr "${qdir}/2/managed" 0
+}
+
+test_reset() {
+ local nvmedev="$1"
+ local qdir="$2"
+ local cpu="$3"
+
+ echo 1 > "/sys/class/nvme/${nvmedev}/reset_controller"
+ _nvmf_wait_for_state "${def_subsysnqn}" "live" || return 1
+
+ expect_attr "${qdir}/1/io_cpu" "${cpu}"
+ expect_attr "${qdir}/1/managed" 0
+ expect_attr "${qdir}/2/io_cpu" -1
+ expect_attr "${qdir}/2/managed" 0
+}
+
+set_qid_max() {
+ local nvmedev="$1"
+ local qid_max="$2"
+ local queue_count_file="/sys/class/nvme-fabrics/ctl/${nvmedev}/queue_count"
+ local retries=10
+
+ echo "${qid_max}" > \
+ "${NVMET_CFS}/subsystems/${def_subsysnqn}/attr_qid_max"
+ while [[ "$(cat "${queue_count_file}")" -ne $((qid_max + 1)) ]]; do
+ if (( retries-- == 0 )); then
+ echo "queue count did not change to $((qid_max + 1))"
+ return 1
+ fi
+ sleep 1
+ done
+ _nvmf_wait_for_state "${def_subsysnqn}" "live" || return 1
+
+ if [[ "$(nr_queue_dirs "${nvmedev}")" -ne "${qid_max}" ]]; then
+ echo "$(nr_queue_dirs "${nvmedev}") queue directories," \
+ "expected ${qid_max}"
+ return 1
+ fi
+ return 0
+}
+
+io_cpu_writer() {
+ local qdir="$1"
+ local cpu="$2"
+ local file
+
+ while true; do
+ for file in "${qdir}"/*/io_cpu; do
+ { echo "${cpu}" > "${file}"; } 2>/dev/null
+ { echo unbound > "${file}"; } 2>/dev/null
+ done
+ done
+}
+
+test() {
+ echo "Running ${TEST_NAME}"
+
+ _setup_nvmet
+
+ local cfs_path="${NVMET_CFS}/subsystems/${def_subsysnqn}"
+ local skipped=false
+ local nvmedev qdir cpu writer
+
+ _nvmet_target_setup --blkdev file
+
+ _nvme_connect_subsys --keep-alive-tmo 1 --reconnect-delay 2
+ _nvmf_wait_for_state "${def_subsysnqn}" "live"
+ nvmedev=$(_find_nvme_dev "${def_subsysnqn}")
+ qdir="/sys/class/nvme/${nvmedev}/queues"
+ cpu=$(last_online_cpu)
+
+ if [[ ! -f "${qdir}/1/io_cpu" ]]; then
+ SKIP_REASONS+=("missing per-queue io_cpu attribute")
+ skipped=true
+ elif [[ "$(nr_queue_dirs "${nvmedev}")" -lt 2 ]]; then
+ SKIP_REASONS+=("controller has fewer than 2 I/O queues")
+ skipped=true
+ else
+ test_read_write "${qdir}" "${cpu}"
+ test_reset "${nvmedev}" "${qdir}" "${cpu}"
+
+ if [[ -f "${cfs_path}/attr_qid_max" ]]; then
+ set_qid_max "${nvmedev}" 1
+ expect_attr "${qdir}/1/io_cpu" "${cpu}"
+ set_qid_max "${nvmedev}" 2
+ fi
+
+ # remove the controller while its queue directories are written
+ io_cpu_writer "${qdir}" "${cpu}" &
+ writer=$!
+ sleep 1
+ fi
+
+ _nvme_disconnect_subsys
+
+ if [[ -n "${writer}" ]]; then
+ kill "${writer}"
+ wait "${writer}" 2>/dev/null
+ fi
+
+ _nvmet_target_cleanup
+
+ if [[ "${skipped}" = true ]] ; then
+ return 1
+ fi
+
+ echo "Test complete"
+}
diff --git a/tests/nvme/075.out b/tests/nvme/075.out
new file mode 100644
index 0000000..0613dfa
--- /dev/null
+++ b/tests/nvme/075.out
@@ -0,0 +1,2 @@
+Running nvme/075
+Test complete
--
2.55.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH blktests] nvme/075: test the per-queue io_cpu sysfs attribute
2026-10-23 23:08 ` [PATCH blktests] nvme/075: test the per-queue io_cpu sysfs attribute Saravanan D
@ 2026-10-29 11:50 ` Shin'ichiro Kawasaki
0 siblings, 0 replies; 2+ messages in thread
From: Shin'ichiro Kawasaki @ 2026-10-29 11:50 UTC (permalink / raw)
To: Saravanan D
Cc: linux-block, linux-nvme, dwagner, hare, nilay, sagi, kbusch,
iyamahata, kiyer, ganbalagane, sjpark, bchen
On Oct 23, 2026 / 16:08, Saravanan D wrote:
> nvme-tcp exposes /sys/class/nvme/nvmeX/queues/<qid>/io_cpu and managed,
> so a control plane can choose the CPU that runs each I/O queue's socket
> work [1]. Test that
>
> - io_cpu reads back a written CPU and rejects invalid values
> - managed is read only and turns 0 once io_cpu is written
> - an assignment survives a controller reset
> - the queue directories follow the queue count as attr_qid_max
> shrinks and grows it
> - removing the controller while io_cpu is written completes
>
> The test skips when the kernel does not have the attribute.
>
> [1] https://lore.kernel.org/linux-nvme/20261018010059.83120-1-saravanand@crusoe.ai/
>
> Assisted-by: Claude:claude-opus-5-5 [Claude Code]
> Signed-off-by: Saravanan D <saravanand@crusoe.ai>
> ---
> This tests the kernel series in the parent thread, which is under
> review on linux-nvme.
Thanks for the patch. The patch content looks good to me. I applied the kernel
series [1] on top of the current Linus master branch, and confirmed this new
test case passes. Good.
I'll wait for the kernel series get settled. I expect the kernel series will be
revised a few more times, and this blktests patch will need to adjust to it,
probably.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-29 11:52 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20261023230426.6425-1-saravanand@crusoe.ai>
2026-10-23 23:08 ` [PATCH blktests] nvme/075: test the per-queue io_cpu sysfs attribute Saravanan D
2026-10-29 11:50 ` Shin'ichiro Kawasaki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox