Skip to content

Commit a94b770

Browse files
swarnagh6kawasaki
authored andcommitted
nvme/067: test io_uring pass through for NVMe admin queue
Simple test to exercise the nvme admin commands usage with io uring passthrough interfaces. The motivation for the test is to extend the kernel code coverage for NVMe admin commands via io_uring passthrough. Signed-off-by: Swarna Prabhu <[email protected]> [Shin'ichiro: fixed program name and space indent, declared local vars] Signed-off-by: Shin'ichiro Kawasaki <[email protected]>
1 parent 5885dee commit a94b770

4 files changed

Lines changed: 140 additions & 1 deletion

File tree

src/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ C_TARGETS := \
2323
zbdioctl
2424

2525
C_URING_TARGETS := miniublk \
26-
metadata
26+
metadata \
27+
nvme-passthru-admin-uring
2728

2829
HAVE_LIBURING := $(call HAVE_C_MACRO,liburing.h,IORING_OP_URING_CMD)
2930
HAVE_UBLK_HEADER := $(call HAVE_C_HEADER,linux/ublk_cmd.h,1)

src/nvme-passthru-admin-uring.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// SPDX-License-Identifier: GPL-3.0+
2+
// Copyright (C) 2026 Swarna Prabhu, Samsung Electronics
3+
/*
4+
* Simple test exercising the admin queue accesses via io_uring passthrough
5+
* commands.
6+
*/
7+
#include <errno.h>
8+
#include <fcntl.h>
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
#include <string.h>
12+
#include <liburing.h>
13+
#include <linux/nvme_ioctl.h>
14+
15+
#define NVME_IDENTIFY_ADMIN_CMD 0x06 /* Identify command using admin queue */
16+
#define NVME_IDENTIFY_CNS_CTRL 0x01 /* Identify controller command to a NVME device */
17+
struct nvme_id_ctrl {
18+
__le16 vid;
19+
__le16 ssvid;
20+
char sn[20];
21+
char mn[40];
22+
char fr[8];
23+
__u8 rab;
24+
__u8 ieee[3];
25+
char pad[4020];
26+
};
27+
28+
29+
int main(int argc, char **argv)
30+
{
31+
int fd, ret;
32+
struct nvme_passthru_cmd *cmd;
33+
struct nvme_id_ctrl *nctrl;
34+
struct io_uring nvring;
35+
int queue_depth = 80;
36+
struct io_uring_sqe *sqe = NULL;
37+
struct io_uring_cqe *cqe = NULL;
38+
39+
if (argc < 2) {
40+
fprintf(stderr, "usage: %s /dev/nvmeXnY\n", argv[0]);
41+
return -EINVAL;
42+
}
43+
44+
fd = open(argv[1], O_RDONLY);
45+
if (fd < 0) {
46+
perror("open");
47+
return -errno;
48+
}
49+
50+
nctrl = (struct nvme_id_ctrl *)calloc(1, sizeof(struct nvme_id_ctrl));
51+
if (!nctrl) {
52+
fprintf(stderr, "Memory allocation failure\n");
53+
ret = -ENOMEM;
54+
goto free_fd;
55+
}
56+
57+
ret = io_uring_queue_init(queue_depth, &nvring, IORING_SETUP_SQE128 | IORING_SETUP_CQE32);
58+
if (ret < 0) {
59+
fprintf(stderr, "Initialize io uring fail %d \n", ret);
60+
goto free_nctrl;
61+
}
62+
/* Prepare the SQE to use the IORING_OP_URING_CMD opcode */
63+
sqe = io_uring_get_sqe(&nvring);
64+
sqe->fd = fd;
65+
sqe->opcode = IORING_OP_URING_CMD;
66+
sqe->cmd_op = NVME_URING_CMD_ADMIN;
67+
68+
cmd = (struct nvme_passthru_cmd *)&sqe->cmd;
69+
memset(cmd, 0, sizeof(*cmd));
70+
71+
/* populate the cmd struct for the opcode */
72+
cmd->opcode = NVME_IDENTIFY_ADMIN_CMD;
73+
cmd->addr = (__u64)(uintptr_t)nctrl;
74+
cmd->data_len = sizeof(struct nvme_id_ctrl);
75+
cmd->cdw10 = NVME_IDENTIFY_CNS_CTRL;
76+
77+
/*submit the SQE */
78+
io_uring_submit(&nvring);
79+
80+
ret = io_uring_wait_cqe(&nvring, &cqe);
81+
82+
if (ret < 0) {
83+
fprintf(stderr, "wait_cqe: %s\n", strerror(-ret));
84+
} else if (cqe && cqe->res < 0) {
85+
fprintf(stderr, "Command failed (cqe->res): %d\n", cqe->res);
86+
ret = cqe->res;
87+
} else {
88+
ret = 0;
89+
}
90+
91+
if (cqe)
92+
io_uring_cqe_seen(&nvring, cqe);
93+
io_uring_queue_exit(&nvring);
94+
free_nctrl:
95+
free(nctrl);
96+
free_fd:
97+
close(fd);
98+
99+
return ret;
100+
}

tests/nvme/067

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-3.0+
3+
# Copyright (C) 2026 Swarna Prabhu, Samsung Electronics
4+
# Test out admin commands through the io uring passthrough interfaces.
5+
6+
. tests/nvme/rc
7+
8+
requires() {
9+
_nvme_requires
10+
_have_kernel_option IO_URING
11+
}
12+
13+
DESCRIPTION="exercise the nvme admin commands usage with io uring passthrough interfaces"
14+
QUICK=1
15+
16+
test_device() {
17+
echo "Running ${TEST_NAME}"
18+
19+
local devname ctrl_dev
20+
21+
# extract the ctrl dev from the test dev
22+
devname=${TEST_DEV#/dev/}
23+
ctrl_dev="/dev/${devname%n*}"
24+
25+
# enable io_uring when it is disabled
26+
_io_uring_enable
27+
28+
if ! sudo src/nvme-passthru-admin-uring "${ctrl_dev}"; then
29+
echo "src/nvme-passthru-admin-uring failed"
30+
fi
31+
32+
# reset io_uring setting before test exits
33+
_io_uring_restore
34+
35+
echo "Test Complete"
36+
}

tests/nvme/067.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Running nvme/067
2+
Test Complete

0 commit comments

Comments
 (0)