From a0befabdd472b72f3d9311b199bd29a4a5bfbd15 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Mon, 14 Sep 2020 16:01:13 +0900 Subject: [PATCH] lib/nvme: Controller holds the latest ANA log page When creating a controller, allocate a buffer to the controller and read ANA log page into the buffer. When receiving ANA change notice, read ANA log page into the buffer to keep the contents up to date. The next patch will provide a public API to get the contents of ANA log page the controller holds. Signed-off-by: Shuhei Matsumoto Change-Id: If5c653f4e80d157e5120bb754e6660250b2b8fa1 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4233 Tested-by: SPDK CI Jenkins Reviewed-by: Aleksey Marchuk Reviewed-by: Changpeng Liu Reviewed-by: Ben Walker --- lib/nvme/nvme_ctrlr.c | 76 +++++++++++++++++++++++++++++++++++++++- lib/nvme/nvme_internal.h | 3 ++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index 5cdaa501c..5f6626dad 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -670,6 +670,61 @@ static int nvme_ctrlr_set_intel_support_log_pages(struct spdk_nvme_ctrlr *ctrlr) return 0; } +static int +nvme_ctrlr_update_ana_log_page(struct spdk_nvme_ctrlr *ctrlr) +{ + struct nvme_completion_poll_status *status; + int rc; + + status = calloc(1, sizeof(*status)); + if (status == NULL) { + SPDK_ERRLOG("Failed to allocaate status tracker\n"); + return -ENOMEM; + } + + rc = spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_ASYMMETRIC_NAMESPACE_ACCESS, + SPDK_NVME_GLOBAL_NS_TAG, ctrlr->ana_log_page, + ctrlr->ana_log_page_size, 0, + nvme_completion_poll_cb, status); + if (rc != 0) { + free(status); + return rc; + } + + if (nvme_wait_for_completion_robust_lock_timeout(ctrlr->adminq, status, &ctrlr->ctrlr_lock, + ctrlr->opts.admin_timeout_ms * 1000)) { + if (!status->timed_out) { + free(status); + } + return -EIO; + } + + free(status); + return 0; +} + +static int +nvme_ctrlr_init_ana_log_page(struct spdk_nvme_ctrlr *ctrlr) +{ + uint32_t ana_log_page_size; + + ana_log_page_size = sizeof(struct spdk_nvme_ana_page) + ctrlr->cdata.nanagrpid * + sizeof(struct spdk_nvme_ana_group_descriptor) + ctrlr->cdata.nn * + sizeof(uint32_t); + + ctrlr->ana_log_page = spdk_zmalloc(ana_log_page_size, 64, NULL, SPDK_ENV_SOCKET_ID_ANY, + SPDK_MALLOC_DMA); + if (ctrlr->ana_log_page == NULL) { + SPDK_ERRLOG("could not allocate ANA log page buffer\n"); + return -ENXIO; + } + ctrlr->ana_log_page_size = ana_log_page_size; + + ctrlr->log_page_supported[SPDK_NVME_LOG_ASYMMETRIC_NAMESPACE_ACCESS] = true; + + return nvme_ctrlr_update_ana_log_page(ctrlr); +} + static int nvme_ctrlr_set_supported_log_pages(struct spdk_nvme_ctrlr *ctrlr) { @@ -685,11 +740,15 @@ nvme_ctrlr_set_supported_log_pages(struct spdk_nvme_ctrlr *ctrlr) } if (ctrlr->cdata.vid == SPDK_PCI_VID_INTEL && !(ctrlr->quirks & NVME_INTEL_QUIRK_NO_LOG_PAGES)) { rc = nvme_ctrlr_set_intel_support_log_pages(ctrlr); + if (rc != 0) { + goto out; + } } if (ctrlr->cdata.cmic.ana_reporting) { - ctrlr->log_page_supported[SPDK_NVME_LOG_ASYMMETRIC_NAMESPACE_ACCESS] = true; + rc = nvme_ctrlr_init_ana_log_page(ctrlr); } +out: return rc; } @@ -2135,6 +2194,14 @@ nvme_ctrlr_async_event_cb(void *arg, const struct spdk_nvme_cpl *cpl) nvme_io_msg_ctrlr_update(ctrlr); } + if ((event.bits.async_event_type == SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE) && + (event.bits.async_event_info == SPDK_NVME_ASYNC_EVENT_ANA_CHANGE)) { + rc = nvme_ctrlr_update_ana_log_page(ctrlr); + if (rc) { + return; + } + } + active_proc = nvme_ctrlr_get_current_process(ctrlr); if (active_proc && active_proc->aer_cb_fn) { active_proc->aer_cb_fn(active_proc->aer_cb_arg, cpl); @@ -2822,6 +2889,9 @@ nvme_ctrlr_construct(struct spdk_nvme_ctrlr *ctrlr) STAILQ_INIT(&ctrlr->queued_aborts); ctrlr->outstanding_aborts = 0; + ctrlr->ana_log_page = NULL; + ctrlr->ana_log_page_size = 0; + rc = nvme_robust_mutex_init_recursive_shared(&ctrlr->ctrlr_lock); if (rc != 0) { return rc; @@ -2894,6 +2964,10 @@ nvme_ctrlr_destruct(struct spdk_nvme_ctrlr *ctrlr) spdk_bit_array_free(&ctrlr->free_io_qids); + spdk_free(ctrlr->ana_log_page); + ctrlr->ana_log_page = NULL; + ctrlr->ana_log_page_size = 0; + nvme_transport_ctrlr_destruct(ctrlr); } diff --git a/lib/nvme/nvme_internal.h b/lib/nvme/nvme_internal.h index 4f356159e..d705ee9ae 100644 --- a/lib/nvme/nvme_internal.h +++ b/lib/nvme/nvme_internal.h @@ -796,6 +796,9 @@ struct spdk_nvme_ctrlr { struct spdk_ring *external_io_msgs; STAILQ_HEAD(, nvme_io_msg_producer) io_producers; + + struct spdk_nvme_ana_page *ana_log_page; + uint32_t ana_log_page_size; }; struct spdk_nvme_probe_ctx {