From 3fb1a9565ec2ed2513fedffc8c2f29118f17763e Mon Sep 17 00:00:00 2001 From: Darek Stojaczyk Date: Mon, 24 Jun 2019 16:07:53 +0200 Subject: [PATCH] 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: Darek Stojaczyk Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/459166 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Shuhei Matsumoto --- lib/vhost/vhost.c | 51 ++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index b6c5d5576..98caa8b2d 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -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; - 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); + if (vsession != NULL) { + ev_ctx->vsession_id = vsession->id; + spdk_thread_send_msg(vsession->poll_group->thread, + foreach_session_continue_cb, ev_ctx); + } else { + ev_ctx->vsession_id = UINT32_MAX; + spdk_thread_send_msg(g_vhost_init_thread, + foreach_session_finish_cb, ev_ctx); + } } void