From 4fa486a1e30a2b38c6e0b129e65d2b18a07d0081 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Sat, 2 Mar 2019 21:43:22 -0500 Subject: [PATCH] nvmf: add asynchronous event for reservation notificaiton Now Host can get an asynchronous event notification when registrants were unregistered/preempted or reservation was released from the associate namespace, Host can send get log page to clear related log pages and reservation report to get the full overview of current reservation configuration. Change-Id: Idc57c19812490c7536503308989871515e9f2361 Signed-off-by: Changpeng Liu Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/439935 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris --- lib/nvmf/ctrlr.c | 46 +++++++++++++++++++ lib/nvmf/nvmf_internal.h | 2 + test/unit/lib/nvmf/subsystem.c/subsystem_ut.c | 5 ++ 3 files changed, 53 insertions(+) diff --git a/lib/nvmf/ctrlr.c b/lib/nvmf/ctrlr.c index 02458ffdf..abd9f8e0c 100644 --- a/lib/nvmf/ctrlr.c +++ b/lib/nvmf/ctrlr.c @@ -1235,6 +1235,13 @@ spdk_nvmf_ctrlr_async_event_request(struct spdk_nvmf_request *req) return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; } + if (ctrlr->reservation_event.bits.async_event_type == + SPDK_NVME_ASYNC_EVENT_TYPE_IO) { + rsp->cdw0 = ctrlr->reservation_event.raw; + ctrlr->reservation_event.raw = 0; + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + } + ctrlr->aer_req = req; return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; } @@ -2106,6 +2113,43 @@ spdk_nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr) return 0; } +void +spdk_nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr) +{ + struct spdk_nvmf_request *req; + struct spdk_nvme_cpl *rsp; + union spdk_nvme_async_event_completion event = {0}; + + if (!ctrlr->num_avail_log_pages) { + return; + } + event.bits.async_event_type = SPDK_NVME_ASYNC_EVENT_TYPE_IO; + event.bits.async_event_info = SPDK_NVME_ASYNC_EVENT_RESERVATION_LOG_AVAIL; + event.bits.log_page_identifier = SPDK_NVME_LOG_RESERVATION_NOTIFICATION; + + /* If there is no outstanding AER request, queue the event. Then + * if an AER is later submitted, this event can be sent as a + * response. + */ + if (!ctrlr->aer_req) { + if (ctrlr->reservation_event.bits.async_event_type == + SPDK_NVME_ASYNC_EVENT_TYPE_IO) { + return; + } + + ctrlr->reservation_event.raw = event.raw; + return; + } + + req = ctrlr->aer_req; + rsp = &req->rsp->nvme_cpl; + + rsp->cdw0 = event.raw; + + spdk_nvmf_request_complete(req); + ctrlr->aer_req = NULL; +} + void spdk_nvmf_qpair_free_aer(struct spdk_nvmf_qpair *qpair) { @@ -2152,6 +2196,8 @@ _nvmf_ctrlr_add_reservation_log(void *ctx) log->log.log_page_count = ctrlr->log_page_count; log->log.num_avail_log_pages = ctrlr->num_avail_log_pages++; TAILQ_INSERT_TAIL(&ctrlr->log_head, log, link); + + spdk_nvmf_ctrlr_async_event_reservation_notification(ctrlr); } void diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index 252e3dc82..219ddb813 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -273,6 +273,7 @@ struct spdk_nvmf_ctrlr { struct spdk_nvmf_request *aer_req; union spdk_nvme_async_event_completion notice_event; + union spdk_nvme_async_event_completion reservation_event; struct spdk_uuid hostid; uint16_t changed_ns_list_count; @@ -371,6 +372,7 @@ void spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid); int spdk_nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr); +void spdk_nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr); void spdk_nvmf_ns_reservation_request(void *ctx); void spdk_nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr, struct spdk_nvmf_ns *ns, diff --git a/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c b/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c index 4e608a352..8ca3ddc65 100644 --- a/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c +++ b/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c @@ -463,6 +463,11 @@ static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C; static struct spdk_nvmf_ns g_ns; struct spdk_nvmf_subsystem_pg_ns_info g_ns_info; +void +spdk_nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr) +{ +} + static void ut_reservation_init(void) {