Commit 3fb1a956 authored by Darek Stojaczyk's avatar Darek Stojaczyk
Browse files

vhost: finish foreach_session chain always on the init thread



foreach_session() is used to e.g. close a bdev, where
for each session we close any io_channels and then,
on the final "finish" call, close the bdev descriptor.

The vhost init thread is the one that called
spdk_vhost_init() and also the same one that calls
all management APIs. One of those is for hotplugging
LUNs to vhost scsi targets, which practically results
in opening bdev descriptors.

By always scheduling that final foreach_session()
callback to the init thread, we end up with calling
spdk_bdev_close() always on the same thread which
called spdk_bdev_open(), which is actually a bdev
layer requirement.

Change-Id: I2338e15c63f93ef37dd4412dd677dee40d272ec2
Signed-off-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/459166


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 4b60bd1b
Loading
Loading
Loading
Loading
+31 −20
Original line number Diff line number Diff line
@@ -985,6 +985,27 @@ static void foreach_session_continue(struct spdk_vhost_dev *vdev,
				     struct spdk_vhost_session *vsession,
				     spdk_vhost_session_fn fn, void *arg);

static void
foreach_session_finish_cb(void *arg1)
{
	struct spdk_vhost_session_fn_ctx *ctx = arg1;
	struct spdk_vhost_dev *vdev = ctx->vdev;

	if (pthread_mutex_trylock(&g_spdk_vhost_mutex) != 0) {
		spdk_thread_send_msg(spdk_get_thread(),
				     foreach_session_finish_cb, arg1);
		return;
	}

	assert(vdev->pending_async_op_num > 0);
	vdev->pending_async_op_num--;
	/* Call fn one last time with vsession == NULL */
	ctx->cb_fn(vdev, NULL, ctx->user_ctx);

	pthread_mutex_unlock(&g_spdk_vhost_mutex);
	free(ctx);
}

static void
foreach_session_continue_cb(void *arg1)
{
@@ -1040,11 +1061,7 @@ foreach_session_continue(struct spdk_vhost_dev *vdev,
	struct spdk_vhost_session_fn_ctx *ev_ctx;
	int rc;

	if (vsession == NULL) {
		goto out_finish_foreach;
	}

	while (!vsession->started) {
	while (vsession != NULL && !vsession->started) {
		if (vsession->initialized) {
			rc = fn(vdev, vsession, arg);
			if (rc < 0) {
@@ -1053,9 +1070,6 @@ foreach_session_continue(struct spdk_vhost_dev *vdev,
		}

		vsession = spdk_vhost_session_next(vdev, vsession->id);
		if (vsession == NULL) {
			goto out_finish_foreach;
		}
	}

	ev_ctx = calloc(1, sizeof(*ev_ctx));
@@ -1066,21 +1080,18 @@ foreach_session_continue(struct spdk_vhost_dev *vdev,
	}

	ev_ctx->vdev = vdev;
	ev_ctx->vsession_id = vsession->id;
	ev_ctx->cb_fn = fn;
	ev_ctx->user_ctx = arg;

	if (vsession != NULL) {
		ev_ctx->vsession_id = vsession->id;
		spdk_thread_send_msg(vsession->poll_group->thread,
				     foreach_session_continue_cb, ev_ctx);
	return;

out_finish_foreach:
	/* there are no more sessions to iterate through, so call the
	 * fn one last time with vsession == NULL
	 */
	assert(vdev->pending_async_op_num > 0);
	vdev->pending_async_op_num--;
	fn(vdev, NULL, arg);
	} else {
		ev_ctx->vsession_id = UINT32_MAX;
		spdk_thread_send_msg(g_vhost_init_thread,
				     foreach_session_finish_cb, ev_ctx);
	}
}

void