From 95dd90039f8e27edf0d79c7f128aad7055829d0e Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Fri, 29 Oct 2021 19:48:33 +0800 Subject: [PATCH] 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: Changpeng Liu Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10058 Community-CI: Mellanox Build Bot Community-CI: Broadcom CI Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- lib/nvmf/ctrlr.c | 45 ++++++++++++++++++++++++++++++++++++++++ lib/nvmf/nvmf_internal.h | 26 +++++++++++++++++++++++ lib/nvmf/vfio_user.c | 3 ++- 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/lib/nvmf/ctrlr.c b/lib/nvmf/ctrlr.c index 2dd6d1b98..0aa8d4ca8 100644 --- a/lib/nvmf/ctrlr.c +++ b/lib/nvmf/ctrlr.c @@ -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) { diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index ed2c3805c..e5842b03f 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -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 diff --git a/lib/nvmf/vfio_user.c b/lib/nvmf/vfio_user.c index aac545fff..675c49286 100644 --- a/lib/nvmf/vfio_user.c +++ b/lib/nvmf/vfio_user.c @@ -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 */