Commit 517b5572 authored by Ben Walker's avatar Ben Walker Committed by Tomasz Zawadzki
Browse files

nvme: Do not track a separate active namespace list



We only populate active namespaces into the main namespace tree, so we
don't need a separate list of active namespaces too.

Change-Id: Iaf194f806cc1d9672f5567cff3dffafff3165069
Signed-off-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10034


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
parent dbde5edd
Loading
Loading
Loading
Loading
+62 −77
Original line number Diff line number Diff line
@@ -2230,6 +2230,7 @@ nvme_ctrlr_destruct_namespace(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
	}

	nvme_ns_destruct(ns);
	ns->active = false;

	return 0;
}
@@ -2239,7 +2240,7 @@ nvme_ctrlr_construct_namespace(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
{
	struct spdk_nvme_ns *ns;

	if (nsid < 1 || nsid > ctrlr->num_ns) {
	if (nsid < 1 || nsid > ctrlr->cdata.nn) {
		return -EINVAL;
	}

@@ -2249,45 +2250,44 @@ nvme_ctrlr_construct_namespace(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
		return -ENOMEM;
	}

	ns->active = true;

	return 0;
}

static void
nvme_ctrlr_identify_active_ns_swap(struct spdk_nvme_ctrlr *ctrlr, uint32_t **new_ns_list,
nvme_ctrlr_identify_active_ns_swap(struct spdk_nvme_ctrlr *ctrlr, uint32_t *new_ns_list,
				   size_t max_entries)
{
	uint32_t active_ns_count = 0;
	size_t i;
	uint32_t nsid, n;
	uint32_t nsid;
	struct spdk_nvme_ns *ns, *tmp_ns;
	int rc;

	/* First, remove namespaces that no longer exist */
	for (i = 0; i < ctrlr->active_ns_count; i++) {
		nsid = ctrlr->active_ns_list[i];

		assert(nsid != 0);

		n = (*new_ns_list)[0];
	RB_FOREACH_SAFE(ns, nvme_ns_tree, &ctrlr->ns, tmp_ns) {
		nsid = new_ns_list[0];
		active_ns_count = 0;
		while (n != 0) {
			if (n == nsid) {
		while (nsid != 0) {
			if (nsid == ns->id) {
				break;
			}

			n = (*new_ns_list)[active_ns_count++];
			nsid = new_ns_list[active_ns_count++];
		}

		if (n != nsid) {
		if (nsid != ns->id) {
			/* Did not find this namespace id in the new list. */
			NVME_CTRLR_DEBUGLOG(ctrlr, "Namespace %u was removed\n", nsid);
			nvme_ctrlr_destruct_namespace(ctrlr, nsid);
			NVME_CTRLR_DEBUGLOG(ctrlr, "Namespace %u was removed\n", ns->id);
			nvme_ctrlr_destruct_namespace(ctrlr, ns->id);
		}
	}

	/* Next, add new namespaces */
	active_ns_count = 0;
	for (i = 0; i < max_entries; i++) {
		nsid = (*new_ns_list)[active_ns_count];
		nsid = new_ns_list[active_ns_count];

		if (nsid == 0) {
			break;
@@ -2305,10 +2305,7 @@ nvme_ctrlr_identify_active_ns_swap(struct spdk_nvme_ctrlr *ctrlr, uint32_t **new
		active_ns_count++;
	}

	spdk_free(ctrlr->active_ns_list);
	ctrlr->active_ns_list = *new_ns_list;
	ctrlr->active_ns_count = active_ns_count;
	*new_ns_list = NULL;
}

static void
@@ -2425,13 +2422,11 @@ _nvme_active_ns_ctx_deleter(struct nvme_active_ns_ctx *ctx)

	assert(ctx->state == NVME_ACTIVE_NS_STATE_DONE);

	ctrlr->num_ns = ctrlr->cdata.nn;

	RB_FOREACH(ns, nvme_ns_tree, &ctrlr->ns) {
		nvme_ns_free_iocs_specific_data(ns);
	}

	nvme_ctrlr_identify_active_ns_swap(ctrlr, &ctx->new_ns_list, ctx->page_count * 1024);
	nvme_ctrlr_identify_active_ns_swap(ctrlr, ctx->new_ns_list, ctx->page_count * 1024);
	nvme_active_ns_ctx_destroy(ctx);
	nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_IDENTIFY_NS, ctrlr->opts.admin_timeout_ms);
}
@@ -2478,7 +2473,7 @@ nvme_ctrlr_identify_active_ns(struct spdk_nvme_ctrlr *ctrlr)
	}

	assert(ctx->state == NVME_ACTIVE_NS_STATE_DONE);
	nvme_ctrlr_identify_active_ns_swap(ctrlr, &ctx->new_ns_list, ctx->page_count * 1024);
	nvme_ctrlr_identify_active_ns_swap(ctrlr, ctx->new_ns_list, ctx->page_count * 1024);
	nvme_active_ns_ctx_destroy(ctx);

	return 0;
@@ -4180,9 +4175,6 @@ nvme_ctrlr_destruct_poll_async(struct spdk_nvme_ctrlr *ctrlr,
		spdk_free(ns);
	}

	ctrlr->num_ns = 0;
	spdk_free(ctrlr->active_ns_list);
	ctrlr->active_ns_list = NULL;
	ctrlr->active_ns_count = 0;

	spdk_bit_array_free(&ctrlr->free_io_qids);
@@ -4384,62 +4376,65 @@ spdk_nvme_ctrlr_get_pmrsz(struct spdk_nvme_ctrlr *ctrlr)
uint32_t
spdk_nvme_ctrlr_get_num_ns(struct spdk_nvme_ctrlr *ctrlr)
{
	return ctrlr->num_ns;
	return ctrlr->cdata.nn;
}

static int32_t
nvme_ctrlr_active_ns_idx(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
bool
spdk_nvme_ctrlr_is_active_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
{
	int32_t result = -1;

	if (ctrlr->active_ns_list == NULL ||
	    ctrlr->active_ns_count == 0 ||
	    nsid == 0 ||
	    nsid > ctrlr->cdata.nn) {
		return result;
	}
	struct spdk_nvme_ns tmp, *ns;

	int32_t lower = 0;
	int32_t upper = ctrlr->active_ns_count - 1;
	int32_t mid;
	tmp.id = nsid;
	ns = RB_FIND(nvme_ns_tree, &ctrlr->ns, &tmp);

	while (lower <= upper) {
		mid = lower + (upper - lower) / 2;
		if (ctrlr->active_ns_list[mid] == nsid) {
			result = mid;
			break;
		} else {
			if (ctrlr->active_ns_list[mid] != 0 && ctrlr->active_ns_list[mid] < nsid) {
				lower = mid + 1;
			} else {
				upper = mid - 1;
	if (ns != NULL) {
		return ns->active;
	}

	return false;
}

uint32_t
spdk_nvme_ctrlr_get_first_active_ns(struct spdk_nvme_ctrlr *ctrlr)
{
	struct spdk_nvme_ns *ns;

	ns = RB_MIN(nvme_ns_tree, &ctrlr->ns);
	if (ns == NULL) {
		return 0;
	}

	return result;
	while (ns != NULL) {
		if (ns->active) {
			return ns->id;
		}

bool
spdk_nvme_ctrlr_is_active_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
{
	return nvme_ctrlr_active_ns_idx(ctrlr, nsid) != -1;
		ns = RB_NEXT(nvme_ns_tree, &ctrlr->ns, ns);
	}

uint32_t
spdk_nvme_ctrlr_get_first_active_ns(struct spdk_nvme_ctrlr *ctrlr)
{
	return ctrlr->active_ns_list ? ctrlr->active_ns_list[0] : 0;
	return 0;
}

uint32_t
spdk_nvme_ctrlr_get_next_active_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t prev_nsid)
{
	int32_t nsid_idx = nvme_ctrlr_active_ns_idx(ctrlr, prev_nsid);
	if (nsid_idx >= 0 && (uint32_t)(nsid_idx + 1) < ctrlr->active_ns_count) {
		return ctrlr->active_ns_list[nsid_idx + 1];
	struct spdk_nvme_ns tmp, *ns;

	tmp.id = prev_nsid;
	ns = RB_FIND(nvme_ns_tree, &ctrlr->ns, &tmp);
	if (ns == NULL) {
		return 0;
	}

	ns = RB_NEXT(nvme_ns_tree, &ctrlr->ns, ns);
	while (ns != NULL) {
		if (ns->active) {
			return ns->id;
		}

		ns = RB_NEXT(nvme_ns_tree, &ctrlr->ns, ns);
	}

	return 0;
}

@@ -4449,7 +4444,7 @@ 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) {
	if (nsid < 1 || nsid > ctrlr->cdata.nn) {
		return NULL;
	}

@@ -4625,12 +4620,7 @@ spdk_nvme_ctrlr_detach_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid,
	}
	free(status);

	res = nvme_ctrlr_identify_active_ns(ctrlr);
	if (res) {
		return res;
	}

	return nvme_ctrlr_destruct_namespace(ctrlr, nsid);
	return nvme_ctrlr_identify_active_ns(ctrlr);
}

uint32_t
@@ -4698,12 +4688,7 @@ spdk_nvme_ctrlr_delete_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
	}
	free(status);

	res = nvme_ctrlr_identify_active_ns(ctrlr);
	if (res) {
		return res;
	}

	return nvme_ctrlr_destruct_namespace(ctrlr, nsid);
	return nvme_ctrlr_identify_active_ns(ctrlr);
}

int
+8 −2
Original line number Diff line number Diff line
@@ -46,9 +46,15 @@ spdk_nvme_ctrlr_is_ocssd_supported(struct spdk_nvme_ctrlr *ctrlr)
		 * Current QEMU OpenChannel Device needs to check nsdata->vs[0].
		 * Here check nsdata->vs[0] of the first namespace.
		 */
		if (ctrlr->cdata.vid == SPDK_PCI_VID_CNEXLABS && ctrlr->num_ns) {
		if (ctrlr->cdata.vid == SPDK_PCI_VID_CNEXLABS) {
			uint32_t nsid = spdk_nvme_ctrlr_get_first_active_ns(ctrlr);
			struct spdk_nvme_ns *ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid);
			struct spdk_nvme_ns *ns;

			if (nsid == 0) {
				return false;
			}

			ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid);

			if (ns && ns->nsdata.vendor_specific[0] == 0x1) {
				return true;
+1 −3
Original line number Diff line number Diff line
@@ -518,6 +518,7 @@ struct spdk_nvme_ns {
	uint32_t			sectors_per_stripe;
	uint32_t			id;
	uint16_t			flags;
	bool				active;

	/* Command Set Identifier */
	enum spdk_nvme_csi		csi;
@@ -863,8 +864,6 @@ struct spdk_nvme_ctrlr {
	/* Tree of namespaces */
	RB_HEAD(nvme_ns_tree, spdk_nvme_ns)	ns;

	uint32_t			num_ns;

	bool				is_removed;

	bool				is_resetting;
@@ -951,7 +950,6 @@ struct spdk_nvme_ctrlr {
	 * Keep track of active namespaces
	 */
	uint32_t			active_ns_count;
	uint32_t			*active_ns_list;

	struct spdk_bit_array		*free_io_qids;
	TAILQ_HEAD(, spdk_nvme_qpair)	active_io_qpairs;
+43 −24
Original line number Diff line number Diff line
@@ -511,7 +511,7 @@ nvme_ctrlr_cmd_identify(struct spdk_nvme_ctrlr *ctrlr, uint8_t cns, uint16_t cnt
		struct spdk_nvme_ns_list *ns_list = (struct spdk_nvme_ns_list *)payload;

		if (g_active_ns_list == NULL) {
			for (i = 1; i <= ctrlr->num_ns; i++) {
			for (i = 1; i <= ctrlr->cdata.nn; i++) {
				if (i <= nsid) {
					continue;
				}
@@ -2091,6 +2091,13 @@ test_nvme_ctrlr_test_active_ns(void)
	uint32_t		nsid, minor;
	size_t			ns_id_count;
	struct spdk_nvme_ctrlr	ctrlr = {};
	uint32_t		active_ns_list[1531];

	for (nsid = 1; nsid <= 1531; nsid++) {
		active_ns_list[nsid - 1] = nsid;
	}

	g_active_ns_list = active_ns_list;

	ctrlr.page_size = 0x1000;

@@ -2104,11 +2111,11 @@ test_nvme_ctrlr_test_active_ns(void)
		ctrlr.cdata.nn = 1531;

		RB_INIT(&ctrlr.ns);
		ctrlr.num_ns = ctrlr.cdata.nn;

		g_active_ns_list_length = SPDK_COUNTOF(active_ns_list);
		nvme_ctrlr_identify_active_ns(&ctrlr);

		for (nsid = 1; nsid <= ctrlr.num_ns; nsid++) {
		for (nsid = 1; nsid <= ctrlr.cdata.nn; nsid++) {
			CU_ASSERT(spdk_nvme_ctrlr_is_active_ns(&ctrlr, nsid) == true);
		}

@@ -2116,12 +2123,18 @@ test_nvme_ctrlr_test_active_ns(void)
			CU_ASSERT(spdk_nvme_ctrlr_is_active_ns(&ctrlr, nsid) == false);
		}

		for (nsid = 0; nsid < ctrlr.num_ns; nsid++) {
			ctrlr.active_ns_list[nsid] = 0;
		g_active_ns_list_length = 0;
		if (minor <= 1) {
			ctrlr.cdata.nn = 0;
		}
		nvme_ctrlr_identify_active_ns(&ctrlr);
		CU_ASSERT(spdk_nvme_ctrlr_get_first_active_ns(&ctrlr) == 0);

		ctrlr.active_ns_list[0] = 1;
		g_active_ns_list_length = 1;
		if (minor <= 1) {
			ctrlr.cdata.nn = 1;
		}
		nvme_ctrlr_identify_active_ns(&ctrlr);
		CU_ASSERT(spdk_nvme_ctrlr_is_active_ns(&ctrlr, 1) == true);
		CU_ASSERT(spdk_nvme_ctrlr_is_active_ns(&ctrlr, 2) == false);
		nsid = spdk_nvme_ctrlr_get_first_active_ns(&ctrlr);
@@ -2130,7 +2143,9 @@ test_nvme_ctrlr_test_active_ns(void)
		if (minor >= 2) {
			/* For NVMe 1.2 and newer, the namespace list can have "holes" where
			 * some namespaces are not active. Test this. */
			ctrlr.active_ns_list[1] = 3;
			g_active_ns_list_length = 2;
			g_active_ns_list[1] = 3;
			nvme_ctrlr_identify_active_ns(&ctrlr);
			CU_ASSERT(spdk_nvme_ctrlr_is_active_ns(&ctrlr, 1) == true);
			CU_ASSERT(spdk_nvme_ctrlr_is_active_ns(&ctrlr, 2) == false);
			CU_ASSERT(spdk_nvme_ctrlr_is_active_ns(&ctrlr, 3) == true);
@@ -2138,12 +2153,16 @@ test_nvme_ctrlr_test_active_ns(void)
			CU_ASSERT(nsid == 3);
			nsid = spdk_nvme_ctrlr_get_next_active_ns(&ctrlr, nsid);
			CU_ASSERT(nsid == 0);

			/* Reset the active namespace list array */
			g_active_ns_list[1] = 2;
		}

		memset(ctrlr.active_ns_list, 0, sizeof(uint32_t) * ctrlr.num_ns);
		for (nsid = 0; nsid < ctrlr.num_ns; nsid++) {
			ctrlr.active_ns_list[nsid] = nsid + 1;
		g_active_ns_list_length = SPDK_COUNTOF(active_ns_list);
		if (minor <= 1) {
			ctrlr.cdata.nn = 1531;
		}
		nvme_ctrlr_identify_active_ns(&ctrlr);

		ns_id_count = 0;
		for (nsid = spdk_nvme_ctrlr_get_first_active_ns(&ctrlr);
@@ -2151,10 +2170,13 @@ test_nvme_ctrlr_test_active_ns(void)
			CU_ASSERT(spdk_nvme_ctrlr_is_active_ns(&ctrlr, nsid) == true);
			ns_id_count++;
		}
		CU_ASSERT(ns_id_count == ctrlr.num_ns);
		CU_ASSERT(ns_id_count == ctrlr.cdata.nn);

		nvme_ctrlr_destruct(&ctrlr);
	}

	g_active_ns_list = NULL;
	g_active_ns_list_length = 0;
}

static void
@@ -2717,7 +2739,7 @@ test_nvme_ctrlr_ns_mgmt(void)
	CU_ASSERT(spdk_nvme_ctrlr_delete_ns(&ctrlr, 3) == 0);
	CU_ASSERT(!spdk_nvme_ctrlr_is_active_ns(&ctrlr, 3));
	CU_ASSERT(spdk_nvme_ctrlr_get_ns(&ctrlr, 3) != NULL);
	g_active_ns_list = 0;
	g_active_ns_list = NULL;
	g_active_ns_list_length = 0;

	nvme_ctrlr_destruct(&ctrlr);
@@ -2768,7 +2790,7 @@ test_nvme_ctrlr_reset(void)
	g_set_reg_cb = NULL;
	CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_READY);
	g_cdata = NULL;
	g_active_ns_list = 0;
	g_active_ns_list = NULL;
	g_active_ns_list_length = 0;

	CU_ASSERT(spdk_nvme_ctrlr_get_num_ns(&ctrlr) == 4096);
@@ -2824,7 +2846,7 @@ test_nvme_ctrlr_aer_callback(void)
	nvme_ctrlr_async_event_cb(&ctrlr.aer[0], &aer_cpl);
	nvme_ctrlr_complete_queued_async_events(&ctrlr);
	CU_ASSERT(g_aer_cb_counter == 1);
	g_active_ns_list = 0;
	g_active_ns_list = NULL;
	g_active_ns_list_length = 0;

	nvme_ctrlr_free_processes(&ctrlr);
@@ -2886,7 +2908,7 @@ test_nvme_ctrlr_ns_attr_changed(void)
	CU_ASSERT(g_aer_cb_counter == 2);
	CU_ASSERT(spdk_nvme_ctrlr_is_active_ns(&ctrlr, 101));

	g_active_ns_list = 0;
	g_active_ns_list = NULL;
	g_active_ns_list_length = 0;
	nvme_ctrlr_free_processes(&ctrlr);
	nvme_ctrlr_destruct(&ctrlr);
@@ -2897,7 +2919,6 @@ test_nvme_ctrlr_identify_namespaces_iocs_specific_next(void)
{
	struct spdk_nvme_ctrlr ctrlr = {};
	uint32_t prev_nsid;
	uint32_t active_ns_list[5] = {1, 2, 3, 4, 5};
	struct spdk_nvme_ns ns[5] = {};
	struct spdk_nvme_ctrlr ns_ctrlr[5] = {};
	int rc = 0;
@@ -2906,14 +2927,12 @@ test_nvme_ctrlr_identify_namespaces_iocs_specific_next(void)
	RB_INIT(&ctrlr.ns);
	for (i = 0; i < 5; i++) {
		ns[i].id = i + 1;
		RB_INSERT(nvme_ns_tree, &ctrlr.ns, &ns[i]);
		ns[i].active = true;
	}

	ctrlr.cdata.nn = 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);
@@ -2925,7 +2944,9 @@ test_nvme_ctrlr_identify_namespaces_iocs_specific_next(void)
	memset(&ctrlr.state, 0x00, sizeof(ctrlr.state));
	memset(&ctrlr.state_timeout_tsc, 0x00, sizeof(ctrlr.state_timeout_tsc));
	prev_nsid = 1;
	ctrlr.active_ns_list = active_ns_list;
	for (i = 0; i < 5; i++) {
		RB_INSERT(nvme_ns_tree, &ctrlr.ns, &ns[i]);
	}
	ctrlr.active_ns_count = 5;
	ns[1].csi = SPDK_NVME_CSI_NVM;
	ns[1].id = 2;
@@ -2939,7 +2960,6 @@ test_nvme_ctrlr_identify_namespaces_iocs_specific_next(void)
	memset(&ctrlr.state_timeout_tsc, 0x00, sizeof(ctrlr.state_timeout_tsc));
	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++) {
@@ -2965,7 +2985,6 @@ test_nvme_ctrlr_identify_namespaces_iocs_specific_next(void)
	memset(&ctrlr.state, 0x00, sizeof(ctrlr.state));
	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;
@@ -3046,12 +3065,12 @@ test_nvme_ctrlr_parse_ana_log_page(void)
	RB_INIT(&ctrlr.ns);
	for (i = 0; i < 3; i++) {
		ns[i].id = i + 1;
		ns[i].active = true;
		RB_INSERT(nvme_ns_tree, &ctrlr.ns, &ns[i]);
	}

	ctrlr.cdata.nn = 3;
	ctrlr.cdata.nanagrpid = 3;
	ctrlr.num_ns = 3;
	ctrlr.active_ns_count = 3;

	rc = nvme_ctrlr_init_ana_log_page(&ctrlr);
@@ -3190,7 +3209,7 @@ test_nvme_ctrlr_ana_resize(void)
		CU_ASSERT(ns->ana_state == SPDK_NVME_ANA_OPTIMIZED_STATE);
	}

	g_active_ns_list = 0;
	g_active_ns_list = NULL;
	g_active_ns_list_length = 0;
	g_ana_hdr = NULL;
	g_ana_descs = NULL;
+1 −1
Original line number Diff line number Diff line
@@ -384,7 +384,7 @@ 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) {
	if (nsid < 1 || nsid > ctrlr->cdata.nn) {
		return NULL;
	}

Loading