diff --git a/lib/nvmf/ctrlr.c b/lib/nvmf/ctrlr.c index 150cdac9a..a0182c37d 100644 --- a/lib/nvmf/ctrlr.c +++ b/lib/nvmf/ctrlr.c @@ -1990,7 +1990,7 @@ nvmf_get_ana_log_page(struct spdk_nvmf_ctrlr *ctrlr, struct iovec *iovs, int iov ana_desc.ana_group_id = anagrpid; ana_desc.num_of_nsid = ctrlr->subsys->ana_group[anagrpid - 1]; - ana_desc.ana_state = ctrlr->listener->ana_state; + ana_desc.ana_state = ctrlr->listener->ana_state[anagrpid - 1]; copy_len = spdk_min(sizeof(ana_desc) - offset, length); copied_len = _copy_buf_to_iovs(©_ctx, (const char *)&ana_desc + offset, @@ -2287,6 +2287,7 @@ spdk_nvmf_ctrlr_identify_ns(struct spdk_nvmf_ctrlr *ctrlr, struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys; struct spdk_nvmf_ns *ns; uint32_t max_num_blocks; + enum spdk_nvme_ana_state ana_state; if (cmd->nsid == 0 || cmd->nsid > subsystem->max_nsid) { SPDK_ERRLOG("Identify Namespace for invalid NSID %u\n", cmd->nsid); @@ -2318,10 +2319,12 @@ spdk_nvmf_ctrlr_identify_ns(struct spdk_nvmf_ctrlr *ctrlr, } if (subsystem->flags.ana_reporting) { + assert(ns->anagrpid - 1 < subsystem->max_nsid); nsdata->anagrpid = ns->anagrpid; - if (ctrlr->listener->ana_state == SPDK_NVME_ANA_INACCESSIBLE_STATE || - ctrlr->listener->ana_state == SPDK_NVME_ANA_PERSISTENT_LOSS_STATE) { + ana_state = ctrlr->listener->ana_state[ns->anagrpid - 1]; + if (ana_state == SPDK_NVME_ANA_INACCESSIBLE_STATE || + ana_state == SPDK_NVME_ANA_PERSISTENT_LOSS_STATE) { nsdata->nuse = 0; } } @@ -2769,6 +2772,28 @@ _nvme_ana_state_to_path_status(enum spdk_nvme_ana_state ana_state) } } +/* we have to use the typedef in the function declaration to appease astyle. */ +typedef enum spdk_nvme_ana_state spdk_nvme_ana_state_t; + +static spdk_nvme_ana_state_t +nvmf_ctrlr_get_ana_state(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid) +{ + struct spdk_nvmf_ns *ns; + + /* We do not have NVM subsystem specific ANA state. Hence if NSID is either + * SPDK_NVMF_GLOBAL_NS_TAG, invalid, or for inactive namespace, return + * the optimized state. + */ + ns = _nvmf_subsystem_get_ns(ctrlr->subsys, nsid); + if (ns == NULL) { + return SPDK_NVME_ANA_OPTIMIZED_STATE; + } + + assert(ns->anagrpid - 1 < ctrlr->subsys->max_nsid); + + return ctrlr->listener->ana_state[ns->anagrpid]; +} + static int nvmf_ctrlr_get_features(struct spdk_nvmf_request *req) { @@ -2798,7 +2823,7 @@ nvmf_ctrlr_get_features(struct spdk_nvmf_request *req) /* * Process Get Features command for non-discovery controller */ - ana_state = ctrlr->listener->ana_state; + ana_state = nvmf_ctrlr_get_ana_state(ctrlr, cmd->nsid); switch (ana_state) { case SPDK_NVME_ANA_INACCESSIBLE_STATE: case SPDK_NVME_ANA_PERSISTENT_LOSS_STATE: @@ -2894,7 +2919,7 @@ nvmf_ctrlr_set_features(struct spdk_nvmf_request *req) /* * Process Set Features command for non-discovery controller */ - ana_state = ctrlr->listener->ana_state; + ana_state = nvmf_ctrlr_get_ana_state(ctrlr, cmd->nsid); switch (ana_state) { case SPDK_NVME_ANA_INACCESSIBLE_STATE: case SPDK_NVME_ANA_CHANGE_STATE: @@ -3690,10 +3715,17 @@ nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req) return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; } - /* It will be lower overhead to check if ANA state is optimized or - * non-optimized. - */ - ana_state = ctrlr->listener->ana_state; + ns = _nvmf_subsystem_get_ns(ctrlr->subsys, nsid); + if (ns == NULL || ns->bdev == NULL) { + SPDK_DEBUGLOG(nvmf, "Unsuccessful query for nsid %u\n", cmd->nsid); + response->status.sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT; + response->status.dnr = 1; + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + } + + assert(ns->anagrpid - 1 < ctrlr->subsys->max_nsid); + + ana_state = ctrlr->listener->ana_state[ns->anagrpid - 1]; if (spdk_unlikely(ana_state != SPDK_NVME_ANA_OPTIMIZED_STATE && ana_state != SPDK_NVME_ANA_NON_OPTIMIZED_STATE)) { SPDK_DEBUGLOG(nvmf, "Fail I/O command due to ANA state %d\n", @@ -3703,14 +3735,6 @@ nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req) return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; } - ns = _nvmf_subsystem_get_ns(ctrlr->subsys, nsid); - if (ns == NULL || ns->bdev == NULL) { - SPDK_DEBUGLOG(nvmf, "Unsuccessful query for nsid %u\n", cmd->nsid); - response->status.sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT; - response->status.dnr = 1; - return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; - } - /* scan-build falsely reporting dereference of null pointer */ assert(group != NULL && group->sgroups != NULL); ns_info = &group->sgroups[ctrlr->subsys->id].ns_info[nsid - 1]; diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index a55c41dd2..b34e2e089 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -103,7 +103,7 @@ struct spdk_nvmf_subsystem_listener { void *cb_arg; struct spdk_nvme_transport_id *trid; struct spdk_nvmf_transport *transport; - enum spdk_nvme_ana_state ana_state; + enum spdk_nvme_ana_state *ana_state; uint64_t ana_state_change_count; TAILQ_ENTRY(spdk_nvmf_subsystem_listener) link; }; diff --git a/lib/nvmf/nvmf_rpc.c b/lib/nvmf/nvmf_rpc.c index d5ed637a5..e0636f6db 100644 --- a/lib/nvmf/nvmf_rpc.c +++ b/lib/nvmf/nvmf_rpc.c @@ -2207,6 +2207,7 @@ dump_nvmf_subsystem_listener(struct spdk_json_write_ctx *w, { const struct spdk_nvme_transport_id *trid = listener->trid; const char *adrfam; + uint32_t i; spdk_json_write_object_begin(w); @@ -2222,8 +2223,15 @@ dump_nvmf_subsystem_listener(struct spdk_json_write_ctx *w, spdk_json_write_object_end(w); if (nvmf_subsystem_get_ana_reporting(listener->subsystem)) { - spdk_json_write_named_string(w, "ana_state", - nvme_ana_state_str(listener->ana_state)); + spdk_json_write_named_array_begin(w, "ana_states"); + for (i = 0; i < listener->subsystem->max_nsid; i++) { + spdk_json_write_object_begin(w); + spdk_json_write_named_uint32(w, "ana_group", i + 1); + spdk_json_write_named_string(w, "ana_state", + nvme_ana_state_str(listener->ana_state[i])); + spdk_json_write_object_end(w); + } + spdk_json_write_array_end(w); } spdk_json_write_object_end(w); diff --git a/lib/nvmf/subsystem.c b/lib/nvmf/subsystem.c index b5cce966d..ab07664b3 100644 --- a/lib/nvmf/subsystem.c +++ b/lib/nvmf/subsystem.c @@ -348,6 +348,7 @@ _nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem, } TAILQ_REMOVE(&subsystem->listeners, listener, link); + free(listener->ana_state); free(listener); } @@ -991,6 +992,7 @@ spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_transport *transport; struct spdk_nvmf_subsystem_listener *listener; struct spdk_nvmf_listener *tr_listener; + uint32_t i; int rc = 0; assert(cb_fn != NULL); @@ -1033,7 +1035,16 @@ spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, listener->cb_fn = cb_fn; listener->cb_arg = cb_arg; listener->subsystem = subsystem; - listener->ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; + listener->ana_state = calloc(subsystem->max_nsid, sizeof(enum spdk_nvme_ana_state)); + if (!listener->ana_state) { + free(listener); + cb_fn(cb_arg, -ENOMEM); + return; + } + + for (i = 0; i < subsystem->max_nsid; i++) { + listener->ana_state[i] = SPDK_NVME_ANA_OPTIMIZED_STATE; + } if (transport->ops->listen_associate != NULL) { rc = transport->ops->listen_associate(transport, subsystem, trid); @@ -1570,7 +1581,6 @@ spdk_nvmf_subsystem_add_ns_ext(struct spdk_nvmf_subsystem *subsystem, const char ns->anagrpid = opts.anagrpid; subsystem->ana_group[ns->anagrpid - 1]++; TAILQ_INIT(&ns->registrants); - if (ptpl_file) { rc = nvmf_ns_load_reservation(ptpl_file, &info); if (!rc) { @@ -3019,6 +3029,7 @@ nvmf_subsystem_set_ana_state(struct spdk_nvmf_subsystem *subsystem, { struct spdk_nvmf_subsystem_listener *listener; struct subsystem_listener_update_ctx *ctx; + uint32_t i; assert(cb_fn != NULL); assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE || @@ -3048,11 +3059,6 @@ nvmf_subsystem_set_ana_state(struct spdk_nvmf_subsystem *subsystem, return; } - if (listener->ana_state == ana_state) { - cb_fn(cb_arg, 0); - return; - } - ctx = calloc(1, sizeof(*ctx)); if (!ctx) { SPDK_ERRLOG("Unable to allocate context\n"); @@ -3060,7 +3066,9 @@ nvmf_subsystem_set_ana_state(struct spdk_nvmf_subsystem *subsystem, return; } - listener->ana_state = ana_state; + for (i = 0; i < subsystem->max_nsid; i++) { + listener->ana_state[i] = ana_state; + } listener->ana_state_change_count++; ctx->listener = listener; diff --git a/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c b/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c index ec38b68cd..c505bb2f0 100644 --- a/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c +++ b/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c @@ -1052,14 +1052,15 @@ test_set_get_features(void) { struct spdk_nvmf_subsystem subsystem = {}; struct spdk_nvmf_qpair admin_qpair = {}; - struct spdk_nvmf_subsystem_listener listener = {}; + enum spdk_nvme_ana_state ana_state[3]; + struct spdk_nvmf_subsystem_listener listener = { .ana_state = ana_state }; struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsystem, .admin_qpair = &admin_qpair, .listener = &listener }; union nvmf_h2c_msg cmd = {}; union nvmf_c2h_msg rsp = {}; struct spdk_nvmf_ns ns[3]; - struct spdk_nvmf_ns *ns_arr[3] = {&ns[0], NULL, &ns[2]};; + struct spdk_nvmf_ns *ns_arr[3] = {&ns[0], NULL, &ns[2]}; struct spdk_nvmf_request req; int rc; @@ -1067,7 +1068,8 @@ test_set_get_features(void) ns[2].anagrpid = 3; subsystem.ns = ns_arr; subsystem.max_nsid = SPDK_COUNTOF(ns_arr); - listener.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; + listener.ana_state[0] = SPDK_NVME_ANA_OPTIMIZED_STATE; + listener.ana_state[2] = SPDK_NVME_ANA_OPTIMIZED_STATE; admin_qpair.ctrlr = &ctrlr; req.qpair = &admin_qpair; cmd.nvme_cmd.nsid = 1; @@ -1666,7 +1668,8 @@ test_fused_compare_and_write(void) struct spdk_nvmf_subsystem subsystem = {}; struct spdk_nvmf_ns ns = {}; struct spdk_nvmf_ns *subsys_ns[1] = {}; - struct spdk_nvmf_subsystem_listener listener = {}; + enum spdk_nvme_ana_state ana_state[1]; + struct spdk_nvmf_subsystem_listener listener = { .ana_state = ana_state }; struct spdk_bdev bdev = {}; struct spdk_nvmf_poll_group group = {}; @@ -1682,7 +1685,7 @@ test_fused_compare_and_write(void) subsys_ns[0] = &ns; subsystem.ns = (struct spdk_nvmf_ns **)&subsys_ns; - listener.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; + listener.ana_state[0] = SPDK_NVME_ANA_OPTIMIZED_STATE; /* Enable controller */ ctrlr.vcprop.cc.bits.en = 1; @@ -1838,7 +1841,8 @@ test_get_ana_log_page_one_ns_per_anagrp(void) uint32_t ana_group[3]; struct spdk_nvmf_subsystem subsystem = { .ana_group = ana_group }; struct spdk_nvmf_ctrlr ctrlr = {}; - struct spdk_nvmf_subsystem_listener listener = {}; + enum spdk_nvme_ana_state ana_state[3]; + struct spdk_nvmf_subsystem_listener listener = { .ana_state = ana_state }; struct spdk_nvmf_ns ns[3]; struct spdk_nvmf_ns *ns_arr[3] = {&ns[0], &ns[1], &ns[2]}; uint64_t offset; @@ -1858,7 +1862,10 @@ test_get_ana_log_page_one_ns_per_anagrp(void) } ctrlr.subsys = &subsystem; ctrlr.listener = &listener; - listener.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; + + for (i = 0; i < 3; i++) { + listener.ana_state[i] = SPDK_NVME_ANA_OPTIMIZED_STATE; + } for (i = 0; i < 3; i++) { ns_arr[i]->nsid = i + 1; @@ -1879,7 +1886,7 @@ test_get_ana_log_page_one_ns_per_anagrp(void) ana_desc->ana_group_id = ns_arr[i]->nsid; ana_desc->num_of_nsid = 1; ana_desc->change_count = 0; - ana_desc->ana_state = ctrlr.listener->ana_state; + ana_desc->ana_state = ctrlr.listener->ana_state[i]; ana_desc->nsid[0] = ns_arr[i]->nsid; memcpy(&expected_page[offset], ana_desc, UT_ANA_DESC_SIZE); offset += UT_ANA_DESC_SIZE; @@ -1923,7 +1930,8 @@ test_get_ana_log_page_multi_ns_per_anagrp(void) struct spdk_nvmf_ns *ns_arr[5] = {&ns[0], &ns[1], &ns[2], &ns[3], &ns[4]}; uint32_t ana_group[5] = {0}; struct spdk_nvmf_subsystem subsystem = { .ns = ns_arr, .ana_group = ana_group, }; - struct spdk_nvmf_subsystem_listener listener = {}; + enum spdk_nvme_ana_state ana_state[5]; + struct spdk_nvmf_subsystem_listener listener = { .ana_state = ana_state, }; struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsystem, .listener = &listener, }; char expected_page[UT_ANA_LOG_PAGE_SIZE] = {0}; char actual_page[UT_ANA_LOG_PAGE_SIZE] = {0}; @@ -1938,7 +1946,9 @@ test_get_ana_log_page_multi_ns_per_anagrp(void) subsystem.max_nsid = 5; subsystem.ana_group[1] = 3; subsystem.ana_group[2] = 2; - listener.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; + for (i = 0; i < 5; i++) { + listener.ana_state[i] = SPDK_NVME_ANA_OPTIMIZED_STATE; + } for (i = 0; i < 5; i++) { ns_arr[i]->nsid = i + 1; @@ -2365,7 +2375,8 @@ test_spdk_nvmf_request_zcopy_start(void) struct spdk_nvmf_subsystem subsystem = {}; struct spdk_nvmf_ns ns = {}; struct spdk_nvmf_ns *subsys_ns[1] = {}; - struct spdk_nvmf_subsystem_listener listener = {}; + enum spdk_nvme_ana_state ana_state[1]; + struct spdk_nvmf_subsystem_listener listener = { .ana_state = ana_state }; struct spdk_bdev bdev = { .blockcnt = 100, .blocklen = 512}; struct spdk_nvmf_poll_group group = {}; @@ -2382,7 +2393,7 @@ test_spdk_nvmf_request_zcopy_start(void) subsys_ns[0] = &ns; subsystem.ns = (struct spdk_nvmf_ns **)&subsys_ns; - listener.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; + listener.ana_state[0] = SPDK_NVME_ANA_OPTIMIZED_STATE; /* Enable controller */ ctrlr.vcprop.cc.bits.en = 1; @@ -2489,7 +2500,8 @@ test_zcopy_read(void) struct spdk_nvmf_subsystem subsystem = {}; struct spdk_nvmf_ns ns = {}; struct spdk_nvmf_ns *subsys_ns[1] = {}; - struct spdk_nvmf_subsystem_listener listener = {}; + enum spdk_nvme_ana_state ana_state[1]; + struct spdk_nvmf_subsystem_listener listener = { .ana_state = ana_state }; struct spdk_bdev bdev = { .blockcnt = 100, .blocklen = 512}; struct spdk_nvmf_poll_group group = {}; @@ -2506,7 +2518,7 @@ test_zcopy_read(void) subsys_ns[0] = &ns; subsystem.ns = (struct spdk_nvmf_ns **)&subsys_ns; - listener.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; + listener.ana_state[0] = SPDK_NVME_ANA_OPTIMIZED_STATE; /* Enable controller */ ctrlr.vcprop.cc.bits.en = 1; @@ -2575,7 +2587,8 @@ test_zcopy_write(void) struct spdk_nvmf_subsystem subsystem = {}; struct spdk_nvmf_ns ns = {}; struct spdk_nvmf_ns *subsys_ns[1] = {}; - struct spdk_nvmf_subsystem_listener listener = {}; + enum spdk_nvme_ana_state ana_state[1]; + struct spdk_nvmf_subsystem_listener listener = { .ana_state = ana_state }; struct spdk_bdev bdev = { .blockcnt = 100, .blocklen = 512}; struct spdk_nvmf_poll_group group = {}; @@ -2592,7 +2605,7 @@ test_zcopy_write(void) subsys_ns[0] = &ns; subsystem.ns = (struct spdk_nvmf_ns **)&subsys_ns; - listener.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; + listener.ana_state[0] = SPDK_NVME_ANA_OPTIMIZED_STATE; /* Enable controller */ ctrlr.vcprop.cc.bits.en = 1;