All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrea Parri <parri.andrea@gmail.com>
To: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>,
	linux-block@vger.kernel.org
Cc: Andrea Parri <parri.andrea@gmail.com>,
	Christoph Hellwig <hch@lst.de>, Keith Busch <kbusch@kernel.org>,
	Sagi Grimberg <sagi@grimberg.me>,
	Chaitanya Kulkarni <kch@nvidia.com>,
	Daniel Wagner <dwagner@suse.de>,
	linux-nvme@lists.infradead.org
Subject: [PATCH blktests v2 2/4] nvme/072: test that nvmet sends no data for a failed read
Date: Thu, 22 Oct 2026 15:09:22 +0200	[thread overview]
Message-ID: <20261022130927.3583166-3-parri.andrea@gmail.com> (raw)
In-Reply-To: <20261022130927.3583166-1-parri.andrea@gmail.com>

Issue a failing Identify into a buffer filled with a sentinel and verify
that the target transfers no data, with a successful Identify as a
control. The test runs on every configured transport; only nvmet-fc
failed it before the fix. Add a small helper because nvme-cli cannot
prefill the data buffer.

The test fails over fc on the unpatched kernel and passes with the fix
applied.

Assisted-by: LLM
Signed-off-by: Andrea Parri <parri.andrea@gmail.com>
---
 src/.gitignore           |  1 +
 src/Makefile             |  1 +
 src/nvme-sentinel-read.c | 89 ++++++++++++++++++++++++++++++++++++++++
 tests/nvme/072           | 72 ++++++++++++++++++++++++++++++++
 tests/nvme/072.out       |  2 +
 5 files changed, 165 insertions(+)
 create mode 100644 src/nvme-sentinel-read.c
 create mode 100755 tests/nvme/072
 create mode 100644 tests/nvme/072.out

diff --git a/src/.gitignore b/src/.gitignore
index f9a3916304c0f..57d14df3a2540 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -19,3 +19,4 @@
 /ioctl-lbmd-query
 /nvme-passthru-admin-uring
 /nvme-delay-ioctl
+/nvme-sentinel-read
diff --git a/src/Makefile b/src/Makefile
index 1e571c6b0b4eb..1133f34d7f07c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -24,6 +24,7 @@ C_TARGETS := \
 	mount_clear_sock \
 	nvme-delay-ioctl \
 	nvme-passthrough-meta \
+	nvme-sentinel-read \
 	ioctl-lbmd-query \
 	nbdsetsize \
 	openclose \
