Commit bc9c6e9e authored by Tomasz Zawadzki's avatar Tomasz Zawadzki Committed by Tomasz Zawadzki
Browse files

lib/nvme: keep the changed namespaces log page buffer



The buffer that has NSID for changed namespaces is now kept across handling
of a particular AER. For case when it overflowed, just discard it.

Change-Id: Ic00f771d34a83e8e7f01bf5df97a7efa440e2443
Signed-off-by: default avatarTomasz Zawadzki <tomasz.zawadzki@nutanix.com>
Reviewed-on: https://review.spdk.io/c/spdk/spdk/+/26495


Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Tested-by: default avatarSPDK Automated Test System <spdkbot@gmail.com>
Reviewed-by: default avatarJacek Kalwas <jacek.kalwas@nutanix.com>
parent 1ff9eb29
Loading
Loading
Loading
Loading
+21 −11
Original line number Diff line number Diff line
@@ -3202,8 +3202,9 @@ nvme_ctrlr_process_async_event_finish(struct spdk_nvme_ctrlr_aer_completion *asy
}

static void
nvme_ctrlr_update_namespaces(struct spdk_nvme_ctrlr *ctrlr)
nvme_ctrlr_update_namespaces(struct spdk_nvme_ctrlr_aer_completion *async_event)
{
	struct spdk_nvme_ctrlr *ctrlr = async_event->ctrlr;
	uint32_t nsid;
	struct spdk_nvme_ns *ns;

@@ -3212,28 +3213,33 @@ nvme_ctrlr_update_namespaces(struct spdk_nvme_ctrlr *ctrlr)
		ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid);
		nvme_ns_construct(ns, nsid, ctrlr);
	}

	spdk_dma_free(async_event->log_page.changed_ns_list);
}

