From b89ad845327a441031a248afed41fe4b12107630 Mon Sep 17 00:00:00 2001 From: Curt Bruns Date: Tue, 4 May 2021 20:52:57 -0400 Subject: [PATCH] nvme: add support for NVME_IOCTL_IO_CMD for cuse Nvme-cli uses NVME_IOCTL_IO_CMDs for "io-passthru" commands to cuse devices. This patch adds support for that IOCTL. Signed-off-by: Curt Bruns Change-Id: I20e0ac91ba08fce91bc5da1f4a1e454058cdd1e7 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7741 Community-CI: Broadcom CI Community-CI: Mellanox Build Bot Reviewed-by: Jim Harris Reviewed-by: Paul Luse Reviewed-by: Shuhei Matsumoto Tested-by: SPDK CI Jenkins --- lib/nvme/nvme_cuse.c | 21 ++++++-- test/unit/lib/nvme/nvme_cuse.c/nvme_cuse_ut.c | 54 +++++++++++++++++++ 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/lib/nvme/nvme_cuse.c b/lib/nvme/nvme_cuse.c index e421d92a23..faeaf8faa1 100644 --- a/lib/nvme/nvme_cuse.c +++ b/lib/nvme/nvme_cuse.c @@ -144,7 +144,7 @@ cuse_nvme_passthru_cmd_execute(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, voi static void cuse_nvme_passthru_cmd_send(fuse_req_t req, struct nvme_passthru_cmd *passthru_cmd, - const void *data) + const void *data, int cmd) { struct cuse_io_ctx *ctx; struct cuse_device *cuse_device = fuse_req_userdata(req); @@ -185,7 +185,13 @@ cuse_nvme_passthru_cmd_send(fuse_req_t req, struct nvme_passthru_cmd *passthru_c } } - rv = nvme_io_msg_send(cuse_device->ctrlr, 0, cuse_nvme_passthru_cmd_execute, ctx); + if ((unsigned int)cmd != NVME_IOCTL_ADMIN_CMD) { + /* Send NS for IO IOCTLs */ + rv = nvme_io_msg_send(cuse_device->ctrlr, passthru_cmd->nsid, cuse_nvme_passthru_cmd_execute, ctx); + } else { + /* NS == 0 for Admin IOCTLs */ + rv = nvme_io_msg_send(cuse_device->ctrlr, 0, cuse_nvme_passthru_cmd_execute, ctx); + } if (rv) { SPDK_ERRLOG("Cannot send io msg to the controller\n"); fuse_reply_err(req, -rv); @@ -220,9 +226,9 @@ cuse_nvme_passthru_cmd(fuse_req_t req, int cmd, void *arg, fuse_reply_ioctl_retry(req, in_iov, 2, NULL, 0); return; } - cuse_nvme_passthru_cmd_send(req, passthru_cmd, in_buf + sizeof(*passthru_cmd)); + cuse_nvme_passthru_cmd_send(req, passthru_cmd, in_buf + sizeof(*passthru_cmd), cmd); } else { - cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL); + cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL, cmd); } return; case SPDK_NVME_DATA_NONE: @@ -240,7 +246,7 @@ cuse_nvme_passthru_cmd(fuse_req_t req, int cmd, void *arg, return; } - cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL); + cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL, cmd); return; case SPDK_NVME_DATA_BIDIRECTIONAL: @@ -614,6 +620,11 @@ cuse_ns_ioctl(fuse_req_t req, int cmd, void *arg, cuse_nvme_submit_io(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); break; + case NVME_IOCTL_IO_CMD: + SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_IO_CMD\n"); + cuse_nvme_passthru_cmd(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); + break; + case NVME_IOCTL_ID: SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_ID\n"); cuse_getid(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); diff --git a/test/unit/lib/nvme/nvme_cuse.c/nvme_cuse_ut.c b/test/unit/lib/nvme/nvme_cuse.c/nvme_cuse_ut.c index a8a7f3b413..7a2cc96746 100644 --- a/test/unit/lib/nvme/nvme_cuse.c/nvme_cuse_ut.c +++ b/test/unit/lib/nvme/nvme_cuse.c/nvme_cuse_ut.c @@ -101,6 +101,14 @@ nvme_io_msg_send(struct spdk_nvme_ctrlr *ctrlr, return 0; } +struct cuse_device *g_cuse_device; +DEFINE_RETURN_MOCK(fuse_req_userdata, void *); +void * +fuse_req_userdata(fuse_req_t req) +{ + return g_cuse_device; +} + static void test_cuse_nvme_submit_io_read_write(void) { @@ -151,6 +159,51 @@ test_cuse_nvme_submit_io_read_write(void) free(user_io); } +static void +test_cuse_nvme_submit_passthru_cmd(void) +{ + struct nvme_passthru_cmd *passthru_cmd = NULL; + fuse_req_t req = (void *)0xDEEACDFF; + + passthru_cmd = calloc(1, sizeof(struct nvme_passthru_cmd)); + g_cuse_device = calloc(1, sizeof(struct cuse_device)); + + /* Use fatal or we'll segfault if we didn't get memory */ + SPDK_CU_ASSERT_FATAL(passthru_cmd != NULL); + SPDK_CU_ASSERT_FATAL(g_cuse_device != NULL); + g_cuse_device->ctrlr = (void *)0xDEADBEEF; + + g_ut_ctx = NULL; + /* Passthrough command */ + passthru_cmd->opcode = SPDK_NVME_DATA_CONTROLLER_TO_HOST; + passthru_cmd->nsid = 1; + passthru_cmd->data_len = 512; + passthru_cmd->cdw10 = 0xc0de1010; + passthru_cmd->cdw11 = 0xc0de1111; + passthru_cmd->cdw12 = 0xc0de1212; + passthru_cmd->cdw13 = 0xc0de1313; + passthru_cmd->cdw14 = 0xc0de1414; + passthru_cmd->cdw15 = 0xc0de1515; + + /* Send IO Command IOCTL */ + cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL, NVME_IOCTL_IO_CMD); + SPDK_CU_ASSERT_FATAL(g_ut_ctx != NULL); + CU_ASSERT(g_ut_ctx->data != NULL); + CU_ASSERT(g_ut_ctx->req == req); + CU_ASSERT(g_ut_ctx->data_len == 512); + CU_ASSERT(g_ut_ctx->nvme_cmd.opc == SPDK_NVME_DATA_CONTROLLER_TO_HOST); + CU_ASSERT(g_ut_ctx->nvme_cmd.nsid == 1); + CU_ASSERT(g_ut_ctx->nvme_cmd.cdw10 == 0xc0de1010); + CU_ASSERT(g_ut_ctx->nvme_cmd.cdw11 == 0xc0de1111); + CU_ASSERT(g_ut_ctx->nvme_cmd.cdw12 == 0xc0de1212); + CU_ASSERT(g_ut_ctx->nvme_cmd.cdw13 == 0xc0de1313); + CU_ASSERT(g_ut_ctx->nvme_cmd.cdw14 == 0xc0de1414); + CU_ASSERT(g_ut_ctx->nvme_cmd.cdw15 == 0xc0de1515); + + cuse_io_ctx_free(g_ut_ctx); + free(passthru_cmd); +} + int main(int argc, char **argv) { CU_pSuite suite = NULL; @@ -161,6 +214,7 @@ int main(int argc, char **argv) suite = CU_add_suite("nvme_cuse", NULL, NULL); CU_ADD_TEST(suite, test_cuse_nvme_submit_io_read_write); + CU_ADD_TEST(suite, test_cuse_nvme_submit_passthru_cmd); CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_run_tests();