From 8b158aaacdece3492a78dc0399efda10fbb7fe2b Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Tue, 5 Jun 2018 16:26:49 -0700 Subject: [PATCH] nvme: factor out request timeout checking This will be used in other transports as well. Change-Id: I05026b0dfea2647d61a173379aca368ca48a2f52 Signed-off-by: Daniel Verkamp Reviewed-on: https://review.gerrithub.io/413864 Tested-by: SPDK Automated Test System Reviewed-by: Changpeng Liu Reviewed-by: Jim Harris --- lib/nvme/nvme.c | 53 +++++++++++++++++++ lib/nvme/nvme_internal.h | 2 + lib/nvme/nvme_pcie.c | 29 ++-------- test/unit/lib/nvme/nvme_pcie.c/nvme_pcie_ut.c | 8 +++ 4 files changed, 66 insertions(+), 26 deletions(-) diff --git a/lib/nvme/nvme.c b/lib/nvme/nvme.c index 7a0e193cd..a41aacf3b 100644 --- a/lib/nvme/nvme.c +++ b/lib/nvme/nvme.c @@ -206,6 +206,59 @@ nvme_allocate_request_user_copy(struct spdk_nvme_qpair *qpair, return req; } +/** + * Check if a request has exceeded the controller timeout. + * + * \param req request to check for timeout. + * \param cid command ID for command submitted by req (will be passed to timeout_cb_fn) + * \param active_proc per-process data for the controller associated with req + * \param now_tick current time from spdk_get_ticks() + * \return 0 if requests submitted more recently than req should still be checked for timeouts, or + * 1 if requests newer than req need not be checked. + * + * The request's timeout callback will be called if needed; the caller is only responsible for + * calling this function on each outstanding request. + */ +int +nvme_request_check_timeout(struct nvme_request *req, uint16_t cid, + struct spdk_nvme_ctrlr_process *active_proc, + uint64_t now_tick) +{ + struct spdk_nvme_qpair *qpair = req->qpair; + struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr; + + assert(active_proc->timeout_cb_fn != NULL); + + if (req->timed_out || req->submit_tick == 0) { + return 0; + } + + if (req->pid != g_spdk_nvme_pid) { + return 0; + } + + if (nvme_qpair_is_admin_queue(qpair) && + req->cmd.opc == SPDK_NVME_OPC_ASYNC_EVENT_REQUEST) { + return 0; + } + + if (req->submit_tick + active_proc->timeout_ticks > now_tick) { + return 1; + } + + req->timed_out = true; + + /* + * We don't want to expose the admin queue to the user, + * so when we're timing out admin commands set the + * qpair to NULL. + */ + active_proc->timeout_cb_fn(active_proc->timeout_cb_arg, ctrlr, + nvme_qpair_is_admin_queue(qpair) ? NULL : qpair, + cid); + return 0; +} + int nvme_robust_mutex_init_shared(pthread_mutex_t *mtx) { diff --git a/lib/nvme/nvme_internal.h b/lib/nvme/nvme_internal.h index 3ccf118b5..81e4bfce1 100644 --- a/lib/nvme/nvme_internal.h +++ b/lib/nvme/nvme_internal.h @@ -735,6 +735,8 @@ nvme_free_request(struct nvme_request *req) } void nvme_request_remove_child(struct nvme_request *parent, struct nvme_request *child); +int nvme_request_check_timeout(struct nvme_request *req, uint16_t cid, + struct spdk_nvme_ctrlr_process *active_proc, uint64_t now_tick); uint64_t nvme_get_quirks(const struct spdk_pci_id *id); int nvme_robust_mutex_init_shared(pthread_mutex_t *mtx); diff --git a/lib/nvme/nvme_pcie.c b/lib/nvme/nvme_pcie.c index 89ef13182..327242db1 100644 --- a/lib/nvme/nvme_pcie.c +++ b/lib/nvme/nvme_pcie.c @@ -2003,36 +2003,13 @@ nvme_pcie_qpair_check_timeout(struct spdk_nvme_qpair *qpair) TAILQ_FOREACH_SAFE(tr, &pqpair->outstanding_tr, tq_list, tmp) { assert(tr->req != NULL); - if (tr->req->timed_out || tr->req->submit_tick == 0) { - continue; - } - - if (nvme_qpair_is_admin_queue(qpair)) { - if (tr->req->pid != getpid()) { - continue; - } - - if (tr->req->cmd.opc == SPDK_NVME_OPC_ASYNC_EVENT_REQUEST) { - continue; - } - } - - if (tr->req->submit_tick + active_proc->timeout_ticks > t02) { - /* The trackers are in order, so as soon as one has not timed out, + if (nvme_request_check_timeout(tr->req, tr->cid, active_proc, t02)) { + /* + * The requests are in order, so as soon as one has not timed out, * stop iterating. */ break; } - - tr->req->timed_out = true; - - /* We don't want to expose the admin queue to the user, - * so when we're timing out admin commands set the - * qpair to NULL. - */ - active_proc->timeout_cb_fn(active_proc->timeout_cb_arg, ctrlr, - nvme_qpair_is_admin_queue(qpair) ? NULL : qpair, - tr->cid); } } diff --git a/test/unit/lib/nvme/nvme_pcie.c/nvme_pcie_ut.c b/test/unit/lib/nvme/nvme_pcie.c/nvme_pcie_ut.c index 34a3e7be8..41919ffa3 100644 --- a/test/unit/lib/nvme/nvme_pcie.c/nvme_pcie_ut.c +++ b/test/unit/lib/nvme/nvme_pcie.c/nvme_pcie_ut.c @@ -288,6 +288,14 @@ nvme_qpair_enable(struct spdk_nvme_qpair *qpair) abort(); } +int +nvme_request_check_timeout(struct nvme_request *req, uint16_t cid, + struct spdk_nvme_ctrlr_process *active_proc, + uint64_t now_tick) +{ + abort(); +} + struct spdk_nvme_ctrlr * spdk_nvme_get_ctrlr_by_trid_unsafe(const struct spdk_nvme_transport_id *trid) {