All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
To: qemu-block@nongnu.org
Cc: qemu-devel@nongnu.org, vsementsov@virtuozzo.com,
	eblake@redhat.com, mreitz@redhat.com, kwolf@redhat.com,
	rvkagan@yandex-team.ru, den@openvz.org
Subject: [PATCH v3 16/33] nbd/client-connection: add possibility of negotiation
Date: Fri, 16 Apr 2021 11:08:54 +0300	[thread overview]
Message-ID: <20210416080911.83197-17-vsementsov@virtuozzo.com> (raw)
In-Reply-To: <20210416080911.83197-1-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>
---
 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 57381be76f..5d86e6a393 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 9bd68dcf10..5e63caaf4b 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -361,7 +361,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;
@@ -2033,7 +2033,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 b45a0bd5f6..ae4a77f826 100644
--- a/nbd/client-connection.c
+++ b/nbd/client-connection.c
@@ -30,14 +30,19 @@
 #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;
 
     /*
      * Result of last attempt. Valid in FAIL and SUCCESS states.
      * If you want to steal error, don't forget to set pointer to NULL.
      */
+    NBDExportInfo updated_info;
     QIOChannelSocket *sioc;
+    QIOChannel *ioc;
     Error *err;
 
     QemuMutex mutex;
@@ -47,12 +52,25 @@ struct NBDClientConnection {
     Coroutine *wait_co; /* nbd_co_establish_connection() wait in yield() */
 };
 
-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);
@@ -68,9 +86,59 @@ 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
+ * given @outioc is provided. @outioc is provided only on success.  The call may
+ * be cancelled in parallel 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;
+    }
+
+    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;
@@ -81,12 +149,19 @@ 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;
     }
 
+    conn->updated_info.x_dirty_bitmap = NULL;
+    conn->updated_info.name = NULL;
+
     WITH_QEMU_LOCK_GUARD(&conn->mutex) {
         assert(conn->running);
         conn->running = false;
@@ -94,8 +169,8 @@ static void *connect_thread_func(void *opaque)
             aio_co_schedule(NULL, conn->wait_co);
             conn->wait_co = NULL;
         }
+        do_free = conn->detached;
     }
-    do_free = conn->detached;
 
 
     if (do_free) {
@@ -131,12 +206,24 @@ void nbd_client_connection_release(NBDClientConnection *conn)
  *   if thread is already succeeded in background, and user didn't get the
  *     result, just return it now
  *   otherwise if thread is not running, 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
@@ -147,6 +234,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);
             }
 
@@ -178,6 +269,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.29.2



  parent reply	other threads:[~2021-04-16  8:31 UTC|newest]

