diff --git a/lib/nvmf/ctrlr.c b/lib/nvmf/ctrlr.c index ee4fb4459..05d65d6cb 100644 --- a/lib/nvmf/ctrlr.c +++ b/lib/nvmf/ctrlr.c @@ -1729,7 +1729,22 @@ spdk_nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr) } void -spdk_nvmf_ctrlr_drain_aer_req(struct spdk_nvmf_ctrlr *ctrlr) +spdk_nvmf_qpair_free_aer(struct spdk_nvmf_qpair *qpair) +{ + struct spdk_nvmf_ctrlr *ctrlr = qpair->ctrlr; + + if (!spdk_nvmf_qpair_is_admin_queue(qpair)) { + return; + } + + if (ctrlr->aer_req != NULL) { + spdk_nvmf_request_free(ctrlr->aer_req); + ctrlr->aer_req = NULL; + } +} + +void +spdk_nvmf_ctrlr_abort_aer(struct spdk_nvmf_ctrlr *ctrlr) { if (!ctrlr->aer_req) { return; diff --git a/lib/nvmf/nvmf.c b/lib/nvmf/nvmf.c index ece31ddb7..8aa2d3a74 100644 --- a/lib/nvmf/nvmf.c +++ b/lib/nvmf/nvmf.c @@ -688,6 +688,7 @@ _spdk_nvmf_qpair_deactivate(void *ctx) if (!TAILQ_EMPTY(&qpair->outstanding)) { qpair->state_cb = _spdk_nvmf_qpair_destroy; qpair->state_cb_arg = qpair_ctx; + spdk_nvmf_qpair_free_aer(qpair); return; } diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index 7a25f2604..1618cec4e 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -293,7 +293,20 @@ struct spdk_nvmf_ctrlr *spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem uint16_t cntlid); int spdk_nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr); -void spdk_nvmf_ctrlr_drain_aer_req(struct spdk_nvmf_ctrlr *ctrlr); +/* + * Abort aer is sent on a per controller basis and sends a completion for the aer to the host. + * This function should be called when attempting to recover in error paths when it is OK for + * the host to send a subsequent AER. + */ +void spdk_nvmf_ctrlr_abort_aer(struct spdk_nvmf_ctrlr *ctrlr); + +/* + * Free aer simply frees the rdma resources for the aer without informing the host. + * This function should be called when deleting a qpair when one wants to make sure + * the qpair is completely empty before freeing the request. The reason we free the + * AER without sending a completion is to prevent the host from sending another AER. + */ +void spdk_nvmf_qpair_free_aer(struct spdk_nvmf_qpair *qpair); static inline struct spdk_nvmf_ns * _spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) diff --git a/lib/nvmf/rdma.c b/lib/nvmf/rdma.c index 4a534ed31..3a516985d 100644 --- a/lib/nvmf/rdma.c +++ b/lib/nvmf/rdma.c @@ -2027,7 +2027,7 @@ spdk_nvmf_rdma_qp_drained(struct spdk_nvmf_rdma_qpair *rqpair) SPDK_NOTICELOG("IBV QP#%u drained\n", rqpair->qpair.qid); if (spdk_nvmf_qpair_is_admin_queue(&rqpair->qpair)) { - spdk_nvmf_ctrlr_drain_aer_req(rqpair->qpair.ctrlr); + spdk_nvmf_ctrlr_abort_aer(rqpair->qpair.ctrlr); } spdk_nvmf_rdma_drain_pending_reqs(rqpair);