diff --git a/src/nvme-sentinel-read.c b/src/nvme-sentinel-read.c
new file mode 100644
index 0000000000000..dd36f283f46e2
--- /dev/null
+++ b/src/nvme-sentinel-read.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-3.0+
+// Copyright (C) 2026 Andrea Parri
+
+/*
+ * Issue an NVMe admin read command into a buffer filled with a sentinel and
+ * print the NVMe status and the number of bytes the command overwrote.
+ */
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/nvme_ioctl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#define SENTINEL	0xa5
+
+static int parse_u32(const char *s, uint32_t *val)
+{
+	unsigned long v;
+	char *end;
+
+	errno = 0;
+	v = strtoul(s, &end, 0);
+	if (errno || end == s || *end || v > UINT32_MAX)
+		return -1;
+	*val = v;
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	struct nvme_passthru_cmd cmd = { };
+	uint32_t opcode, cdw10, len, i, changed = 0;
+	unsigned char *buf;
+	void *p;
+	int fd, ret;
+
+	if (argc != 5 || parse_u32(argv[2], &opcode) || opcode > 0xff ||
+	    parse_u32(argv[3], &cdw10) || parse_u32(argv[4], &len) || !len) {
+		fprintf(stderr, "usage: %s /dev/nvmeX opcode cdw10 data-len\n",
+			argv[0]);
+		return 2;
+	}
+
+	/*
+	 * Page-align the buffer so that the kernel maps it for the transfer
+	 * instead of bouncing it: a bounce buffer is zero-filled and copied
+	 * back even when the command fails, which would hide the sentinel.
+	 */
+	ret = posix_memalign(&p, 4096, len);
+	if (ret) {
+		fprintf(stderr, "posix_memalign: %s\n", strerror(ret));
+		return 2;
+	}
+	buf = p;
+	memset(buf, SENTINEL, len);
+
+	fd = open(argv[1], O_RDONLY);
+	if (fd < 0) {
+		perror(argv[1]);
+		free(buf);
+		return 2;
+	}
+
+	cmd.opcode = opcode;
+	cmd.addr = (uintptr_t)buf;
+	cmd.data_len = len;
+	cmd.cdw10 = cdw10;
+
+	ret = ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd);
+	close(fd);
+	if (ret < 0) {
+		perror("NVME_IOCTL_ADMIN_CMD");
+		free(buf);
+		return 2;
+	}
+
+	for (i = 0; i < len; i++)
+		if (buf[i] != SENTINEL)
+			changed++;
+
+	printf("%#x %u\n", ret, changed);
+	free(buf);
+	return 0;
+}
diff --git a/tests/nvme/072 b/tests/nvme/072
new file mode 100755
index 0000000000000..a651fa0b0c672
--- /dev/null
+++ b/tests/nvme/072
@@ -0,0 +1,72 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-3.0+
+# Copyright (C) 2026 Andrea Parri
+#
+# Check that the NVMe target transfers no read data for a failed command.
+# The host buffer is filled with a sentinel, so any data the target sends
+# shows up as changed bytes.
+#
+# Regression test for patch "nvmet-fc: only send read data for successful
+# commands".
+
+. tests/nvme/rc
+
+DESCRIPTION="verify nvmet does not transfer data for failed reads"
+QUICK=1
+
+requires() {
+	_nvme_requires
+	_have_loop
+	_require_kernel_nvme_target
+	_have_src_program nvme-sentinel-read
+}
+
+set_conditions() {
+	_set_nvme_trtype "$@"
+}
+
+# Issue an Identify with CNS $2 to controller $1 and print the NVMe status
+# and the number of changed bytes in the 4096-byte data buffer.
+issue_identify() {
+	src/nvme-sentinel-read "$1" 0x06 "$2" 4096 2>>"$FULL"
+}
+
+test() {
+	echo "Running ${TEST_NAME}"
+
+	local changed ctrl status
+
+	_setup_nvmet
+	_nvmet_target_setup
+	_nvme_connect_subsys
+
+	ctrl=$(_find_nvme_dev "$def_subsysnqn")
+
+	# Identify Controller succeeds and must overwrite the sentinel.
+	if ! read -r status changed < <(issue_identify "/dev/$ctrl" 0x01); then
+		echo "successful Identify could not be issued"
+	else
+		echo "cns=0x01 status=$status changed=$changed" >>"$FULL"
+		if ((status != 0 || changed == 0)); then
+			echo "successful Identify returned status $status with $changed bytes"
+		fi
+	fi
+
+	# An unsupported CNS fails and must leave the sentinel intact.
+	if ! read -r status changed < <(issue_identify "/dev/$ctrl" 0xff); then
+		echo "failed Identify could not be issued"
+	else
+		echo "cns=0xff status=$status changed=$changed" >>"$FULL"
+		if (((status & 0x7ff) != 2)); then
+			echo "failed Identify returned status $status, expected 0x2"
+		fi
+		if ((changed != 0)); then
+			echo "failed Identify transferred data: $changed bytes changed"
+		fi
+	fi
+
+	_nvme_disconnect_subsys
+	_nvmet_target_cleanup
+
+	echo "Test complete"
+}
diff --git a/tests/nvme/072.out b/tests/nvme/072.out
new file mode 100644
index 0000000000000..3f765b30a22b0
--- /dev/null
+++ b/tests/nvme/072.out
@@ -0,0 +1,2 @@
+Running nvme/072
+Test complete
-- 
2.53.0


  parent reply	other threads:[~2026-10-22 13:09 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-22 13:09 [PATCH blktests v2 0/4] nvme: add nvmet zone report and FC regression tests Andrea Parri
2026-10-22 13:09 ` [PATCH blktests v2 1/4] nvme/rc: add zoned null_blk target helpers Andrea Parri
2026-10-22 13:09 ` Andrea Parri [this message]
2026-10-22 13:09 ` [PATCH blktests v2 3/4] nvme/073: test nvmet zone report initialization and length Andrea Parri
2026-10-22 13:09 ` [PATCH blktests v2 4/4] nvme/074: test that nvmet rejects a zone report NUMD that wraps Andrea Parri
2026-10-22 13:36 ` [PATCH blktests v2 0/4] nvme: add nvmet zone report and FC regression tests Andrea Parri
2026-10-28 14:59 ` Christoph Hellwig
2026-10-29  3:46 ` Shin'ichiro Kawasaki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261022130927.3583166-3-parri.andrea@gmail.com \
    --to=parri.andrea@gmail.com \
    --cc=dwagner@suse.de \
    --cc=hch@lst.de \
    --cc=kbusch@kernel.org \
    --cc=kch@nvidia.com \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-nvme@lists.infradead.org \
    --cc=sagi@grimberg.me \
    --cc=shinichiro.kawasaki@wdc.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.