diff options
author | Vladimir Sementsov-Ogievskiy | 2021-06-10 12:07:42 +0200 |
---|---|---|
committer | Eric Blake | 2021-06-18 17:59:53 +0200 |
commit | d33833d7af73641d26b836a40f0bc697b656859b (patch) | |
tree | 80b9ad2f223944b281b7a1b8c778cb8845c12a7a /block | |
parent | block/nbd: drop thr->state (diff) | |
download | qemu-d33833d7af73641d26b836a40f0bc697b656859b.tar.gz qemu-d33833d7af73641d26b836a40f0bc697b656859b.tar.xz qemu-d33833d7af73641d26b836a40f0bc697b656859b.zip |
block/nbd: bs-independent interface for nbd_co_establish_connection()
We are going to split connection code to a separate file. Now we are
ready to give nbd_co_establish_connection() clean and bs-independent
interface.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Roman Kagan <rvkagan@yandex-team.ru>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20210610100802.5888-13-vsementsov@virtuozzo.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/nbd.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/block/nbd.c b/block/nbd.c index f2d5b47026..15b569a899 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -130,7 +130,8 @@ typedef struct BDRVNBDState { static void nbd_free_connect_thread(NBDConnectThread *thr); static int nbd_establish_connection(BlockDriverState *bs, SocketAddress *saddr, Error **errp); -static int nbd_co_establish_connection(BlockDriverState *bs, Error **errp); +static coroutine_fn QIOChannelSocket * +nbd_co_establish_connection(NBDConnectThread *thr, Error **errp); static void nbd_co_establish_connection_cancel(BlockDriverState *bs); static int nbd_client_handshake(BlockDriverState *bs, Error **errp); static void nbd_yank(void *opaque); @@ -416,22 +417,37 @@ static void *connect_thread_func(void *opaque) return NULL; } -static int coroutine_fn -nbd_co_establish_connection(BlockDriverState *bs, Error **errp) +/* + * Get a new connection in context of @thr: + * if the thread is running, wait for completion + * if the thread already succeeded in the background, and user didn't get the + * result, just return it now + * otherwise the thread is not running, so start a thread and wait for + * completion + */ +static coroutine_fn QIOChannelSocket * +nbd_co_establish_connection(NBDConnectThread *thr, Error **errp) { + QIOChannelSocket *sioc = NULL; QemuThread thread; - BDRVNBDState *s = bs->opaque; - NBDConnectThread *thr = s->connect_thread; - - assert(!s->sioc); qemu_mutex_lock(&thr->mutex); + /* + * Don't call nbd_co_establish_connection() in several coroutines in + * parallel. Only one call at once is supported. + */ + assert(!thr->wait_co); + if (!thr->running) { if (thr->sioc) { /* Previous attempt finally succeeded in background */ - goto out; + sioc = g_steal_pointer(&thr->sioc); + qemu_mutex_unlock(&thr->mutex); + + return sioc; } + thr->running = true; error_free(thr->err); thr->err = NULL; @@ -445,13 +461,12 @@ nbd_co_establish_connection(BlockDriverState *bs, Error **errp) /* * We are going to wait for connect-thread finish, but - * nbd_client_co_drain_begin() can interrupt. + * nbd_co_establish_connection_cancel() can interrupt. */ qemu_coroutine_yield(); qemu_mutex_lock(&thr->mutex); -out: if (thr->running) { /* * The connection attempt was canceled and the coroutine resumed @@ -463,17 +478,12 @@ out: } else { error_propagate(errp, thr->err); thr->err = NULL; - s->sioc = thr->sioc; - thr->sioc = NULL; - if (s->sioc) { - yank_register_function(BLOCKDEV_YANK_INSTANCE(bs->node_name), - nbd_yank, bs); - } + sioc = g_steal_pointer(&thr->sioc); } qemu_mutex_unlock(&thr->mutex); - return s->sioc ? 0 : -1; + return sioc; } /* @@ -541,11 +551,15 @@ static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState *s) s->ioc = NULL; } - if (nbd_co_establish_connection(s->bs, NULL) < 0) { + s->sioc = nbd_co_establish_connection(s->connect_thread, NULL); + if (!s->sioc) { ret = -ECONNREFUSED; goto out; } + yank_register_function(BLOCKDEV_YANK_INSTANCE(s->bs->node_name), nbd_yank, + s->bs); + bdrv_dec_in_flight(s->bs); ret = nbd_client_handshake(s->bs, NULL); |