Commit 7003bd0d authored by Changpeng Liu's avatar Changpeng Liu Committed by Tomasz Zawadzki
Browse files

nvmf/vfio-user: take endpoint as input parameter in quiesce_done



QEMU may exit due to some exceptions which mean the socket
connection may be disconnected at any time, so for asynchronous
callbacks especially the subsystem pause/resume callbacks, they
all run in asynchronous way, the controller pointer may become
invalid before the callbacks are called.

Fix #2530.

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


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 avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 5fd83ebd
Loading
Loading
Loading
Loading
+31 −11
Original line number Diff line number Diff line
@@ -2899,7 +2899,7 @@ init_pci_config_space(vfu_pci_config_space_t *p)
}

struct ctrlr_quiesce_ctx {
	struct nvmf_vfio_user_ctrlr *ctrlr;
	struct nvmf_vfio_user_endpoint *endpoint;
	struct nvmf_vfio_user_poll_group *group;
	int status;
};
@@ -2914,6 +2914,10 @@ _vfio_user_endpoint_resume_done_msg(void *ctx)

	endpoint->need_resume = false;

	if (!vu_ctrlr) {
		return;
	}

	if (!vu_ctrlr->queued_quiesce) {
		vu_ctrlr->state = VFIO_USER_CTRLR_RUNNING;

@@ -2961,10 +2965,15 @@ static void
vfio_user_quiesce_done(void *ctx)
{
	struct ctrlr_quiesce_ctx *quiesce_ctx = ctx;
	struct nvmf_vfio_user_ctrlr *vu_ctrlr = quiesce_ctx->ctrlr;
	struct nvmf_vfio_user_endpoint *endpoint = vu_ctrlr->endpoint;
	struct nvmf_vfio_user_endpoint *endpoint = quiesce_ctx->endpoint;
	struct nvmf_vfio_user_ctrlr *vu_ctrlr = endpoint->ctrlr;
	int ret;

	if (!vu_ctrlr) {
		free(quiesce_ctx);
		return;
	}

	SPDK_DEBUGLOG(nvmf_vfio, "%s device quiesced\n", ctrlr_id(vu_ctrlr));

	assert(vu_ctrlr->state == VFIO_USER_CTRLR_PAUSING);
@@ -2996,13 +3005,20 @@ vfio_user_pause_done(struct spdk_nvmf_subsystem *subsystem,
		     void *ctx, int status)
{
	struct ctrlr_quiesce_ctx *quiesce_ctx = ctx;
	struct nvmf_vfio_user_endpoint *endpoint = quiesce_ctx->endpoint;
	struct nvmf_vfio_user_ctrlr *vu_ctrlr = endpoint->ctrlr;

	if (!vu_ctrlr) {
		free(quiesce_ctx);
		return;
	}

	quiesce_ctx->status = status;

	SPDK_DEBUGLOG(nvmf_vfio, "%s pause done with status %d\n",
		      ctrlr_id(quiesce_ctx->ctrlr), status);
		      ctrlr_id(vu_ctrlr), status);

	spdk_thread_send_msg(quiesce_ctx->ctrlr->thread,
	spdk_thread_send_msg(vu_ctrlr->thread,
			     vfio_user_quiesce_done, ctx);
}

@@ -3019,15 +3035,20 @@ static void
vfio_user_quiesce_pg(void *ctx)
{
	struct ctrlr_quiesce_ctx *quiesce_ctx = ctx;
	struct nvmf_vfio_user_ctrlr *vu_ctrlr = quiesce_ctx->ctrlr;
	struct spdk_nvmf_subsystem *subsystem = vu_ctrlr->endpoint->subsystem;
	struct nvmf_vfio_user_endpoint *endpoint = quiesce_ctx->endpoint;
	struct nvmf_vfio_user_ctrlr *vu_ctrlr = endpoint->ctrlr;
	struct nvmf_vfio_user_poll_group *vu_group = quiesce_ctx->group;
	struct spdk_nvmf_subsystem *subsystem = endpoint->subsystem;
	int ret;

	SPDK_DEBUGLOG(nvmf_vfio, "quiesced pg:%p\n", vu_group);

	quiesce_ctx->group = TAILQ_NEXT(vu_group, link);
	if (!vu_ctrlr) {
		free(quiesce_ctx);
		return;
	}

	quiesce_ctx->group = TAILQ_NEXT(vu_group, link);
	if (quiesce_ctx->group != NULL)  {
		spdk_thread_send_msg(poll_group_to_thread(quiesce_ctx->group),
				     vfio_user_quiesce_pg, quiesce_ctx);
@@ -3038,7 +3059,7 @@ vfio_user_quiesce_pg(void *ctx)
					vfio_user_pause_done, quiesce_ctx);
	if (ret < 0) {
		SPDK_ERRLOG("%s: failed to pause, ret=%d\n",
			    endpoint_id(vu_ctrlr->endpoint), ret);
			    endpoint_id(endpoint), ret);
		vu_ctrlr->state = VFIO_USER_CTRLR_RUNNING;
		fail_ctrlr(vu_ctrlr);
		free(quiesce_ctx);
@@ -3059,7 +3080,7 @@ ctrlr_quiesce(struct nvmf_vfio_user_ctrlr *vu_ctrlr)
		return;
	}

	quiesce_ctx->ctrlr = vu_ctrlr;
	quiesce_ctx->endpoint = vu_ctrlr->endpoint;
	quiesce_ctx->status = 0;
	quiesce_ctx->group = TAILQ_FIRST(&vu_ctrlr->transport->poll_groups);

@@ -3072,7 +3093,6 @@ vfio_user_dev_quiesce_cb(vfu_ctx_t *vfu_ctx)
{
	struct nvmf_vfio_user_endpoint *endpoint = vfu_get_private(vfu_ctx);
	struct spdk_nvmf_subsystem *subsystem = endpoint->subsystem;

	struct nvmf_vfio_user_ctrlr *vu_ctrlr = endpoint->ctrlr;

	if (!vu_ctrlr) {