From: Eric Blake <eblake@redhat.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>,
"open list:Network Block Dev..." <qemu-block@nongnu.org>,
Max Reitz <mreitz@redhat.com>
Subject: [PULL 21/34] nbd/client-connection: add possibility of negotiation
Date: Tue, 15 Jun 2021 15:47:43 -0500 [thread overview]
Message-ID: <20210615204756.281505-22-eblake@redhat.com> (raw)
In-Reply-To: <20210615204756.281505-1-eblake@redhat.com>
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Add arguments and logic to support nbd negotiation in the same thread
after successful connection.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20210610100802.5888-20-vsementsov@virtuozzo.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
---
include/block/nbd.h | 9 +++-
block/nbd.c | 4 +-
nbd/client-connection.c | 105 ++++++++++++++++++++++++++++++++++++++--
3 files changed, 109 insertions(+), 9 deletions(-)
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 57381be76fc5..5d86e6a393ff 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -409,11 +409,16 @@ const char *nbd_err_lookup(int err);
/* nbd/client-connection.c */
typedef struct NBDClientConnection NBDClientConnection;
-NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr);
+NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr,
+ bool do_negotiation,
+ const char *export_name,
+ const char *x_dirty_bitmap,
+ QCryptoTLSCreds *tlscreds);
void nbd_client_connection_release(NBDClientConnection *conn);
QIOChannelSocket *coroutine_fn
-nbd_co_establish_connection(NBDClientConnection *conn, Error **errp);
+nbd_co_establish_connection(NBDClientConnection *conn, NBDExportInfo *info,
+ QIOChannel **ioc, Error **errp);
void coroutine_fn nbd_co_establish_connection_cancel(NBDClientConnection *conn);
diff --git a/block/nbd.c b/block/nbd.c
index 26914509f153..df9d241313f4 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -357,7 +357,7 @@ static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState *s)
s->ioc = NULL;
}
- s->sioc = nbd_co_establish_connection(s->conn, NULL);
+ s->sioc = nbd_co_establish_connection(s->conn, NULL, NULL, NULL);
if (!s->sioc) {
ret = -ECONNREFUSED;
goto out;
@@ -2035,7 +2035,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
- s->conn = nbd_client_connection_new(s->saddr);
+ s->conn = nbd_client_connection_new(s->saddr, false, NULL, NULL, NULL);
/*
* establish TCP connection, return error if it fails
diff --git a/nbd/client-connection.c b/nbd/client-connection.c
index eb5cae2eaea4..4ed37cd73fa1 100644
--- a/nbd/client-connection.c
+++ b/nbd/client-connection.c
@@ -30,8 +30,11 @@
#include "qapi/clone-visitor.h"
struct NBDClientConnection {
- /* Initialization constants */
+ /* Initialization constants, never change */
SocketAddress *saddr; /* address to connect to */
+ QCryptoTLSCreds *tlscreds;
+ NBDExportInfo initial_info;
+ bool do_negotiation;
QemuMutex mutex;
@@ -42,7 +45,9 @@ struct NBDClientConnection {
* nbd_co_establish_connection then steals these pointers while
* under the mutex.
*/
+ NBDExportInfo updated_info;
QIOChannelSocket *sioc;
+ QIOChannel *ioc;
Error *err;
/* All further fields are accessed only under mutex */
@@ -56,12 +61,25 @@ struct NBDClientConnection {
Coroutine *wait_co;
};
-NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr)
+NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr,
+ bool do_negotiation,
+ const char *export_name,
+ const char *x_dirty_bitmap,
+ QCryptoTLSCreds *tlscreds)
{
NBDClientConnection *conn = g_new(NBDClientConnection, 1);
+ object_ref(OBJECT(tlscreds));
*conn = (NBDClientConnection) {
.saddr = QAPI_CLONE(SocketAddress, saddr),
+ .tlscreds = tlscreds,
+ .do_negotiation = do_negotiation,
+
+ .initial_info.request_sizes = true,
+ .initial_info.structured_reply = true,
+ .initial_info.base_allocation = true,
+ .initial_info.x_dirty_bitmap = g_strdup(x_dirty_bitmap),
+ .initial_info.name = g_strdup(export_name ?: "")
};
qemu_mutex_init(&conn->mutex);
@@ -77,9 +95,61 @@ static void nbd_client_connection_do_free(NBDClientConnection *conn)
}
error_free(conn->err);
qapi_free_SocketAddress(conn->saddr);
+ object_unref(OBJECT(conn->tlscreds));
+ g_free(conn->initial_info.x_dirty_bitmap);
+ g_free(conn->initial_info.name);
g_free(conn);
}
+/*
+ * Connect to @addr and do NBD negotiation if @info is not null. If @tlscreds
+ * are given @outioc is returned. @outioc is provided only on success. The call
+ * may be cancelled from other thread by simply qio_channel_shutdown(sioc).
+ */
+static int nbd_connect(QIOChannelSocket *sioc, SocketAddress *addr,
+ NBDExportInfo *info, QCryptoTLSCreds *tlscreds,
+ QIOChannel **outioc, Error **errp)
+{
+ int ret;
+
+ if (outioc) {
+ *outioc = NULL;
+ }
+
+ ret = qio_channel_socket_connect_sync(sioc, addr, errp);
+ if (ret < 0) {
+ return ret;
+ }
+
+ qio_channel_set_delay(QIO_CHANNEL(sioc), false);
+
+ if (!info) {
+ return 0;
+ }
+
+ ret = nbd_receive_negotiate(NULL, QIO_CHANNEL(sioc), tlscreds,
+ tlscreds ? addr->u.inet.host : NULL,
+ outioc, info, errp);
+ if (ret < 0) {
+ /*
+ * nbd_receive_negotiate() may setup tls ioc and return it even on
+ * failure path. In this case we should use it instead of original
+ * channel.
+ */
+ if (outioc && *outioc) {
+ qio_channel_close(QIO_CHANNEL(*outioc), NULL);
+ object_unref(OBJECT(*outioc));
+ *outioc = NULL;
+ } else {
+ qio_channel_close(QIO_CHANNEL(sioc), NULL);
+ }
+
+ return ret;
+ }
+
+ return 0;
+}
+
static void *connect_thread_func(void *opaque)
{
NBDClientConnection *conn = opaque;
@@ -90,13 +160,18 @@ static void *connect_thread_func(void *opaque)
error_free(conn->err);
conn->err = NULL;
- ret = qio_channel_socket_connect_sync(conn->sioc, conn->saddr, &conn->err);
+ 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;
}
- qio_channel_set_delay(QIO_CHANNEL(conn->sioc), false);
+ conn->updated_info.x_dirty_bitmap = NULL;
+ conn->updated_info.name = NULL;
qemu_mutex_lock(&conn->mutex);
@@ -146,12 +221,24 @@ void nbd_client_connection_release(NBDClientConnection *conn)
* result, just return it now
* otherwise the thread is not running, so start a thread and wait for
* completion
+ *
+ * If @info is not NULL, also do nbd-negotiation after successful connection.
+ * In this case info is used only as out parameter, and is fully initialized by
+ * nbd_co_establish_connection(). "IN" fields of info as well as related only to
+ * nbd_receive_export_list() would be zero (see description of NBDExportInfo in
+ * include/block/nbd.h).
*/
QIOChannelSocket *coroutine_fn
-nbd_co_establish_connection(NBDClientConnection *conn, Error **errp)
+nbd_co_establish_connection(NBDClientConnection *conn, NBDExportInfo *info,
+ QIOChannel **ioc, Error **errp)
{
QemuThread thread;
+ if (conn->do_negotiation) {
+ assert(info);
+ assert(ioc);
+ }
+
WITH_QEMU_LOCK_GUARD(&conn->mutex) {
/*
* Don't call nbd_co_establish_connection() in several coroutines in
@@ -162,6 +249,10 @@ nbd_co_establish_connection(NBDClientConnection *conn, Error **errp)
if (!conn->running) {
if (conn->sioc) {
/* Previous attempt finally succeeded in background */
+ if (conn->do_negotiation) {
+ *ioc = g_steal_pointer(&conn->ioc);
+ memcpy(info, &conn->updated_info, sizeof(*info));
+ }
return g_steal_pointer(&conn->sioc);
}
@@ -194,6 +285,10 @@ nbd_co_establish_connection(NBDClientConnection *conn, Error **errp)
} else {
error_propagate(errp, conn->err);
conn->err = NULL;
+ if (conn->sioc && conn->do_negotiation) {
+ *ioc = g_steal_pointer(&conn->ioc);
+ memcpy(info, &conn->updated_info, sizeof(*info));
+ }
return g_steal_pointer(&conn->sioc);
}
}
--
2.31.1
next prev parent reply other threads:[~2021-06-15 21:07 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-15 20:47 [PULL 00/34] NBD patches for 2021-06-15 Eric Blake
2021-06-15 20:47 ` [PULL 01/34] async: the main AioContext is only "current" if under the BQL Eric Blake
2021-06-15 20:47 ` [PULL 02/34] tests: cover aio_co_enter from a worker thread without BQL taken Eric Blake
2021-06-15 20:47 ` [PULL 03/34] co-queue: drop extra coroutine_fn marks Eric Blake
2021-06-15 20:47 ` [PULL 04/34] block/nbd: fix channel object leak Eric Blake
2021-06-15 20:47 ` [PULL 05/34] block/nbd: fix how state is cleared on nbd_open() failure paths Eric Blake
2021-06-15 20:47 ` [PULL 06/34] block/nbd: connect_thread_func(): do qio_channel_set_delay(false) Eric Blake
2021-06-15 20:47 ` [PULL 07/34] qemu-sockets: introduce socket_address_parse_named_fd() Eric Blake
2021-06-15 20:47 ` [PULL 08/34] block/nbd: call socket_address_parse_named_fd() in advance Eric Blake
2021-06-15 20:47 ` [PULL 09/34] block/nbd: ensure ->connection_thread is always valid Eric Blake
2021-06-15 20:47 ` [PULL 10/34] block/nbd: nbd_client_handshake(): fix leak of s->ioc Eric Blake
2021-06-15 20:47 ` [PULL 11/34] block/nbd: BDRVNBDState: drop unused connect_err and connect_status Eric Blake
2021-06-15 20:47 ` [PULL 12/34] block/nbd: simplify waking of nbd_co_establish_connection() Eric Blake
2021-06-15 20:47 ` [PULL 13/34] block/nbd: drop thr->state Eric Blake
2021-06-15 20:47 ` [PULL 14/34] block/nbd: bs-independent interface for nbd_co_establish_connection() Eric Blake
2021-06-15 20:47 ` [PULL 15/34] block/nbd: make nbd_co_establish_connection_cancel() bs-independent Eric Blake
2021-06-15 20:47 ` [PULL 16/34] block/nbd: rename NBDConnectThread to NBDClientConnection Eric Blake
2021-06-15 20:47 ` [PULL 17/34] block/nbd: introduce nbd_client_connection_new() Eric Blake
2021-06-15 20:47 ` [PULL 18/34] block/nbd: introduce nbd_client_connection_release() Eric Blake
2021-06-15 20:47 ` [PULL 19/34] nbd: move connection code from block/nbd to nbd/client-connection Eric Blake
2021-06-15 20:47 ` [PULL 20/34] nbd/client-connection: use QEMU_LOCK_GUARD Eric Blake
2021-06-15 20:47 ` Eric Blake [this message]
2021-06-15 20:47 ` [PULL 22/34] nbd/client-connection: implement connection retry Eric Blake
2021-06-15 20:47 ` [PULL 23/34] nbd/client-connection: shutdown connection on release Eric Blake
2021-06-15 20:47 ` [PULL 24/34] block/nbd: split nbd_handle_updated_info out of nbd_client_handshake() Eric Blake
2021-06-15 20:47 ` [PULL 25/34] block/nbd: use negotiation of NBDClientConnection Eric Blake
2021-06-15 20:47 ` [PULL 26/34] block/nbd: don't touch s->sioc in nbd_teardown_connection() Eric Blake
2021-06-15 20:47 ` [PULL 27/34] block/nbd: drop BDRVNBDState::sioc Eric Blake
2021-06-15 20:47 ` [PULL 28/34] nbd/client-connection: return only one io channel Eric Blake
2021-06-17 18:32 ` Vladimir Sementsov-Ogievskiy
2021-06-18 15:55 ` Eric Blake
2021-06-15 20:47 ` [PULL 29/34] block-coroutine-wrapper: allow non bdrv_ prefix Eric Blake
2021-06-15 20:47 ` [PULL 30/34] block/nbd: split nbd_co_do_establish_connection out of nbd_reconnect_attempt Eric Blake
2021-06-15 20:47 ` [PULL 31/34] nbd/client-connection: add option for non-blocking connection attempt Eric Blake
2021-06-15 20:47 ` [PULL 32/34] block/nbd: reuse nbd_co_do_establish_connection() in nbd_open() Eric Blake
2021-06-15 20:47 ` [PULL 33/34] block/nbd: add nbd_client_connected() helper Eric Blake
2021-06-15 20:47 ` [PULL 34/34] block/nbd: safer transition to receiving request Eric Blake
2021-06-17 9:42 ` [PULL 00/34] NBD patches for 2021-06-15 Peter Maydell
2021-06-17 18:35 ` Vladimir Sementsov-Ogievskiy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210615204756.281505-22-eblake@redhat.com \
--to=eblake@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=vsementsov@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).