diff options
author | Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 2021-06-10 13:07:50 +0300 |
---|---|---|
committer | Eric Blake <eblake@redhat.com> | 2021-06-18 10:59:53 -0500 |
commit | e0e67cbe58f42500e3451c46b3caba572f2a965f (patch) | |
tree | adc32dfa370ad235d0318fad2571c8bc6829aa55 /nbd/client-connection.c | |
parent | 130d49baa50655729f09efb72e77bebf09421dd7 (diff) | |
download | qemu-e0e67cbe58f42500e3451c46b3caba572f2a965f.zip |
nbd/client-connection: implement connection retry
Add an option for a thread to retry connecting until it succeeds. We'll
use nbd/client-connection both for reconnect and for initial connection
in nbd_open(), so we need a possibility to use same NBDClientConnection
instance to connect once in nbd_open() and then use retry semantics for
reconnect.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20210610100802.5888-21-vsementsov@virtuozzo.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[eblake: grammar tweak]
Signed-off-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'nbd/client-connection.c')
-rw-r--r-- | nbd/client-connection.c | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/nbd/client-connection.c b/nbd/client-connection.c index 4ed37cd73f..032b38ed3e 100644 --- a/nbd/client-connection.c +++ b/nbd/client-connection.c @@ -35,6 +35,7 @@ struct NBDClientConnection { QCryptoTLSCreds *tlscreds; NBDExportInfo initial_info; bool do_negotiation; + bool do_retry; QemuMutex mutex; @@ -61,6 +62,15 @@ struct NBDClientConnection { Coroutine *wait_co; }; +/* + * The function isn't protected by any mutex, only call it when the client + * connection attempt has not yet started. + */ +void nbd_client_connection_enable_retry(NBDClientConnection *conn) +{ + conn->do_retry = true; +} + NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr, bool do_negotiation, const char *export_name, @@ -155,23 +165,43 @@ static void *connect_thread_func(void *opaque) NBDClientConnection *conn = opaque; int ret; bool do_free; + uint64_t timeout = 1; + uint64_t max_timeout = 16; - conn->sioc = qio_channel_socket_new(); + while (true) { + conn->sioc = qio_channel_socket_new(); - error_free(conn->err); - conn->err = NULL; - conn->updated_info = conn->initial_info; + error_free(conn->err); + conn->err = NULL; + conn->updated_info = conn->initial_info; - ret = nbd_connect(conn->sioc, conn->saddr, - conn->do_negotiation ? &conn->updated_info : NULL, - conn->tlscreds, &conn->ioc, &conn->err); - if (ret < 0) { - object_unref(OBJECT(conn->sioc)); - conn->sioc = NULL; - } + ret = nbd_connect(conn->sioc, conn->saddr, + conn->do_negotiation ? &conn->updated_info : NULL, + conn->tlscreds, &conn->ioc, &conn->err); + + /* + * conn->updated_info will finally be returned to the user. Clear the + * pointers to our internally allocated strings, which are IN parameters + * of nbd_receive_negotiate() and therefore nbd_connect(). Caller + * shoudn't be interested in these fields. + */ + conn->updated_info.x_dirty_bitmap = NULL; + conn->updated_info.name = NULL; + + if (ret < 0) { + object_unref(OBJECT(conn->sioc)); + conn->sioc = NULL; + if (conn->do_retry) { + sleep(timeout); + if (timeout < max_timeout) { + timeout *= 2; + } + continue; + } + } - conn->updated_info.x_dirty_bitmap = NULL; - conn->updated_info.name = NULL; + break; + } qemu_mutex_lock(&conn->mutex); |