diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index de2d50638..f100140c7 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -54,6 +54,20 @@ static void nvme_ctrlr_init_cap(struct spdk_nvme_ctrlr *ctrlr); static void nvme_ctrlr_set_state(struct spdk_nvme_ctrlr *ctrlr, enum nvme_ctrlr_state state, uint64_t timeout_in_ms); +static int +nvme_ns_cmp(struct spdk_nvme_ns *ns1, struct spdk_nvme_ns *ns2) +{ + if (ns1->id < ns2->id) { + return -1; + } else if (ns1->id > ns2->id) { + return 1; + } else { + return 0; + } +} + +RB_GENERATE_STATIC(nvme_ns_tree, spdk_nvme_ns, node, nvme_ns_cmp); + #define CTRLR_STRING(ctrlr) \ ((ctrlr->trid.trtype == SPDK_NVME_TRANSPORT_TCP || ctrlr->trid.trtype == SPDK_NVME_TRANSPORT_RDMA) ? \ ctrlr->trid.subnqn : ctrlr->trid.traddr) @@ -2206,17 +2220,14 @@ nvme_active_ns_ctx_destroy(struct nvme_active_ns_ctx *ctx) static int nvme_ctrlr_destruct_namespace(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid) { - struct spdk_nvme_ns *ns; + struct spdk_nvme_ns tmp, *ns; assert(ctrlr != NULL); - if (nsid < 1 || nsid > ctrlr->num_ns) { - return -EINVAL; - } - - ns = ctrlr->ns[nsid - 1]; + tmp.id = nsid; + ns = RB_FIND(nvme_ns_tree, &ctrlr->ns, &tmp); if (ns == NULL) { - return 0; + return -EINVAL; } nvme_ns_destruct(ns); @@ -2996,18 +3007,15 @@ nvme_ctrlr_set_host_id(struct spdk_nvme_ctrlr *ctrlr) static void nvme_ctrlr_destruct_namespaces(struct spdk_nvme_ctrlr *ctrlr) { - if (ctrlr->ns) { - uint32_t i, num_ns = ctrlr->num_ns; + struct spdk_nvme_ns *ns, *tmp_ns; - for (i = 1; i <= num_ns; i++) { - nvme_ctrlr_destruct_namespace(ctrlr, i); - spdk_free(ctrlr->ns[i - 1]); - } - - spdk_free(ctrlr->ns); - ctrlr->ns = NULL; - ctrlr->num_ns = 0; + RB_FOREACH_SAFE(ns, nvme_ns_tree, &ctrlr->ns, tmp_ns) { + nvme_ctrlr_destruct_namespace(ctrlr, ns->id); + RB_REMOVE(nvme_ns_tree, &ctrlr->ns, ns); + spdk_free(ns); } + + ctrlr->num_ns = 0; } void @@ -3026,45 +3034,15 @@ nvme_ctrlr_update_namespaces(struct spdk_nvme_ctrlr *ctrlr) static int nvme_ctrlr_construct_namespaces(struct spdk_nvme_ctrlr *ctrlr) { - int rc = 0; - uint32_t i, nn = ctrlr->cdata.nn; - struct spdk_nvme_ns **tmp; struct spdk_nvme_ns *ns; - /* ctrlr->num_ns may be 0 (startup) or a different number of namespaces (reset), - * so check if we need to reallocate. - */ - if (nn != ctrlr->num_ns) { + ctrlr->num_ns = ctrlr->cdata.nn; - tmp = spdk_realloc(ctrlr->ns, nn * sizeof(struct spdk_nvme_ns *), 64); - - if (tmp == NULL) { - rc = -ENOMEM; - goto fail; - } - - if (nn > ctrlr->num_ns) { - memset(tmp + ctrlr->num_ns, 0, (nn - ctrlr->num_ns) * sizeof(struct spdk_nvme_ns *)); - } - - ctrlr->ns = tmp; - ctrlr->num_ns = nn; - } - - for (i = 0; i < ctrlr->num_ns; i++) { - ns = ctrlr->ns[i]; - if (ns != NULL) { - nvme_ns_free_iocs_specific_data(ns); - } + RB_FOREACH(ns, nvme_ns_tree, &ctrlr->ns) { + nvme_ns_free_iocs_specific_data(ns); } return 0; - -fail: - nvme_ctrlr_destruct_namespaces(ctrlr); - NVME_CTRLR_ERRLOG(ctrlr, "Failed to construct namespaces, err %d\n", rc); - nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_ERROR, NVME_TIMEOUT_INFINITE); - return rc; } static int @@ -4146,6 +4124,8 @@ nvme_ctrlr_construct(struct spdk_nvme_ctrlr *ctrlr) TAILQ_INIT(&ctrlr->active_procs); STAILQ_INIT(&ctrlr->register_operations); + RB_INIT(&ctrlr->ns); + return rc; } @@ -4492,6 +4472,7 @@ spdk_nvme_ctrlr_get_next_active_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t prev_ struct spdk_nvme_ns * spdk_nvme_ctrlr_get_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid) { + struct spdk_nvme_ns tmp; struct spdk_nvme_ns *ns; if (nsid < 1 || nsid > ctrlr->num_ns) { @@ -4500,7 +4481,8 @@ spdk_nvme_ctrlr_get_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid) nvme_robust_mutex_lock(&ctrlr->ctrlr_lock); - ns = ctrlr->ns[nsid - 1]; + tmp.id = nsid; + ns = RB_FIND(nvme_ns_tree, &ctrlr->ns, &tmp); if (ns == NULL) { ns = spdk_zmalloc(sizeof(struct spdk_nvme_ns), 64, NULL, SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_SHARE); @@ -4510,7 +4492,8 @@ spdk_nvme_ctrlr_get_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid) } NVME_CTRLR_DEBUGLOG(ctrlr, "Namespace %u was added\n", nsid); - ctrlr->ns[nsid - 1] = ns; + ns->id = nsid; + RB_INSERT(nvme_ns_tree, &ctrlr->ns, ns); } nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock); diff --git a/lib/nvme/nvme_internal.h b/lib/nvme/nvme_internal.h index 27d6b735b..a41e3ca6a 100644 --- a/lib/nvme/nvme_internal.h +++ b/lib/nvme/nvme_internal.h @@ -54,6 +54,7 @@ #include "spdk/memory.h" #include "spdk/nvme_intel.h" #include "spdk/nvmf_spec.h" +#include "spdk/tree.h" #include "spdk/uuid.h" #include "spdk_internal/assert.h" @@ -532,6 +533,8 @@ struct spdk_nvme_ns { /* Zoned Namespace Command Set Specific Identify Namespace data. */ struct spdk_nvme_zns_ns_data *nsdata_zns; + + RB_ENTRY(spdk_nvme_ns) node; }; /** @@ -857,8 +860,8 @@ struct nvme_register_completion { struct spdk_nvme_ctrlr { /* Hot data (accessed in I/O path) starts here. */ - /** Array of namespace pointers indexed by nsid - 1 */ - struct spdk_nvme_ns **ns; + /* Tree of namespaces */ + RB_HEAD(nvme_ns_tree, spdk_nvme_ns) ns; uint32_t num_ns; diff --git a/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c b/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c index 0a254fa0e..b851890cd 100644 --- a/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c +++ b/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c @@ -2103,8 +2103,7 @@ test_nvme_ctrlr_test_active_ns(void) ctrlr.vs.bits.ter = 0; ctrlr.cdata.nn = 1531; - ctrlr.ns = calloc(ctrlr.cdata.nn, sizeof(struct spdk_nvme_ns *)); - SPDK_CU_ASSERT_FATAL(ctrlr.ns != NULL); + RB_INIT(&ctrlr.ns); ctrlr.num_ns = ctrlr.cdata.nn; nvme_ctrlr_identify_active_ns(&ctrlr); @@ -2145,7 +2144,6 @@ test_nvme_ctrlr_test_active_ns(void) for (nsid = 0; nsid < ctrlr.num_ns; nsid++) { ctrlr.active_ns_list[nsid] = nsid + 1; } - ctrlr.active_ns_list[ctrlr.active_ns_count] = 0; ns_id_count = 0; for (nsid = spdk_nvme_ctrlr_get_first_active_ns(&ctrlr); @@ -2901,22 +2899,22 @@ test_nvme_ctrlr_identify_namespaces_iocs_specific_next(void) uint32_t prev_nsid; uint32_t active_ns_list[5] = {1, 2, 3, 4, 5}; struct spdk_nvme_ns ns[5] = {}; - struct spdk_nvme_ns *ns_array[5]; struct spdk_nvme_ctrlr ns_ctrlr[5] = {}; int rc = 0; int i; + RB_INIT(&ctrlr.ns); for (i = 0; i < 5; i++) { - ns_array[i] = &ns[i]; + ns[i].id = i + 1; + RB_INSERT(nvme_ns_tree, &ctrlr.ns, &ns[i]); } - ctrlr.ns = ns_array; ctrlr.cdata.nn = 5; - ctrlr.active_ns_count = 5; ctrlr.num_ns = 5; /* case 1: No first/next active NS, move on to the next state, expect: pass */ prev_nsid = 0; ctrlr.active_ns_list = NULL; + ctrlr.active_ns_count = 0; ctrlr.opts.admin_timeout_ms = NVME_TIMEOUT_INFINITE; rc = nvme_ctrlr_identify_namespaces_iocs_specific_next(&ctrlr, prev_nsid); CU_ASSERT(rc == 0); @@ -2928,6 +2926,7 @@ test_nvme_ctrlr_identify_namespaces_iocs_specific_next(void) memset(&ctrlr.state_timeout_tsc, 0x00, sizeof(ctrlr.state_timeout_tsc)); prev_nsid = 1; ctrlr.active_ns_list = active_ns_list; + ctrlr.active_ns_count = 5; ns[1].csi = SPDK_NVME_CSI_NVM; ns[1].id = 2; rc = nvme_ctrlr_identify_namespaces_iocs_specific_next(&ctrlr, prev_nsid); @@ -2941,6 +2940,7 @@ test_nvme_ctrlr_identify_namespaces_iocs_specific_next(void) ctrlr.opts.admin_timeout_ms = NVME_TIMEOUT_INFINITE; prev_nsid = 0; ctrlr.active_ns_list = active_ns_list; + ctrlr.active_ns_count = 5; for (int i = 0; i < 5; i++) { ns[i].csi = SPDK_NVME_CSI_NVM; @@ -2966,6 +2966,7 @@ test_nvme_ctrlr_identify_namespaces_iocs_specific_next(void) memset(&ctrlr.state_timeout_tsc, 0x00, sizeof(ctrlr.state_timeout_tsc)); prev_nsid = 1; ctrlr.active_ns_list = active_ns_list; + ctrlr.active_ns_count = 5; ns[1].csi = SPDK_NVME_CSI_ZNS; g_fail_next_identify = true; rc = nvme_ctrlr_identify_namespaces_iocs_specific_next(&ctrlr, prev_nsid); @@ -3037,17 +3038,17 @@ test_nvme_ctrlr_parse_ana_log_page(void) int rc, i; struct spdk_nvme_ctrlr ctrlr = {}; struct spdk_nvme_ns ns[3] = {}; - struct spdk_nvme_ns *ns_array[3]; struct spdk_nvme_ana_page ana_hdr; char _ana_desc[UT_ANA_DESC_SIZE]; struct spdk_nvme_ana_group_descriptor *ana_desc; uint32_t offset; + RB_INIT(&ctrlr.ns); for (i = 0; i < 3; i++) { - ns_array[i] = &ns[i]; + ns[i].id = i + 1; + RB_INSERT(nvme_ns_tree, &ctrlr.ns, &ns[i]); } - ctrlr.ns = ns_array; ctrlr.cdata.nn = 3; ctrlr.cdata.nanagrpid = 3; ctrlr.num_ns = 3; diff --git a/test/unit/lib/nvme/nvme_ctrlr_cmd.c/nvme_ctrlr_cmd_ut.c b/test/unit/lib/nvme/nvme_ctrlr_cmd.c/nvme_ctrlr_cmd_ut.c index 80d0ff5b5..dec7cb492 100644 --- a/test/unit/lib/nvme/nvme_ctrlr_cmd.c/nvme_ctrlr_cmd_ut.c +++ b/test/unit/lib/nvme/nvme_ctrlr_cmd.c/nvme_ctrlr_cmd_ut.c @@ -79,6 +79,14 @@ DEFINE_STUB(nvme_transport_qpair_iterate_requests, int, DEFINE_STUB(nvme_qpair_abort_queued_reqs_with_cbarg, uint32_t, (struct spdk_nvme_qpair *qpair, void *cmd_cb_arg), 0); +static int +nvme_ns_cmp(struct spdk_nvme_ns *ns1, struct spdk_nvme_ns *ns2) +{ + return ns1->id - ns2->id; +} + +RB_GENERATE_STATIC(nvme_ns_tree, spdk_nvme_ns, node, nvme_ns_cmp); + static void verify_firmware_log_page(struct nvme_request *req) { uint32_t temp_cdw10; @@ -373,13 +381,15 @@ static struct spdk_nvme_ns g_inactive_ns = {}; struct spdk_nvme_ns * spdk_nvme_ctrlr_get_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid) { + struct spdk_nvme_ns tmp; struct spdk_nvme_ns *ns; if (nsid < 1 || nsid > ctrlr->num_ns) { return NULL; } - ns = ctrlr->ns[nsid - 1]; + tmp.id = nsid; + ns = RB_FIND(nvme_ns_tree, &ctrlr->ns, &tmp); if (ns == NULL) { return &g_inactive_ns; diff --git a/test/unit/lib/nvme/nvme_ctrlr_ocssd_cmd.c/nvme_ctrlr_ocssd_cmd_ut.c b/test/unit/lib/nvme/nvme_ctrlr_ocssd_cmd.c/nvme_ctrlr_ocssd_cmd_ut.c index 31f5c0fd5..3ef28f3b5 100644 --- a/test/unit/lib/nvme/nvme_ctrlr_ocssd_cmd.c/nvme_ctrlr_ocssd_cmd_ut.c +++ b/test/unit/lib/nvme/nvme_ctrlr_ocssd_cmd.c/nvme_ctrlr_ocssd_cmd_ut.c @@ -59,18 +59,28 @@ verify_request_fn_t verify_fn; static const uint32_t expected_geometry_ns = 1; +static int +nvme_ns_cmp(struct spdk_nvme_ns *ns1, struct spdk_nvme_ns *ns2) +{ + return ns1->id - ns2->id; +} + +RB_GENERATE_STATIC(nvme_ns_tree, spdk_nvme_ns, node, nvme_ns_cmp); + static struct spdk_nvme_ns g_inactive_ns = {}; struct spdk_nvme_ns * spdk_nvme_ctrlr_get_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid) { + struct spdk_nvme_ns tmp; struct spdk_nvme_ns *ns; if (nsid < 1 || nsid > ctrlr->num_ns) { return NULL; } - ns = ctrlr->ns[nsid - 1]; + tmp.id = nsid; + ns = RB_FIND(nvme_ns_tree, &ctrlr->ns, &tmp); if (ns == NULL) { return &g_inactive_ns; @@ -121,13 +131,13 @@ test_spdk_nvme_ctrlr_is_ocssd_supported(void) { struct spdk_nvme_ctrlr ctrlr = {}; struct spdk_nvme_ns ns = {}; - struct spdk_nvme_ns *ns_array; bool rc; - ns_array = &ns; + RB_INIT(&ctrlr.ns); + ns.id = 1; + RB_INSERT(nvme_ns_tree, &ctrlr.ns, &ns); ns.nsdata.vendor_specific[0] = 1; - ctrlr.ns = &ns_array; ctrlr.quirks |= NVME_QUIRK_OCSSD; ctrlr.cdata.vid = SPDK_PCI_VID_CNEXLABS; ctrlr.num_ns = 1; diff --git a/test/unit/lib/nvme/nvme_cuse.c/nvme_cuse_ut.c b/test/unit/lib/nvme/nvme_cuse.c/nvme_cuse_ut.c index c34b2411e..8257c9927 100644 --- a/test/unit/lib/nvme/nvme_cuse.c/nvme_cuse_ut.c +++ b/test/unit/lib/nvme/nvme_cuse.c/nvme_cuse_ut.c @@ -85,6 +85,14 @@ DEFINE_STUB(pthread_join, int, (pthread_t tid, void **val), 0); DEFINE_STUB_V(nvme_ctrlr_update_namespaces, (struct spdk_nvme_ctrlr *ctrlr)); +static int +nvme_ns_cmp(struct spdk_nvme_ns *ns1, struct spdk_nvme_ns *ns2) +{ + return ns1->id - ns2->id; +} + +RB_GENERATE_STATIC(nvme_ns_tree, spdk_nvme_ns, node, nvme_ns_cmp); + struct cuse_io_ctx *g_ut_ctx; struct spdk_nvme_ctrlr *g_ut_ctrlr; uint32_t g_ut_nsid; @@ -135,13 +143,15 @@ static struct spdk_nvme_ns g_inactive_ns = {}; struct spdk_nvme_ns * spdk_nvme_ctrlr_get_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid) { + struct spdk_nvme_ns tmp; struct spdk_nvme_ns *ns; if (nsid < 1 || nsid > ctrlr->num_ns) { return NULL; } - ns = ctrlr->ns[nsid - 1]; + tmp.id = nsid; + ns = RB_FIND(nvme_ns_tree, &ctrlr->ns, &tmp); if (ns == NULL) { return &g_inactive_ns; @@ -291,7 +301,6 @@ test_cuse_nvme_submit_io(void) struct spdk_nvme_ctrlr ctrlr = {}; struct fuse_file_info fi = {}; struct spdk_nvme_ns ns = {}; - struct spdk_nvme_ns *ns_array; struct nvme_user_io *user_io = NULL; char arg[1024] = {}; fuse_req_t req = (void *)0xDEEACDFF; @@ -300,10 +309,11 @@ test_cuse_nvme_submit_io(void) user_io = calloc(3, 4096); SPDK_CU_ASSERT_FATAL(user_io != NULL); - ns_array = &ns; + RB_INIT(&ctrlr.ns); + ns.id = 1; + RB_INSERT(nvme_ns_tree, &ctrlr.ns, &ns); cuse_device.ctrlr = &ctrlr; - ctrlr.ns = &ns_array; ctrlr.num_ns = 1; ns.sector_size = 4096; ns.id = 1;