From 7a12f4812d9a922e5c331b61d19708402fba33b2 Mon Sep 17 00:00:00 2001 From: Krishna Kanth Reddy Date: Fri, 30 Apr 2021 14:29:32 +0530 Subject: [PATCH] lib/nvme: Add support for Simple Copy Command Signed-off-by: Krishna Kanth Reddy Change-Id: I7aae5abca6ba5621e99fd604d146d84401eb45cd Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7694 Community-CI: Broadcom CI Community-CI: Mellanox Build Bot Reviewed-by: Aleksey Marchuk Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto Tested-by: SPDK CI Jenkins --- CHANGELOG.md | 4 ++++ include/spdk/nvme.h | 34 ++++++++++++++++++++++++++++++++++ lib/nvme/Makefile | 2 +- lib/nvme/nvme_ns_cmd.c | 34 ++++++++++++++++++++++++++++++++++ lib/nvme/spdk_nvme.map | 1 + 5 files changed, 74 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13aa1d56ab..57c6b8a852 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ of spdk_idxd_probe_cb function pointer. It should be implemented in idxd_user.c. Added `min_cntlid` and `max_cntlid` to `nvmf_create_subsystem` to limit the controller ID range. +### nvme + +Added a new function `spdk_nvme_ns_cmd_copy` to submit a Simple Copy Command to a Namespace. + ## v21.04: ### accel diff --git a/include/spdk/nvme.h b/include/spdk/nvme.h index f5a8f73c95..3723529861 100644 --- a/include/spdk/nvme.h +++ b/include/spdk/nvme.h @@ -3062,6 +3062,40 @@ int spdk_nvme_ns_cmd_dataset_management(struct spdk_nvme_ns *ns, struct spdk_nvm spdk_nvme_cmd_cb cb_fn, void *cb_arg); +/** + * Submit a simple copy command request to the specified NVMe namespace. + * + * The command is submitted to a qpair allocated by spdk_nvme_ctrlr_alloc_io_qpair(). + * The user must ensure that only one thread submits I/O on a given qpair at any + * given time. + * + * This is a convenience wrapper that will automatically allocate and construct + * the correct data buffers. Therefore, ranges does not need to be allocated from + * pinned memory and can be placed on the stack. If a higher performance, zero-copy + * version of SCC is required, simply build and submit a raw command using + * spdk_nvme_ctrlr_cmd_io_raw(). + * + * \param ns NVMe namespace to submit the SCC request + * \param qpair I/O queue pair to submit the request + * \param ranges An array of \ref spdk_nvme_scc_source_range elements describing the LBAs + * to operate on. + * \param num_ranges The number of elements in the ranges array. + * \param dest_lba Destination LBA to copy the data. + * \param cb_fn Callback function to invoke when the I/O is completed + * \param cb_arg Argument to pass to the callback function + * + * \return 0 if successfully submitted, negated errnos on the following error conditions: + * -ENOMEM: The request cannot be allocated. + * -EINVAL: Invalid ranges. + * -ENXIO: The qpair is failed at the transport level. + */ +int spdk_nvme_ns_cmd_copy(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + const struct spdk_nvme_scc_source_range *ranges, + uint16_t num_ranges, + uint64_t dest_lba, + spdk_nvme_cmd_cb cb_fn, + void *cb_arg); + /** * Submit a flush request to the specified NVMe namespace. * diff --git a/lib/nvme/Makefile b/lib/nvme/Makefile index 65a494b34a..f722ea56d7 100644 --- a/lib/nvme/Makefile +++ b/lib/nvme/Makefile @@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk SO_VER := 5 -SO_MINOR := 0 +SO_MINOR := 1 C_SRCS = nvme_ctrlr_cmd.c nvme_ctrlr.c nvme_fabric.c nvme_ns_cmd.c nvme_ns.c nvme_pcie_common.c nvme_pcie.c nvme_qpair.c nvme.c nvme_quirks.c nvme_transport.c \ nvme_ctrlr_ocssd_cmd.c nvme_ns_ocssd_cmd.c nvme_tcp.c nvme_opal.c nvme_io_msg.c nvme_poll_group.c nvme_zns.c diff --git a/lib/nvme/nvme_ns_cmd.c b/lib/nvme/nvme_ns_cmd.c index 1f03d761ab..7904f6d122 100644 --- a/lib/nvme/nvme_ns_cmd.c +++ b/lib/nvme/nvme_ns_cmd.c @@ -1091,6 +1091,40 @@ spdk_nvme_ns_cmd_dataset_management(struct spdk_nvme_ns *ns, struct spdk_nvme_qp return nvme_qpair_submit_request(qpair, req); } +int +spdk_nvme_ns_cmd_copy(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + const struct spdk_nvme_scc_source_range *ranges, + uint16_t num_ranges, uint64_t dest_lba, + spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + struct nvme_request *req; + struct spdk_nvme_cmd *cmd; + + if (num_ranges == 0) { + return -EINVAL; + } + + if (ranges == NULL) { + return -EINVAL; + } + + req = nvme_allocate_request_user_copy(qpair, (void *)ranges, + num_ranges * sizeof(struct spdk_nvme_scc_source_range), + cb_fn, cb_arg, true); + if (req == NULL) { + return -ENOMEM; + } + + cmd = &req->cmd; + cmd->opc = SPDK_NVME_OPC_COPY; + cmd->nsid = ns->id; + + *(uint64_t *)&cmd->cdw10 = dest_lba; + cmd->cdw12 = num_ranges - 1; + + return nvme_qpair_submit_request(qpair, req); +} + int spdk_nvme_ns_cmd_flush(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, spdk_nvme_cmd_cb cb_fn, void *cb_arg) diff --git a/lib/nvme/spdk_nvme.map b/lib/nvme/spdk_nvme.map index f9d95dba22..d54dd091bf 100644 --- a/lib/nvme/spdk_nvme.map +++ b/lib/nvme/spdk_nvme.map @@ -139,6 +139,7 @@ spdk_nvme_ns_cmd_readv_with_md; spdk_nvme_ns_cmd_read_with_md; spdk_nvme_ns_cmd_dataset_management; + spdk_nvme_ns_cmd_copy; spdk_nvme_ns_cmd_flush; spdk_nvme_ns_cmd_reservation_register; spdk_nvme_ns_cmd_reservation_release;