From 941d9e7aa8f3f209809e9393875b39da677cc2de Mon Sep 17 00:00:00 2001 From: Maciej Szwed Date: Thu, 12 Dec 2019 10:51:42 +0100 Subject: [PATCH] nvmf: Add support for compare op command This patch introduces new spdk_nvmf_bdev_ctrlr_compare_cmd function which implements support for compare operation. Signed-off-by: Maciej Szwed Change-Id: Iadf402a6441a78ea0e6468f1066c6b0e10e63b9b Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/477782 Community-CI: Broadcom SPDK FC-NVMe CI Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris --- lib/nvmf/ctrlr.c | 4 +++ lib/nvmf/ctrlr_bdev.c | 44 +++++++++++++++++++++++++++ lib/nvmf/nvmf_internal.h | 2 ++ test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c | 6 ++++ test/unit/lib/nvmf/tcp.c/tcp_ut.c | 6 ++++ 5 files changed, 62 insertions(+) diff --git a/lib/nvmf/ctrlr.c b/lib/nvmf/ctrlr.c index 872fc9e02..269d6b72d 100644 --- a/lib/nvmf/ctrlr.c +++ b/lib/nvmf/ctrlr.c @@ -1392,6 +1392,8 @@ static const struct spdk_nvme_cmds_and_effect_log_page g_cmds_and_effect_log_pag [SPDK_NVME_OPC_WRITE_ZEROES] = {1, 1, 0, 0, 0, 0, 0, 0}, /* DATASET MANAGEMENT */ [SPDK_NVME_OPC_DATASET_MANAGEMENT] = {1, 1, 0, 0, 0, 0, 0, 0}, + /* COMPARE */ + [SPDK_NVME_OPC_COMPARE] = {1, 0, 0, 0, 0, 0, 0, 0}, }, }; @@ -2528,6 +2530,8 @@ spdk_nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req) return spdk_nvmf_bdev_ctrlr_read_cmd(bdev, desc, ch, req); case SPDK_NVME_OPC_WRITE: return spdk_nvmf_bdev_ctrlr_write_cmd(bdev, desc, ch, req); + case SPDK_NVME_OPC_COMPARE: + return spdk_nvmf_bdev_ctrlr_compare_cmd(bdev, desc, ch, req); case SPDK_NVME_OPC_WRITE_ZEROES: return spdk_nvmf_bdev_ctrlr_write_zeroes_cmd(bdev, desc, ch, req); case SPDK_NVME_OPC_FLUSH: diff --git a/lib/nvmf/ctrlr_bdev.c b/lib/nvmf/ctrlr_bdev.c index a703a0fb0..dc6b5d7fa 100644 --- a/lib/nvmf/ctrlr_bdev.c +++ b/lib/nvmf/ctrlr_bdev.c @@ -344,6 +344,50 @@ spdk_nvmf_bdev_ctrlr_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *de return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; } +int +spdk_nvmf_bdev_ctrlr_compare_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, + struct spdk_io_channel *ch, struct spdk_nvmf_request *req) +{ + uint64_t bdev_num_blocks = spdk_bdev_get_num_blocks(bdev); + uint32_t block_size = spdk_bdev_get_block_size(bdev); + struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; + struct spdk_nvme_cpl *rsp = &req->rsp->nvme_cpl; + uint64_t start_lba; + uint64_t num_blocks; + int rc; + + nvmf_bdev_ctrlr_get_rw_params(cmd, &start_lba, &num_blocks); + + if (spdk_unlikely(!nvmf_bdev_ctrlr_lba_in_range(bdev_num_blocks, start_lba, num_blocks))) { + SPDK_ERRLOG("end of media\n"); + rsp->status.sct = SPDK_NVME_SCT_GENERIC; + rsp->status.sc = SPDK_NVME_SC_LBA_OUT_OF_RANGE; + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + } + + if (spdk_unlikely(num_blocks * block_size > req->length)) { + SPDK_ERRLOG("Compare NLB %" PRIu64 " * block size %" PRIu32 " > SGL length %" PRIu32 "\n", + num_blocks, block_size, req->length); + rsp->status.sct = SPDK_NVME_SCT_GENERIC; + rsp->status.sc = SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID; + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + } + + rc = spdk_bdev_comparev_blocks(desc, ch, req->iov, req->iovcnt, start_lba, num_blocks, + nvmf_bdev_ctrlr_complete_cmd, req); + if (spdk_unlikely(rc)) { + if (rc == -ENOMEM) { + nvmf_bdev_ctrl_queue_io(req, bdev, ch, spdk_nvmf_ctrlr_process_io_cmd_resubmit, req); + return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; + } + rsp->status.sct = SPDK_NVME_SCT_GENERIC; + rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + } + + return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; +} + int spdk_nvmf_bdev_ctrlr_compare_and_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, struct spdk_nvmf_request *cmp_req, struct spdk_nvmf_request *write_req) diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index fb35e8e19..f35532e10 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -422,6 +422,8 @@ int spdk_nvmf_bdev_ctrlr_read_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc struct spdk_io_channel *ch, struct spdk_nvmf_request *req); int spdk_nvmf_bdev_ctrlr_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, struct spdk_nvmf_request *req); +int spdk_nvmf_bdev_ctrlr_compare_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, + struct spdk_io_channel *ch, struct spdk_nvmf_request *req); int spdk_nvmf_bdev_ctrlr_compare_and_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, struct spdk_nvmf_request *cmp_req, struct spdk_nvmf_request *write_req); int spdk_nvmf_bdev_ctrlr_write_zeroes_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, diff --git a/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c b/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c index 39e3405f2..600354a5d 100644 --- a/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c +++ b/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c @@ -136,6 +136,12 @@ DEFINE_STUB(spdk_nvmf_bdev_ctrlr_write_cmd, struct spdk_nvmf_request *req), 0); +DEFINE_STUB(spdk_nvmf_bdev_ctrlr_compare_cmd, + int, + (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, + struct spdk_nvmf_request *req), + 0); + DEFINE_STUB(spdk_nvmf_bdev_ctrlr_write_zeroes_cmd, int, (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, diff --git a/test/unit/lib/nvmf/tcp.c/tcp_ut.c b/test/unit/lib/nvmf/tcp.c/tcp_ut.c index b5046d1b3..b53b1166c 100644 --- a/test/unit/lib/nvmf/tcp.c/tcp_ut.c +++ b/test/unit/lib/nvmf/tcp.c/tcp_ut.c @@ -133,6 +133,12 @@ DEFINE_STUB(spdk_nvmf_bdev_ctrlr_write_cmd, struct spdk_nvmf_request *req), 0); +DEFINE_STUB(spdk_nvmf_bdev_ctrlr_compare_cmd, + int, + (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, + struct spdk_nvmf_request *req), + 0); + DEFINE_STUB(spdk_nvmf_bdev_ctrlr_write_zeroes_cmd, int, (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,