On Wed, Apr 07, 2021 at 01:46:29PM +0300, Vladimir Sementsov-Ogievskiy wrote: > Add personal state NBDConnectThread for connect-thread and > nbd_connect_thread_start() function. Next step would be moving > connect-thread to a separate file. > > Note that we stop publishing thr->sioc during > qio_channel_socket_connect_sync(). Which probably means that we can't > early-cancel qio_channel_socket_connect_sync() call in > nbd_free_connect_thread(). Still, when thread is detached it doesn't > make big sense, and we have no guarantee anyway. > > Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> > --- > block/nbd.c | 57 ++++++++++++++++++++++++++++++++++++----------------- > 1 file changed, 39 insertions(+), 18 deletions(-) > > diff --git a/block/nbd.c b/block/nbd.c > index e16c6d636a..23eb8adab1 100644 > --- a/block/nbd.c > +++ b/block/nbd.c > @@ -85,8 +85,6 @@ typedef enum NBDConnectThreadState { > } NBDConnectThreadState; > > typedef struct NBDConnectCB { > - /* Initialization constants */ > - SocketAddress *saddr; /* address to connect to */ > /* > * Bottom half to schedule on completion. Scheduled only if bh_ctx is not > * NULL > @@ -103,6 +101,15 @@ typedef struct NBDConnectCB { > AioContext *bh_ctx; /* where to schedule bh (NULL means don't schedule) > */ > } NBDConnectCB; > > +typedef void (*NBDConnectThreadCallback)(QIOChannelSocket *sioc, int ret, > + void *opaque); > + > +typedef struct NBDConnectThread { > + SocketAddress *saddr; /* address to connect to */ > + NBDConnectThreadCallback cb; > + void *cb_opaque; > +} NBDConnectThread; > + > typedef struct BDRVNBDState { > QIOChannelSocket *sioc; /* The master data channel */ > QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */ > @@ -367,7 +374,6 @@ static void nbd_init_connect_thread(BDRVNBDState *s) > s->connect_thread = g_new(NBDConnectCB, 1); > > *s->connect_thread = (NBDConnectCB) { > - .saddr = QAPI_CLONE(SocketAddress, s->saddr), > .state = CONNECT_THREAD_NONE, > .bh_func = connect_bh, > .bh_opaque = s, > @@ -378,20 +384,18 @@ static void nbd_init_connect_thread(BDRVNBDState *s) > > static void nbd_free_connect_thread(NBDConnectCB *thr) > { > - if (thr->sioc) { > - qio_channel_close(QIO_CHANNEL(thr->sioc), NULL); > - }
Doesn't this result in an open channel leak? (The original code here seems to be missing an unref, too.) > - qapi_free_SocketAddress(thr->saddr); > g_free(thr); > } > > -static void connect_thread_cb(int ret, void *opaque) > +static void connect_thread_cb(QIOChannelSocket *sioc, int ret, void *opaque) > { > NBDConnectCB *thr = opaque; > bool do_free = false; > > qemu_mutex_lock(&thr->mutex); > > + thr->sioc = sioc; > + > switch (thr->state) { > case CONNECT_THREAD_RUNNING: > thr->state = ret < 0 ? CONNECT_THREAD_FAIL : CONNECT_THREAD_SUCCESS; > @@ -418,27 +422,45 @@ static void connect_thread_cb(int ret, void *opaque) > > static void *connect_thread_func(void *opaque) > { > - NBDConnectCB *thr = opaque; > + NBDConnectThread *thr = opaque; > int ret; > + QIOChannelSocket *sioc = qio_channel_socket_new(); > > - thr->sioc = qio_channel_socket_new(); > - > - ret = qio_channel_socket_connect_sync(thr->sioc, thr->saddr, NULL); > + ret = qio_channel_socket_connect_sync(sioc, thr->saddr, NULL); > if (ret < 0) { > - object_unref(OBJECT(thr->sioc)); > - thr->sioc = NULL; > + object_unref(OBJECT(sioc)); > + sioc = NULL; > } > > - connect_thread_cb(ret, thr); > + thr->cb(sioc, ret, thr->cb_opaque); > + > + qapi_free_SocketAddress(thr->saddr); > + g_free(thr); > > return NULL; > } > > +static void nbd_connect_thread_start(const SocketAddress *saddr, > + NBDConnectThreadCallback cb, > + void *cb_opaque) > +{ > + QemuThread thread; > + NBDConnectThread *thr = g_new(NBDConnectThread, 1); > + > + *thr = (NBDConnectThread) { > + .saddr = QAPI_CLONE(SocketAddress, saddr), > + .cb = cb, > + .cb_opaque = cb_opaque, > + }; > + > + qemu_thread_create(&thread, "nbd-connect", > + connect_thread_func, thr, QEMU_THREAD_DETACHED); > +} > + > static int coroutine_fn > nbd_co_establish_connection(BlockDriverState *bs) > { > int ret; > - QemuThread thread; > BDRVNBDState *s = bs->opaque; > NBDConnectCB *thr = s->connect_thread; > > @@ -448,8 +470,7 @@ nbd_co_establish_connection(BlockDriverState *bs) > case CONNECT_THREAD_FAIL: > case CONNECT_THREAD_NONE: > thr->state = CONNECT_THREAD_RUNNING; > - qemu_thread_create(&thread, "nbd-connect", > - connect_thread_func, thr, QEMU_THREAD_DETACHED); > + nbd_connect_thread_start(s->saddr, connect_thread_cb, thr); > break; > case CONNECT_THREAD_SUCCESS: > /* Previous attempt finally succeeded in background */ > -- > 2.29.2 >