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 <shuhei.matsumoto.xt@hitachi.com>
Change-Id: If5c653f4e80d157e5120bb754e6660250b2b8fa1
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4233
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Shuhei Matsumoto 2020-09-14 16:01:13 +09:00 committed by Tomasz Zawadzki
parent 06d25b7021
commit a0befabdd4
2 changed files with 78 additions and 1 deletions

View File

@ -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);
}

View File

@ -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 {