diff --git a/module/bdev/nvme/bdev_nvme.c b/module/bdev/nvme/bdev_nvme.c index 0ef671c06..7680ac0ce 100644 --- a/module/bdev/nvme/bdev_nvme.c +++ b/module/bdev/nvme/bdev_nvme.c @@ -84,6 +84,8 @@ struct nvme_bdev_io { /** Saved status for admin passthru completion event, PI error verification, or intermediate compare-and-write status */ struct spdk_nvme_cpl cpl; + /** Extended IO opts passed by the user to bdev layer and mapped to NVME format */ + struct spdk_nvme_ns_cmd_ext_io_opts ext_opts; /** Originating thread */ struct spdk_thread *orig_thread; @@ -3291,6 +3293,7 @@ bdev_nvme_readv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *md, uint64_t lba_count, uint64_t lba, uint32_t flags) { int rc; + struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(bio); SPDK_DEBUGLOG(bdev_nvme, "read %" PRIu64 " blocks with offset %#" PRIx64 "\n", lba_count, lba); @@ -3300,7 +3303,18 @@ bdev_nvme_readv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, bio->iovpos = 0; bio->iov_offset = 0; - if (iovcnt == 1) { + if (bdev_io->internal.ext_opts) { + bio->ext_opts.size = sizeof(struct spdk_nvme_ns_cmd_ext_io_opts); + bio->ext_opts.memory_domain = bdev_io->internal.ext_opts->memory_domain; + bio->ext_opts.memory_domain_ctx = bdev_io->internal.ext_opts->memory_domain_ctx; + bio->ext_opts.io_flags = flags; + bio->ext_opts.metadata = md; + + rc = spdk_nvme_ns_cmd_readv_ext(ns, qpair, lba, lba_count, + bdev_nvme_readv_done, bio, + bdev_nvme_queued_reset_sgl, bdev_nvme_queued_next_sge, + &bio->ext_opts); + } else if (iovcnt == 1) { rc = spdk_nvme_ns_cmd_read_with_md(ns, qpair, iov[0].iov_base, md, lba, lba_count, bdev_nvme_readv_done, bio, @@ -3326,6 +3340,7 @@ bdev_nvme_writev(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint32_t flags) { int rc; + struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(bio); SPDK_DEBUGLOG(bdev_nvme, "write %" PRIu64 " blocks with offset %#" PRIx64 "\n", lba_count, lba); @@ -3335,7 +3350,18 @@ bdev_nvme_writev(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, bio->iovpos = 0; bio->iov_offset = 0; - if (iovcnt == 1) { + if (bdev_io->internal.ext_opts) { + bio->ext_opts.size = sizeof(struct spdk_nvme_ns_cmd_ext_io_opts); + bio->ext_opts.memory_domain = bdev_io->internal.ext_opts->memory_domain; + bio->ext_opts.memory_domain_ctx = bdev_io->internal.ext_opts->memory_domain_ctx; + bio->ext_opts.io_flags = flags; + bio->ext_opts.metadata = md; + + rc = spdk_nvme_ns_cmd_writev_ext(ns, qpair, lba, lba_count, + bdev_nvme_readv_done, bio, + bdev_nvme_queued_reset_sgl, bdev_nvme_queued_next_sge, + &bio->ext_opts); + } else if (iovcnt == 1) { rc = spdk_nvme_ns_cmd_write_with_md(ns, qpair, iov[0].iov_base, md, lba, lba_count, bdev_nvme_writev_done, bio, diff --git a/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c b/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c index 01e6eee2e..54fabb6fe 100644 --- a/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c +++ b/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c @@ -909,6 +909,32 @@ spdk_nvme_ns_cmd_writev_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_WRITE, cb_fn, cb_arg); } +static bool g_ut_readv_ext_called; +int +spdk_nvme_ns_cmd_readv_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + uint64_t lba, uint32_t lba_count, + spdk_nvme_cmd_cb cb_fn, void *cb_arg, + spdk_nvme_req_reset_sgl_cb reset_sgl_fn, + spdk_nvme_req_next_sge_cb next_sge_fn, + struct spdk_nvme_ns_cmd_ext_io_opts *opts) +{ + g_ut_readv_ext_called = true; + return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_READ, cb_fn, cb_arg); +} + +static bool g_ut_writev_ext_called; +int +spdk_nvme_ns_cmd_writev_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + uint64_t lba, uint32_t lba_count, + spdk_nvme_cmd_cb cb_fn, void *cb_arg, + spdk_nvme_req_reset_sgl_cb reset_sgl_fn, + spdk_nvme_req_next_sge_cb next_sge_fn, + struct spdk_nvme_ns_cmd_ext_io_opts *opts) +{ + g_ut_writev_ext_called = true; + return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_WRITE, cb_fn, cb_arg); +} + int spdk_nvme_ns_cmd_comparev_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t lba, uint32_t lba_count, @@ -1990,6 +2016,7 @@ test_submit_nvme_cmd(void) struct nvme_bdev *bdev; struct spdk_bdev_io *bdev_io; struct spdk_io_channel *ch; + struct spdk_bdev_ext_io_opts ext_io_opts = {}; int rc; memset(attached_names, 0, sizeof(char *) * STRING_SIZE); @@ -2038,6 +2065,19 @@ test_submit_nvme_cmd(void) ut_test_submit_fused_nvme_cmd(ch, bdev_io); + /* Verify that ext NVME API is called if bdev_io ext_opts is set */ + bdev_io->internal.ext_opts = &ext_io_opts; + g_ut_readv_ext_called = false; + ut_test_submit_nvme_cmd(ch, bdev_io, SPDK_BDEV_IO_TYPE_READ); + CU_ASSERT(g_ut_readv_ext_called == true); + g_ut_readv_ext_called = false; + + g_ut_writev_ext_called = false; + ut_test_submit_nvme_cmd(ch, bdev_io, SPDK_BDEV_IO_TYPE_WRITE); + CU_ASSERT(g_ut_writev_ext_called == true); + g_ut_writev_ext_called = false; + bdev_io->internal.ext_opts = NULL; + ut_test_submit_admin_cmd(ch, bdev_io, ctrlr); free(bdev_io);