Commit 95dd9003 authored by Changpeng Liu's avatar Changpeng Liu Committed by Jim Harris
Browse files

nvmf: add save/restore a controller in runtime



When doing live migration, there are some spdk_nvmf_ctrlr internal
data structures need to be saved/restored.

Change-Id: Ie39482e8c49765c36fc3700fbac4ce47ef306f29
Signed-off-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10058


Community-CI: Mellanox Build Bot
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 13f7510f
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -1922,6 +1922,51 @@ nvmf_ctrlr_save_aers(struct spdk_nvmf_ctrlr *ctrlr, uint16_t *aer_cids,
	return ctrlr->nr_aer_reqs;
}

int
nvmf_ctrlr_save_migr_data(struct spdk_nvmf_ctrlr *ctrlr, struct nvmf_ctrlr_migr_data *data)
{
	uint32_t num_async_events = 0;
	struct spdk_nvmf_async_event_completion *event, *event_tmp;

	memcpy(&data->feat, &ctrlr->feat, sizeof(struct spdk_nvmf_ctrlr_feat));
	data->cntlid = ctrlr->cntlid;
	data->acre_enabled = ctrlr->acre_enabled;
	data->notice_aen_mask = ctrlr->notice_aen_mask;

	STAILQ_FOREACH_SAFE(event, &ctrlr->async_events, link, event_tmp) {
		data->async_events[num_async_events++].raw = event->event.raw;
		if (num_async_events == NVMF_MIGR_MAX_PENDING_AERS) {
			SPDK_ERRLOG("%p has too many pending AERs\n", ctrlr);
			break;
		}
	}
	data->num_async_events = num_async_events;

	return 0;
}

int
nvmf_ctrlr_restore_migr_data(struct spdk_nvmf_ctrlr *ctrlr, struct nvmf_ctrlr_migr_data *data)
{
	struct spdk_nvmf_async_event_completion *event;
	uint32_t i;

	memcpy(&ctrlr->feat, &data->feat, sizeof(struct spdk_nvmf_ctrlr_feat));
	ctrlr->acre_enabled = data->acre_enabled;
	ctrlr->notice_aen_mask = data->notice_aen_mask;

	for (i = 0; i < data->num_async_events; i++) {
		event = calloc(1, sizeof(struct spdk_nvmf_async_event_completion));
		if (!event) {
			return -ENOMEM;
		}
		event->event.raw = data->async_events[i].raw;
		STAILQ_INSERT_TAIL(&ctrlr->async_events, event, link);
	}

	return 0;
}

static int
nvmf_ctrlr_set_features_async_event_configuration(struct spdk_nvmf_request *req)
{
+26 −0
Original line number Diff line number Diff line
@@ -282,6 +282,29 @@ struct spdk_nvmf_ctrlr {
	TAILQ_ENTRY(spdk_nvmf_ctrlr)	link;
};

/* Maximum pending AERs that can be migrated */
#define NVMF_MIGR_MAX_PENDING_AERS 256

/* spdk_nvmf_ctrlr private migration data structure used to save/restore a controller */
struct nvmf_ctrlr_migr_data {
	uint32_t				opts_size;

	uint16_t				cntlid;
	uint8_t					reserved1[2];

	struct spdk_nvmf_ctrlr_feat		feat;
	uint32_t				reserved2[2];

	uint32_t				num_async_events;
	uint32_t				acre_enabled;
	uint64_t				notice_aen_mask;
	union spdk_nvme_async_event_completion	async_events[NVMF_MIGR_MAX_PENDING_AERS];

	/* New fields shouldn't go after reserved3 */
	uint8_t					reserved3[3000];
};
SPDK_STATIC_ASSERT(sizeof(struct nvmf_ctrlr_migr_data) == 0x1000, "Incorrect size");

#define NVMF_MAX_LISTENERS_PER_SUBSYSTEM	16

struct spdk_nvmf_subsystem {
@@ -452,6 +475,9 @@ void nvmf_ctrlr_abort_aer(struct spdk_nvmf_ctrlr *ctrlr);
int nvmf_ctrlr_save_aers(struct spdk_nvmf_ctrlr *ctrlr, uint16_t *aer_cids,
			 uint16_t max_aers);

int nvmf_ctrlr_save_migr_data(struct spdk_nvmf_ctrlr *ctrlr, struct nvmf_ctrlr_migr_data *data);
int nvmf_ctrlr_restore_migr_data(struct spdk_nvmf_ctrlr *ctrlr, struct nvmf_ctrlr_migr_data *data);

/*
 * Abort zero-copy requests that already got the buffer (received zcopy_start cb), but haven't
 * started zcopy_end.  These requests are kept on the outstanding queue, but are not waiting for a
+2 −1
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@ struct nvme_migr_device_state {

	uint16_t	reserved2[3];
	uint16_t	nr_aers;
	uint16_t	aer_cids[256];
	uint16_t	aer_cids[NVMF_MIGR_MAX_PENDING_AERS];

	/* Controller private data offset and length if exist, starting at
	 * the beginning of this data structure.
@@ -390,6 +390,7 @@ vfio_user_migr_data_len(void)
	len = NVMF_VFIO_USER_MAX_QPAIRS_PER_CTRLR * (sizeof(struct nvme_migr_sq_state) + sizeof(
				struct nvme_migr_cq_state));
	len += sizeof(struct nvme_migr_device_state);
	len += sizeof(struct nvmf_ctrlr_migr_data);
	len += NVME_REG_BAR0_SIZE;
	len += NVME_REG_CFG_SIZE;
	/* BAR4 */