From 7e21385f8acd52419e86d64cc618b2cb06e8d66e Mon Sep 17 00:00:00 2001 From: Jim Harris Date: Tue, 8 Jun 2021 19:25:37 +0000 Subject: [PATCH] nvme: add async+poll APIs for nvme_fabric_qpair_connect These functions will allow for sending the connect fabric command asynchronously. Additionally, this patch changes the return code for `nvme_fabric_qpair_connect()` when a timeout occurs from -EIO to -ECANCELED. It gives better description of the error as well as make it more consistent with `nvme_wait_for_completion*` APIs. Signed-off-by: Jim Harris Signed-off-by: Konrad Sztyber Change-Id: I95806626d3573ebe4b1568157fd57013c4b909a7 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8604 Community-CI: Broadcom CI Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Aleksey Marchuk --- lib/nvme/nvme_fabric.c | 70 ++++++++++++++----- lib/nvme/nvme_internal.h | 2 + .../lib/nvme/nvme_fabric.c/nvme_fabric_ut.c | 2 +- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/lib/nvme/nvme_fabric.c b/lib/nvme/nvme_fabric.c index 6f4896fc8..f232533b6 100644 --- a/lib/nvme/nvme_fabric.c +++ b/lib/nvme/nvme_fabric.c @@ -384,10 +384,9 @@ nvme_fabric_ctrlr_discover(struct spdk_nvme_ctrlr *ctrlr, } int -nvme_fabric_qpair_connect(struct spdk_nvme_qpair *qpair, uint32_t num_entries) +nvme_fabric_qpair_connect_async(struct spdk_nvme_qpair *qpair, uint32_t num_entries) { struct nvme_completion_poll_status *status; - struct spdk_nvmf_fabric_connect_rsp *rsp; struct spdk_nvmf_fabric_connect_cmd cmd; struct spdk_nvmf_fabric_connect_data *nvmf_data; struct spdk_nvme_ctrlr *ctrlr; @@ -454,26 +453,43 @@ nvme_fabric_qpair_connect(struct spdk_nvme_qpair *qpair, uint32_t num_entries) spdk_get_ticks_hz() / SPDK_SEC_TO_USEC; } - /* Wait until the command completes or times out */ - while (nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, NULL) == -EAGAIN) {} + qpair->poll_status = status; + return 0; +} + +int +nvme_fabric_qpair_connect_poll(struct spdk_nvme_qpair *qpair) +{ + struct nvme_completion_poll_status *status; + struct spdk_nvmf_fabric_connect_rsp *rsp; + struct spdk_nvme_ctrlr *ctrlr; + int rc = 0; + + ctrlr = qpair->ctrlr; + status = qpair->poll_status; + + if (nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, NULL) == -EAGAIN) { + return -EAGAIN; + } if (status->timed_out || spdk_nvme_cpl_is_error(&status->cpl)) { - SPDK_ERRLOG("Connect command failed, rc %d, trtype:%s adrfam:%s traddr:%s trsvcid:%s subnqn:%s\n", + SPDK_ERRLOG("Connect command failed, rc %d, trtype:%s adrfam:%s " + "traddr:%s trsvcid:%s subnqn:%s\n", status->timed_out ? -ECANCELED : -EIO, spdk_nvme_transport_id_trtype_str(ctrlr->trid.trtype), spdk_nvme_transport_id_adrfam_str(ctrlr->trid.adrfam), ctrlr->trid.traddr, ctrlr->trid.trsvcid, ctrlr->trid.subnqn); - if (spdk_nvme_cpl_is_error(&status->cpl)) { - SPDK_ERRLOG("Connect command completed with error: sct %d, sc %d\n", status->cpl.status.sct, - status->cpl.status.sc); + if (status->timed_out) { + rc = -ECANCELED; + } else { + SPDK_ERRLOG("Connect command completed with error: sct %d, sc %d\n", + status->cpl.status.sct, status->cpl.status.sc); + rc = -EIO; } - if (!status->timed_out) { - spdk_free(status->dma_data); - free(status); - } - return -EIO; + + goto finish; } if (nvme_qpair_is_admin_queue(qpair)) { @@ -481,8 +497,30 @@ nvme_fabric_qpair_connect(struct spdk_nvme_qpair *qpair, uint32_t num_entries) ctrlr->cntlid = rsp->status_code_specific.success.cntlid; SPDK_DEBUGLOG(nvme, "CNTLID 0x%04" PRIx16 "\n", ctrlr->cntlid); } +finish: + qpair->poll_status = NULL; + if (!status->timed_out) { + spdk_free(status->dma_data); + free(status); + } - spdk_free(status->dma_data); - free(status); - return 0; + return rc; +} + +int +nvme_fabric_qpair_connect(struct spdk_nvme_qpair *qpair, uint32_t num_entries) +{ + int rc; + + rc = nvme_fabric_qpair_connect_async(qpair, num_entries); + if (rc) { + return rc; + } + + do { + /* Wait until the command completes or times out */ + rc = nvme_fabric_qpair_connect_poll(qpair); + } while (rc == -EAGAIN); + + return rc; } diff --git a/lib/nvme/nvme_internal.h b/lib/nvme/nvme_internal.h index e7a84885a..59d69264e 100644 --- a/lib/nvme/nvme_internal.h +++ b/lib/nvme/nvme_internal.h @@ -1124,6 +1124,8 @@ int nvme_fabric_ctrlr_get_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, int nvme_fabric_ctrlr_discover(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_probe_ctx *probe_ctx); int nvme_fabric_qpair_connect(struct spdk_nvme_qpair *qpair, uint32_t num_entries); +int nvme_fabric_qpair_connect_async(struct spdk_nvme_qpair *qpair, uint32_t num_entries); +int nvme_fabric_qpair_connect_poll(struct spdk_nvme_qpair *qpair); typedef int (*spdk_nvme_parse_ana_log_page_cb)( const struct spdk_nvme_ana_group_descriptor *desc, void *cb_arg); diff --git a/test/unit/lib/nvme/nvme_fabric.c/nvme_fabric_ut.c b/test/unit/lib/nvme/nvme_fabric.c/nvme_fabric_ut.c index 67c8ecd85..f6907b3c4 100644 --- a/test/unit/lib/nvme/nvme_fabric.c/nvme_fabric_ut.c +++ b/test/unit/lib/nvme/nvme_fabric.c/nvme_fabric_ut.c @@ -432,7 +432,7 @@ test_nvme_fabric_qpair_connect(void) g_nvme_wait_for_completion_timeout = true; rc = nvme_fabric_qpair_connect(&qpair, 1); - CU_ASSERT(rc == -EIO); + CU_ASSERT(rc == -ECANCELED); g_nvme_wait_for_completion_timeout = false; abort_request(g_request);