static int
nvme_ctrlr_clear_changed_ns_log(struct spdk_nvme_ctrlr *ctrlr)
nvme_ctrlr_clear_changed_ns_log(struct spdk_nvme_ctrlr_aer_completion *async_event)
{
	struct spdk_nvme_ctrlr			*ctrlr = async_event->ctrlr;
	struct nvme_completion_poll_status	*status;
	int		rc = -ENOMEM;
	char		*buffer = NULL;
	uint32_t	*changed_ns_list = NULL;
	uint32_t	nsid;
	size_t		buf_size = (SPDK_NVME_MAX_CHANGED_NAMESPACES * sizeof(uint32_t));
	size_t		changed_ns_list_length = (SPDK_NVME_MAX_CHANGED_NAMESPACES * sizeof(uint32_t));

	if (ctrlr->opts.disable_read_changed_ns_list_log_page) {
		return 0;
	}

	buffer = spdk_dma_zmalloc(buf_size, 4096, NULL);
	if (!buffer) {
	changed_ns_list = spdk_dma_zmalloc(changed_ns_list_length, 4096, NULL);
	if (!changed_ns_list) {
		NVME_CTRLR_ERRLOG(ctrlr, "Failed to allocate buffer for getting "
				  "changed ns log.\n");
		return rc;
	}

	async_event->log_page.changed_ns_list = changed_ns_list;

	status = calloc(1, sizeof(*status));
	if (!status) {
		NVME_CTRLR_ERRLOG(ctrlr, "Failed to allocate status tracker\n");
@@ -3243,7 +3249,7 @@ nvme_ctrlr_clear_changed_ns_log(struct spdk_nvme_ctrlr *ctrlr)
	rc = spdk_nvme_ctrlr_cmd_get_log_page(ctrlr,
					      SPDK_NVME_LOG_CHANGED_NS_LIST,
					      SPDK_NVME_GLOBAL_NS_TAG,
					      buffer, buf_size, 0,
					      changed_ns_list, changed_ns_list_length, 0,
					      nvme_completion_poll_cb, status);

	if (rc) {
@@ -3264,13 +3270,17 @@ nvme_ctrlr_clear_changed_ns_log(struct spdk_nvme_ctrlr *ctrlr)
	}

	/* only check the case of overflow. */
	nsid = from_le32(buffer);
	nsid = from_le32(changed_ns_list);
	if (nsid == 0xffffffffu) {
		NVME_CTRLR_WARNLOG(ctrlr, "changed ns log overflowed.\n");
		goto free_buffer;
	}

	return rc;

free_buffer:
	spdk_dma_free(buffer);
	spdk_dma_free(changed_ns_list);
	async_event->log_page.changed_ns_list = NULL;
	return rc;
}

@@ -3286,13 +3296,13 @@ nvme_ctrlr_process_async_event(struct spdk_nvme_ctrlr_aer_completion *async_even

	if ((event.bits.async_event_type == SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE) &&
	    (event.bits.async_event_info == SPDK_NVME_ASYNC_EVENT_NS_ATTR_CHANGED)) {
		nvme_ctrlr_clear_changed_ns_log(ctrlr);
		nvme_ctrlr_clear_changed_ns_log(async_event);

		rc = nvme_ctrlr_identify_active_ns(ctrlr);
		if (rc) {
			return;
		}
		nvme_ctrlr_update_namespaces(ctrlr);
		nvme_ctrlr_update_namespaces(async_event);
		nvme_io_msg_ctrlr_update(ctrlr);
	}

+6 −0
Original line number Diff line number Diff line
@@ -923,6 +923,12 @@ enum nvme_ctrlr_state {
struct spdk_nvme_ctrlr_aer_completion {
	struct spdk_nvme_ctrlr	*ctrlr;
	struct spdk_nvme_cpl	cpl;

	union {
		/* Contains payload of Changed Attached Namespace List log page. */
		uint32_t		*changed_ns_list;
	} log_page;

	STAILQ_ENTRY(spdk_nvme_ctrlr_aer_completion) link;
};

+13 −0
Original line number Diff line number Diff line
@@ -3019,6 +3019,7 @@ test_nvme_ctrlr_ns_attr_changed(void)
	uint32_t active_ns_list6_aer2[] = { 1, 2, 105, 1024 };
	uint32_t changed_ns_list6_aer2[] = { 104, 105 };
	uint32_t active_ns_list7[] = { 1, 2, 105, 106, 1024 };
	uint32_t changed_ns_list7_aer[] = { 0xFFFFFFFF };
	union spdk_nvme_async_event_completion	aer_event = {
		.bits.async_event_type = SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE,
		.bits.async_event_info = SPDK_NVME_ASYNC_EVENT_NS_ATTR_CHANGED
@@ -3148,6 +3149,18 @@ test_nvme_ctrlr_ns_attr_changed(void)
	check_active_ns(&ctrlr, active_ns_list7, SPDK_COUNTOF(active_ns_list7));
	ctrlr.opts.disable_read_changed_ns_list_log_page = false;

	/* Log page overflowed - there were more than 1024 changes since last read.
	 * Yet the active namespaces remain as they were. */
	g_aer_cb_counter = 0;
	g_nvme_ns_constructed = 0;
	setup_aer_for_ns_change(active_ns_list7, SPDK_COUNTOF(active_ns_list7),
				changed_ns_list7_aer, SPDK_COUNTOF(changed_ns_list7_aer));
	nvme_ctrlr_complete_queued_async_events(&ctrlr);
	CU_ASSERT(g_aer_cb_counter == 1);
	/* Log page overflowed, issued identify to all active NS. */
	CU_ASSERT(g_nvme_ns_constructed == SPDK_COUNTOF(active_ns_list7));
	check_active_ns(&ctrlr, active_ns_list7, SPDK_COUNTOF(active_ns_list7));

	nvme_ctrlr_free_processes(&ctrlr);
	nvme_ctrlr_destruct(&ctrlr);
}