From 072f2d0011afdbdeb299736884b041a662546ccf Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Fri, 2 Jul 2021 16:03:59 +0900 Subject: [PATCH] bdev/nvme: Update ANA log page it self when ANA change event is notified When ANA change event is notified, increment reference count, read ANA log page, and parse it to update ANA states of namespaces. Then remove the spdk_nvme_ns_get_ana_state() call and its stub in unit tests. Signed-off-by: Shuhei Matsumoto Change-Id: I254ae6cb993694bf0d7f4fa4b1039b5f9243b5cb Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8335 Community-CI: Broadcom CI Community-CI: Mellanox Build Bot Reviewed-by: Ben Walker Reviewed-by: Aleksey Marchuk Tested-by: SPDK CI Jenkins --- module/bdev/nvme/bdev_nvme.c | 84 ++++++++++++++++++- .../lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c | 26 +++++- 2 files changed, 105 insertions(+), 5 deletions(-) diff --git a/module/bdev/nvme/bdev_nvme.c b/module/bdev/nvme/bdev_nvme.c index 101daa858..c6474f616 100644 --- a/module/bdev/nvme/bdev_nvme.c +++ b/module/bdev/nvme/bdev_nvme.c @@ -1282,7 +1282,7 @@ bdev_nvme_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) if (cdata->cmic.ana_reporting) { spdk_json_write_named_string(w, "ana_state", - _nvme_ana_state_str(spdk_nvme_ns_get_ana_state(ns))); + _nvme_ana_state_str(nvme_ns->ana_state)); } spdk_json_write_object_end(w); @@ -1820,6 +1820,85 @@ nvme_ctrlr_depopulate_namespaces(struct nvme_ctrlr *nvme_ctrlr) } } +static bool +nvme_ctrlr_acquire(struct nvme_ctrlr *nvme_ctrlr) +{ + pthread_mutex_lock(&nvme_ctrlr->mutex); + if (nvme_ctrlr->destruct || nvme_ctrlr->resetting) { + pthread_mutex_unlock(&nvme_ctrlr->mutex); + return false; + } + nvme_ctrlr->ref++; + pthread_mutex_unlock(&nvme_ctrlr->mutex); + return true; +} + +static int +nvme_ctrlr_set_ana_states(const struct spdk_nvme_ana_group_descriptor *desc, + void *cb_arg) +{ + struct nvme_ctrlr *nvme_ctrlr = cb_arg; + struct nvme_ns *nvme_ns; + uint32_t i, nsid; + + for (i = 0; i < desc->num_of_nsid; i++) { + nsid = desc->nsid[i]; + if (nsid == 0 || nsid > nvme_ctrlr->num_ns) { + continue; + } + + nvme_ns = nvme_ctrlr->namespaces[nsid - 1]; + assert(nvme_ns != NULL); + + if (!nvme_ns->populated) { + continue; + } + + nvme_ns->ana_group_id = desc->ana_group_id; + nvme_ns->ana_state = desc->ana_state; + } + + return 0; +} + +static void +nvme_ctrlr_read_ana_log_page_done(void *ctx, const struct spdk_nvme_cpl *cpl) +{ + struct nvme_ctrlr *nvme_ctrlr = ctx; + + if (spdk_nvme_cpl_is_success(cpl)) { + bdev_nvme_parse_ana_log_page(nvme_ctrlr, nvme_ctrlr_set_ana_states, + nvme_ctrlr); + } + + nvme_ctrlr_release(nvme_ctrlr); +} + +static void +nvme_ctrlr_read_ana_log_page(struct nvme_ctrlr *nvme_ctrlr) +{ + int rc; + + if (nvme_ctrlr->ana_log_page == NULL) { + return; + } + + if (!nvme_ctrlr_acquire(nvme_ctrlr)) { + return; + } + + rc = spdk_nvme_ctrlr_cmd_get_log_page(nvme_ctrlr->ctrlr, + SPDK_NVME_LOG_ASYMMETRIC_NAMESPACE_ACCESS, + SPDK_NVME_GLOBAL_NS_TAG, + nvme_ctrlr->ana_log_page, + nvme_ctrlr->ana_log_page_size, 0, + nvme_ctrlr_read_ana_log_page_done, + nvme_ctrlr); + if (rc != 0) { + nvme_ctrlr_release(nvme_ctrlr); + } +} + static void aer_cb(void *arg, const struct spdk_nvme_cpl *cpl) { @@ -1839,6 +1918,9 @@ aer_cb(void *arg, const struct spdk_nvme_cpl *cpl) (event.bits.log_page_identifier == SPDK_OCSSD_LOG_CHUNK_NOTIFICATION) && spdk_nvme_ctrlr_is_ocssd_supported(nvme_ctrlr->ctrlr)) { bdev_ocssd_handle_chunk_notification(nvme_ctrlr); + } else if ((event.bits.async_event_type == SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE) && + (event.bits.async_event_info == SPDK_NVME_ASYNC_EVENT_ANA_CHANGE)) { + nvme_ctrlr_read_ana_log_page(nvme_ctrlr); } } diff --git a/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c b/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c index 6110caf4c..ee97fa21d 100644 --- a/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c +++ b/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c @@ -129,9 +129,6 @@ DEFINE_STUB(spdk_nvme_ns_get_dealloc_logical_block_read_value, DEFINE_STUB(spdk_nvme_ns_get_optimal_io_boundary, uint32_t, (struct spdk_nvme_ns *ns), 0); -DEFINE_STUB(spdk_nvme_ns_get_ana_state, enum spdk_nvme_ana_state, - (const struct spdk_nvme_ns *ns), 0); - DEFINE_STUB(spdk_nvme_ns_get_csi, enum spdk_nvme_csi, (const struct spdk_nvme_ns *ns), 0); @@ -1757,7 +1754,7 @@ test_aer_cb(void) /* Attach a ctrlr, whose max number of namespaces is 4, and 2nd, 3rd, and 4th * namespaces are populated. */ - ctrlr = ut_attach_ctrlr(&trid, 4, false); + ctrlr = ut_attach_ctrlr(&trid, 4, true); SPDK_CU_ASSERT_FATAL(ctrlr != NULL); ctrlr->ns[0].is_active = false; @@ -1772,6 +1769,9 @@ test_aer_cb(void) spdk_delay_us(1000); poll_threads(); + spdk_delay_us(10000); + poll_threads(); + nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0"); SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL); @@ -1804,6 +1804,24 @@ test_aer_cb(void) CU_ASSERT(nvme_ctrlr->namespaces[3]->populated == true); CU_ASSERT(bdev->disk.blockcnt == 2048); + /* Change ANA state of active namespaces. */ + ctrlr->ns[0].ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE; + ctrlr->ns[1].ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE; + ctrlr->ns[3].ana_state = SPDK_NVME_ANA_CHANGE_STATE; + + event.bits.async_event_type = SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE; + event.bits.async_event_info = SPDK_NVME_ASYNC_EVENT_ANA_CHANGE; + cpl.cdw0 = event.raw; + + aer_cb(nvme_ctrlr, &cpl); + + spdk_delay_us(10000); + poll_threads(); + + CU_ASSERT(nvme_ctrlr->namespaces[0]->ana_state == SPDK_NVME_ANA_NON_OPTIMIZED_STATE); + CU_ASSERT(nvme_ctrlr->namespaces[1]->ana_state == SPDK_NVME_ANA_INACCESSIBLE_STATE); + CU_ASSERT(nvme_ctrlr->namespaces[3]->ana_state == SPDK_NVME_ANA_CHANGE_STATE); + rc = bdev_nvme_delete("nvme0", NULL); CU_ASSERT(rc == 0);