diff --git a/lib/nvme/nvme_rdma.c b/lib/nvme/nvme_rdma.c index e6e2f210d..c2f27ae0d 100644 --- a/lib/nvme/nvme_rdma.c +++ b/lib/nvme/nvme_rdma.c @@ -50,6 +50,7 @@ #include "spdk/nvmf_spec.h" #include "spdk/string.h" #include "spdk/endian.h" +#include "spdk/likely.h" #include "nvme_internal.h" @@ -1531,6 +1532,45 @@ nvme_rdma_qpair_fail(struct spdk_nvme_qpair *qpair) return 0; } +static void +nvme_rdma_qpair_check_timeout(struct spdk_nvme_qpair *qpair) +{ + uint64_t t02; + struct spdk_nvme_rdma_req *rdma_req, *tmp; + struct nvme_rdma_qpair *rqpair = nvme_rdma_qpair(qpair); + struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr; + struct spdk_nvme_ctrlr_process *active_proc; + + /* Don't check timeouts during controller initialization. */ + if (ctrlr->state != NVME_CTRLR_STATE_READY) { + return; + } + + if (nvme_qpair_is_admin_queue(qpair)) { + active_proc = spdk_nvme_ctrlr_get_current_process(ctrlr); + } else { + active_proc = qpair->active_proc; + } + + /* Only check timeouts if the current process has a timeout callback. */ + if (active_proc == NULL || active_proc->timeout_cb_fn == NULL) { + return; + } + + t02 = spdk_get_ticks(); + TAILQ_FOREACH_SAFE(rdma_req, &rqpair->outstanding_reqs, link, tmp) { + assert(rdma_req->req != NULL); + + if (nvme_request_check_timeout(rdma_req->req, rdma_req->id, active_proc, t02)) { + /* + * The requests are in order, so as soon as one has not timed out, + * stop iterating. + */ + break; + } + } +} + #define MAX_COMPLETIONS_PER_POLL 128 int @@ -1599,6 +1639,10 @@ nvme_rdma_qpair_process_completions(struct spdk_nvme_qpair *qpair, } } while (reaped < max_completions); + if (spdk_unlikely(rqpair->qpair.ctrlr->timeout_enabled)) { + nvme_rdma_qpair_check_timeout(qpair); + } + return reaped; }