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 <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/459166
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Darek Stojaczyk 2019-06-24 16:07:53 +02:00
parent 4b60bd1b59
commit 3fb1a9565e

View File

@ -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