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 <curt.e.bruns@gmail.com>
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 <james.r.harris@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Curt Bruns 2021-05-04 20:52:57 -04:00 committed by Tomasz Zawadzki
parent f3edd7a359
commit b89ad84532
2 changed files with 70 additions and 5 deletions

View File

@ -144,7 +144,7 @@ cuse_nvme_passthru_cmd_execute(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, voi
static void static void
cuse_nvme_passthru_cmd_send(fuse_req_t req, struct nvme_passthru_cmd *passthru_cmd, 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_io_ctx *ctx;
struct cuse_device *cuse_device = fuse_req_userdata(req); 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) { if (rv) {
SPDK_ERRLOG("Cannot send io msg to the controller\n"); SPDK_ERRLOG("Cannot send io msg to the controller\n");
fuse_reply_err(req, -rv); 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); fuse_reply_ioctl_retry(req, in_iov, 2, NULL, 0);
return; 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 { } else {
cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL); cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL, cmd);
} }
return; return;
case SPDK_NVME_DATA_NONE: case SPDK_NVME_DATA_NONE:
@ -240,7 +246,7 @@ cuse_nvme_passthru_cmd(fuse_req_t req, int cmd, void *arg,
return; return;
} }
cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL); cuse_nvme_passthru_cmd_send(req, passthru_cmd, NULL, cmd);
return; return;
case SPDK_NVME_DATA_BIDIRECTIONAL: 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); cuse_nvme_submit_io(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz);
break; 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: case NVME_IOCTL_ID:
SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_ID\n"); SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_ID\n");
cuse_getid(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); cuse_getid(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz);

View File

@ -101,6 +101,14 @@ nvme_io_msg_send(struct spdk_nvme_ctrlr *ctrlr,
return 0; 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 static void
test_cuse_nvme_submit_io_read_write(void) test_cuse_nvme_submit_io_read_write(void)
{ {
@ -151,6 +159,51 @@ test_cuse_nvme_submit_io_read_write(void)
free(user_io); 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) int main(int argc, char **argv)
{ {
CU_pSuite suite = NULL; CU_pSuite suite = NULL;
@ -161,6 +214,7 @@ int main(int argc, char **argv)
suite = CU_add_suite("nvme_cuse", NULL, NULL); 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_io_read_write);
CU_ADD_TEST(suite, test_cuse_nvme_submit_passthru_cmd);
CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests(); CU_basic_run_tests();