Thread overview: 121+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-16  8:08 [PATCH v3 00/33] block/nbd: rework client connection Vladimir Sementsov-Ogievskiy
2021-04-16  8:08 ` [PATCH v3 01/33] block/nbd: fix channel object leak Vladimir Sementsov-Ogievskiy
2021-05-24 21:31   ` Eric Blake
2021-05-25  4:47     ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:08 ` [PATCH v3 02/33] block/nbd: fix how state is cleared on nbd_open() failure paths Vladimir Sementsov-Ogievskiy
2021-04-21 14:00   ` Roman Kagan
2021-04-21 22:27     ` Vladimir Sementsov-Ogievskiy
2021-04-22  8:49       ` Roman Kagan
2021-06-01 21:39   ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 03/33] block/nbd: ensure ->connection_thread is always valid Vladimir Sementsov-Ogievskiy
2021-06-01 21:41   ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 04/33] block/nbd: nbd_client_handshake(): fix leak of s->ioc Vladimir Sementsov-Ogievskiy
2021-04-22  8:59   ` Roman Kagan
2021-04-16  8:08 ` [PATCH v3 05/33] block/nbd: BDRVNBDState: drop unused connect_err and connect_status Vladimir Sementsov-Ogievskiy
2021-06-01 21:43   ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 06/33] util/async: aio_co_schedule(): support reschedule in same ctx Vladimir Sementsov-Ogievskiy
2021-04-23 10:09   ` Roman Kagan
2021-04-26  8:52     ` Vladimir Sementsov-Ogievskiy
2021-05-12  6:56   ` Paolo Bonzini
2021-05-12  7:15     ` Vladimir Sementsov-Ogievskiy
2021-05-13 21:04       ` Paolo Bonzini
2021-05-14 17:27         ` Roman Kagan
2021-05-14 21:19           ` Paolo Bonzini
2021-06-08 18:45         ` Vladimir Sementsov-Ogievskiy
2021-06-09  9:35           ` Paolo Bonzini
2021-06-09 10:24             ` Vladimir Sementsov-Ogievskiy
2021-06-09 12:17               ` Paolo Bonzini
2021-04-16  8:08 ` [PATCH v3 07/33] block/nbd: simplify waking of nbd_co_establish_connection() Vladimir Sementsov-Ogievskiy
2021-04-27 21:44   ` Roman Kagan
2021-06-02 19:05   ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 08/33] block/nbd: drop thr->state Vladimir Sementsov-Ogievskiy
2021-04-27 22:23   ` Roman Kagan
2021-04-28  8:01     ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:08 ` [PATCH v3 09/33] block/nbd: bs-independent interface for nbd_co_establish_connection() Vladimir Sementsov-Ogievskiy
2021-06-02 19:14   ` Eric Blake
2021-06-08 10:12     ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:08 ` [PATCH v3 10/33] block/nbd: make nbd_co_establish_connection_cancel() bs-independent Vladimir Sementsov-Ogievskiy
2021-06-02 21:18   ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 11/33] block/nbd: rename NBDConnectThread to NBDClientConnection Vladimir Sementsov-Ogievskiy
2021-04-27 22:28   ` Roman Kagan
2021-06-02 21:21   ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 12/33] block/nbd: introduce nbd_client_connection_new() Vladimir Sementsov-Ogievskiy
2021-06-02 21:22   ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 13/33] block/nbd: introduce nbd_client_connection_release() Vladimir Sementsov-Ogievskiy
2021-04-27 22:35   ` Roman Kagan
2021-04-28  8:06     ` Vladimir Sementsov-Ogievskiy
2021-06-02 21:27   ` Eric Blake
2021-06-03 11:59     ` Vladimir Sementsov-Ogievskiy
2021-06-08 10:00     ` Vladimir Sementsov-Ogievskiy
2021-06-08 14:18       ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 14/33] nbd: move connection code from block/nbd to nbd/client-connection Vladimir Sementsov-Ogievskiy
2021-04-27 22:45   ` Roman Kagan
2021-04-28  8:14     ` Vladimir Sementsov-Ogievskiy
2021-06-09 15:49       ` Vladimir Sementsov-Ogievskiy
2021-06-03 15:55   ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 15/33] nbd/client-connection: use QEMU_LOCK_GUARD Vladimir Sementsov-Ogievskiy
2021-04-28  6:08   ` Roman Kagan
2021-04-28  8:17     ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:08 ` Vladimir Sementsov-Ogievskiy [this message]
2021-05-11 10:45   ` [PATCH v3 16/33] nbd/client-connection: add possibility of negotiation Roman Kagan
2021-05-12  6:42     ` Vladimir Sementsov-Ogievskiy
2021-06-08 19:23       ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:08 ` [PATCH v3 17/33] nbd/client-connection: implement connection retry Vladimir Sementsov-Ogievskiy
2021-05-11 20:54   ` Roman Kagan
2021-06-08 10:24     ` Vladimir Sementsov-Ogievskiy
2021-06-03 16:17   ` Eric Blake
2021-06-03 17:49     ` Vladimir Sementsov-Ogievskiy
2021-06-08 10:38       ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:08 ` [PATCH v3 18/33] nbd/client-connection: shutdown connection on release Vladimir Sementsov-Ogievskiy
2021-05-11 21:08   ` Roman Kagan
2021-05-12  6:39     ` Vladimir Sementsov-Ogievskiy
2021-06-03 16:20   ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 19/33] block/nbd: split nbd_handle_updated_info out of nbd_client_handshake() Vladimir Sementsov-Ogievskiy
2021-05-12  8:40   ` Roman Kagan
2021-06-03 16:29   ` Eric Blake
2021-06-09 17:23     ` Vladimir Sementsov-Ogievskiy
2021-06-09 18:28       ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 20/33] block/nbd: use negotiation of NBDClientConnection Vladimir Sementsov-Ogievskiy
2021-06-03 18:05   ` Eric Blake
2021-04-16  8:08 ` [PATCH v3 21/33] qemu-socket: pass monitor link to socket_get_fd directly Vladimir Sementsov-Ogievskiy
2021-04-19  9:34   ` Daniel P. Berrangé
2021-04-19 10:09     ` Vladimir Sementsov-Ogievskiy
2021-05-12  9:40     ` Roman Kagan
2021-05-12  9:59       ` Daniel P. Berrangé
2021-05-13 11:02         ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:09 ` [PATCH v3 22/33] block/nbd: pass monitor directly to connection thread Vladimir Sementsov-Ogievskiy
2021-06-03 18:16   ` Eric Blake
2021-06-03 18:31     ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:09 ` [PATCH v3 23/33] block/nbd: nbd_teardown_connection() don't touch s->sioc Vladimir Sementsov-Ogievskiy
2021-06-03 19:04   ` Eric Blake
2021-04-16  8:09 ` [PATCH v3 24/33] block/nbd: drop BDRVNBDState::sioc Vladimir Sementsov-Ogievskiy
2021-06-03 19:12   ` Eric Blake
2021-04-16  8:09 ` [PATCH v3 25/33] nbd/client-connection: return only one io channel Vladimir Sementsov-Ogievskiy
2021-06-03 19:58   ` Eric Blake
2021-04-16  8:09 ` [PATCH v3 26/33] block-coroutine-wrapper: allow non bdrv_ prefix Vladimir Sementsov-Ogievskiy
2021-06-03 20:00   ` Eric Blake
2021-06-03 20:53   ` Eric Blake
2021-06-04  5:29     ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:09 ` [PATCH v3 27/33] block/nbd: split nbd_co_do_establish_connection out of nbd_reconnect_attempt Vladimir Sementsov-Ogievskiy
2021-06-03 20:04   ` Eric Blake
2021-06-04  5:30     ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:09 ` [PATCH v3 28/33] nbd/client-connection: do qio_channel_set_delay(false) Vladimir Sementsov-Ogievskiy
2021-06-03 20:48   ` Eric Blake
2021-06-04  5:32     ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:09 ` [PATCH v3 29/33] nbd/client-connection: add option for non-blocking connection attempt Vladimir Sementsov-Ogievskiy
2021-06-03 20:51   ` Eric Blake
2021-04-16  8:09 ` [PATCH v3 30/33] block/nbd: reuse nbd_co_do_establish_connection() in nbd_open() Vladimir Sementsov-Ogievskiy
2021-06-03 20:57   ` Eric Blake
2021-04-16  8:09 ` [PATCH v3 31/33] block/nbd: add nbd_clinent_connected() helper Vladimir Sementsov-Ogievskiy
2021-05-12  7:06   ` Paolo Bonzini
2021-05-12  7:19     ` Vladimir Sementsov-Ogievskiy
2021-06-03 21:08   ` Eric Blake
2021-04-16  8:09 ` [PATCH v3 32/33] block/nbd: safer transition to receiving request Vladimir Sementsov-Ogievskiy
2021-06-03 21:11   ` Eric Blake
2021-06-04  5:36     ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:09 ` [PATCH v3 33/33] block/nbd: drop connection_co Vladimir Sementsov-Ogievskiy
2021-04-16  8:14   ` Vladimir Sementsov-Ogievskiy
2021-04-16  8:21     ` Vladimir Sementsov-Ogievskiy
2021-06-03 21:27   ` Eric Blake
2021-06-04  5:39     ` Vladimir Sementsov-Ogievskiy
2021-05-12  6:54 ` [PATCH v3 00/33] block/nbd: rework client connection Paolo Bonzini

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=20210416080911.83197-17-vsementsov@virtuozzo.com \
    --to=vsementsov@virtuozzo.com \
    --cc=den@openvz.org \
    --cc=eblake@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=rvkagan@yandex-team.ru \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.