nvme: Hold namespaces in an RB_TREE

Since this is now sparsely populated, a tree is a better choice.

Change-Id: Ie66d913fa1d298de56a7d22ef55f0adf7f8803b8
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10031
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Ben Walker 2021-10-25 14:16:00 -07:00 committed by Tomasz Zawadzki
parent b4dace738e
commit e7602c158f
6 changed files with 90 additions and 73 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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