All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/6] NBD server refactoring before BLOCK_STATUS
@ 2018-01-10 23:08 Eric Blake
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 1/6] nbd/server: Hoist nbd_reject_length() earlier Eric Blake
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Eric Blake @ 2018-01-10 23:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, vsementsov

This is my promised revision of Vladimir's v1 posted here:
https://lists.gnu.org/archive/html/qemu-devel/2017-11/msg04119.html

Sorry for my delay; it was due in part to an embargo while dealing
with 2 bounds-check CVEs in the NBD code that I discovered while
reviewing his v1 (fixed in time for 2.11), then waiting for the
2.12 tree to reopen, coupled with my holiday break.  I'm hoping
we can get actual BLOCK_STATUS code reviewed and applied much
faster than this preliminary series has gone.

Based-on: <20180110225944.17920-1-eblake@redhat.com>

Since v1:
- original patch 4/5 now in a pull request
- replace original 2-3/5 with a single patch, giving more useful
semantics to nbd_opt_drop/nbd_opt_read
- add a couple of other easy fixes while touching the file

Eric Blake (4):
  nbd/server: Hoist nbd_reject_length() earlier
  nbd/server: Better error for NBD_OPT_EXPORT_NAME failure
  nbd/server: Add va_list form of nbd_negotiate_send_rep_err()
  nbd/server: Add helper functions for parsing option payload

Vladimir Sementsov-Ogievskiy (2):
  nbd/server: refactor negotiation functions parameters
  nbd/server: structurize option reply sending

 nbd/server.c | 341 ++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 171 insertions(+), 170 deletions(-)

-- 
2.14.3

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v2 1/6] nbd/server: Hoist nbd_reject_length() earlier
  2018-01-10 23:08 [Qemu-devel] [PATCH v2 0/6] NBD server refactoring before BLOCK_STATUS Eric Blake
@ 2018-01-10 23:08 ` Eric Blake
  2018-01-11 17:31   ` Vladimir Sementsov-Ogievskiy
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 2/6] nbd/server: refactor negotiation functions parameters Eric Blake
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Eric Blake @ 2018-01-10 23:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, vsementsov, Paolo Bonzini

No semantic change, but will make it easier for an upcoming patch
to refactor code without having to add forward declarations.

Signed-off-by: Eric Blake <eblake@redhat.com>
---
 nbd/server.c | 56 ++++++++++++++++++++++++++++----------------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index 6cf2eeb2c1..d3b457c337 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -348,6 +348,34 @@ static int nbd_negotiate_send_info(NBDClient *client, uint32_t opt,
     return 0;
 }

+/* nbd_reject_length: Handle any unexpected payload.
+ * @fatal requests that we quit talking to the client, even if we are able
+ * to successfully send an error to the guest.
+ * Return:
+ * -errno  transmission error occurred or @fatal was requested, errp is set
+ * 0       error message successfully sent to client, errp is not set
+ */
+static int nbd_reject_length(NBDClient *client, uint32_t length,
+                             uint32_t option, bool fatal, Error **errp)
+{
+    int ret;
+
+    assert(length);
+    if (nbd_drop(client->ioc, length, errp) < 0) {
+        return -EIO;
+    }
+    ret = nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_INVALID,
+                                     option, errp,
+                                     "option '%s' should have zero length",
+                                     nbd_opt_lookup(option));
+    if (fatal && !ret) {
+        error_setg(errp, "option '%s' should have zero length",
+                   nbd_opt_lookup(option));
+        return -EINVAL;
+    }
+    return ret;
+}
+
 /* Handle NBD_OPT_INFO and NBD_OPT_GO.
  * Return -errno on error, 0 if ready for next option, and 1 to move
  * into transmission phase.  */
@@ -570,34 +598,6 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
     return QIO_CHANNEL(tioc);
 }

-/* nbd_reject_length: Handle any unexpected payload.
- * @fatal requests that we quit talking to the client, even if we are able
- * to successfully send an error to the guest.
- * Return:
- * -errno  transmission error occurred or @fatal was requested, errp is set
- * 0       error message successfully sent to client, errp is not set
- */
-static int nbd_reject_length(NBDClient *client, uint32_t length,
-                             uint32_t option, bool fatal, Error **errp)
-{
-    int ret;
-
-    assert(length);
-    if (nbd_drop(client->ioc, length, errp) < 0) {
-        return -EIO;
-    }
-    ret = nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_INVALID,
-                                     option, errp,
-                                     "option '%s' should have zero length",
-                                     nbd_opt_lookup(option));
-    if (fatal && !ret) {
-        error_setg(errp, "option '%s' should have zero length",
-                   nbd_opt_lookup(option));
-        return -EINVAL;
-    }
-    return ret;
-}
-
 /* nbd_negotiate_options
  * Process all NBD_OPT_* client option commands, during fixed newstyle
  * negotiation.
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v2 2/6] nbd/server: refactor negotiation functions parameters
  2018-01-10 23:08 [Qemu-devel] [PATCH v2 0/6] NBD server refactoring before BLOCK_STATUS Eric Blake
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 1/6] nbd/server: Hoist nbd_reject_length() earlier Eric Blake
@ 2018-01-10 23:08 ` Eric Blake
  2018-01-11 17:55   ` Vladimir Sementsov-Ogievskiy
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 3/6] nbd/server: Better error for NBD_OPT_EXPORT_NAME failure Eric Blake
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Eric Blake @ 2018-01-10 23:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, vsementsov, Paolo Bonzini

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

Instead of passing currently negotiating option and its length to
many of negotiation functions let's just store them on NBDClient
struct to be state-variables of negotiation phase.

This unifies semantics of negotiation functions and allows
tracking changes of remaining option length in future patches.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20171122101958.17065-2-vsementsov@virtuozzo.com>
[eblake: rebase, commit message tweak, assert !optlen after
negotiation completes]
Signed-off-by: Eric Blake <eblake@redhat.com>
---
 nbd/server.c | 168 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 84 insertions(+), 84 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index d3b457c337..08a24b56f4 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -102,9 +102,11 @@ struct NBDClient {
     bool closing;

     bool structured_reply;
-};

-/* That's all folks */
+    uint32_t opt; /* Current option being negotiated */
+    uint32_t optlen; /* remaining length of data in ioc for the option being
+                        negotiated now */
+};

 static void nbd_client_receive_next_request(NBDClient *client);

@@ -137,10 +139,12 @@ static void nbd_client_receive_next_request(NBDClient *client);

 /* Send a reply header, including length, but no payload.
  * Return -errno on error, 0 on success. */
-static int nbd_negotiate_send_rep_len(QIOChannel *ioc, uint32_t type,
-                                      uint32_t opt, uint32_t len, Error **errp)
+static int nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type,
+                                      uint32_t len, Error **errp)
 {
     uint64_t magic;
+    QIOChannel *ioc = client->ioc;
+    uint32_t opt = client->opt;

     trace_nbd_negotiate_send_rep_len(opt, nbd_opt_lookup(opt),
                                      type, nbd_rep_lookup(type), len);
@@ -174,17 +178,17 @@ static int nbd_negotiate_send_rep_len(QIOChannel *ioc, uint32_t type,

 /* Send a reply header with default 0 length.
  * Return -errno on error, 0 on success. */
-static int nbd_negotiate_send_rep(QIOChannel *ioc, uint32_t type, uint32_t opt,
+static int nbd_negotiate_send_rep(NBDClient *client, uint32_t type,
                                   Error **errp)
 {
-    return nbd_negotiate_send_rep_len(ioc, type, opt, 0, errp);
+    return nbd_negotiate_send_rep_len(client, type, 0, errp);
 }

 /* Send an error reply.
  * Return -errno on error, 0 on success. */
-static int GCC_FMT_ATTR(5, 6)
-nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type,
-                           uint32_t opt, Error **errp, const char *fmt, ...)
+static int GCC_FMT_ATTR(4, 5)
+nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
+                           Error **errp, const char *fmt, ...)
 {
     va_list va;
     char *msg;
@@ -197,11 +201,11 @@ nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type,
     len = strlen(msg);
     assert(len < 4096);
     trace_nbd_negotiate_send_rep_err(msg);
-    ret = nbd_negotiate_send_rep_len(ioc, type, opt, len, errp);
+    ret = nbd_negotiate_send_rep_len(client, type, len, errp);
     if (ret < 0) {
         goto out;
     }
-    if (nbd_write(ioc, msg, len, errp) < 0) {
+    if (nbd_write(client->ioc, msg, len, errp) < 0) {
         error_prepend(errp, "write failed (error message): ");
         ret = -EIO;
     } else {
@@ -215,21 +219,21 @@ out:

 /* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
  * Return -errno on error, 0 on success. */
-static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp,
+static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,
                                        Error **errp)
 {
     size_t name_len, desc_len;
     uint32_t len;
     const char *name = exp->name ? exp->name : "";
     const char *desc = exp->description ? exp->description : "";
+    QIOChannel *ioc = client->ioc;
     int ret;

     trace_nbd_negotiate_send_rep_list(name, desc);
     name_len = strlen(name);
     desc_len = strlen(desc);
     len = name_len + desc_len + sizeof(len);
-    ret = nbd_negotiate_send_rep_len(ioc, NBD_REP_SERVER, NBD_OPT_LIST, len,
-                                     errp);
+    ret = nbd_negotiate_send_rep_len(client, NBD_REP_SERVER, len, errp);
     if (ret < 0) {
         return ret;
     }
@@ -258,20 +262,21 @@ static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp,
 static int nbd_negotiate_handle_list(NBDClient *client, Error **errp)
 {
     NBDExport *exp;
+    assert(client->opt == NBD_OPT_LIST);

     /* For each export, send a NBD_REP_SERVER reply. */
     QTAILQ_FOREACH(exp, &exports, next) {
-        if (nbd_negotiate_send_rep_list(client->ioc, exp, errp)) {
+        if (nbd_negotiate_send_rep_list(client, exp, errp)) {
             return -EINVAL;
         }
     }
     /* Finish with a NBD_REP_ACK. */
-    return nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, NBD_OPT_LIST, errp);
+    return nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
 }

 /* Send a reply to NBD_OPT_EXPORT_NAME.
  * Return -errno on error, 0 on success. */
-static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length,
+static int nbd_negotiate_handle_export_name(NBDClient *client,
                                             uint16_t myflags, bool no_zeroes,
                                             Error **errp)
 {
@@ -288,15 +293,16 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length,
         [10 .. 133]   reserved     (0) [unless no_zeroes]
      */
     trace_nbd_negotiate_handle_export_name();
-    if (length >= sizeof(name)) {
+    if (client->optlen >= sizeof(name)) {
         error_setg(errp, "Bad length received");
         return -EINVAL;
     }
-    if (nbd_read(client->ioc, name, length, errp) < 0) {
+    if (nbd_read(client->ioc, name, client->optlen, errp) < 0) {
         error_prepend(errp, "read failed: ");
         return -EINVAL;
     }
-    name[length] = '\0';
+    name[client->optlen] = '\0';
+    client->optlen = 0;

     trace_nbd_negotiate_handle_export_name_request(name);

@@ -326,14 +332,14 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length,
 /* Send a single NBD_REP_INFO, with a buffer @buf of @length bytes.
  * The buffer does NOT include the info type prefix.
  * Return -errno on error, 0 if ready to send more. */
-static int nbd_negotiate_send_info(NBDClient *client, uint32_t opt,
+static int nbd_negotiate_send_info(NBDClient *client,
                                    uint16_t info, uint32_t length, void *buf,
                                    Error **errp)
 {
     int rc;

     trace_nbd_negotiate_send_info(info, nbd_info_lookup(info), length);
-    rc = nbd_negotiate_send_rep_len(client->ioc, NBD_REP_INFO, opt,
+    rc = nbd_negotiate_send_rep_len(client, NBD_REP_INFO,
                                     sizeof(info) + length, errp);
     if (rc < 0) {
         return rc;
@@ -355,22 +361,20 @@ static int nbd_negotiate_send_info(NBDClient *client, uint32_t opt,
  * -errno  transmission error occurred or @fatal was requested, errp is set
  * 0       error message successfully sent to client, errp is not set
  */
-static int nbd_reject_length(NBDClient *client, uint32_t length,
-                             uint32_t option, bool fatal, Error **errp)
+static int nbd_reject_length(NBDClient *client, bool fatal, Error **errp)
 {
     int ret;

-    assert(length);
-    if (nbd_drop(client->ioc, length, errp) < 0) {
+    assert(client->optlen);
+    if (nbd_drop(client->ioc, client->optlen, errp) < 0) {
         return -EIO;
     }
-    ret = nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_INVALID,
-                                     option, errp,
+    ret = nbd_negotiate_send_rep_err(client, NBD_REP_ERR_INVALID, errp,
                                      "option '%s' should have zero length",
-                                     nbd_opt_lookup(option));
+                                     nbd_opt_lookup(client->opt));
     if (fatal && !ret) {
         error_setg(errp, "option '%s' should have zero length",
-                   nbd_opt_lookup(option));
+                   nbd_opt_lookup(client->opt));
         return -EINVAL;
     }
     return ret;
@@ -379,8 +383,7 @@ static int nbd_reject_length(NBDClient *client, uint32_t length,
 /* Handle NBD_OPT_INFO and NBD_OPT_GO.
  * Return -errno on error, 0 if ready for next option, and 1 to move
  * into transmission phase.  */
-static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
-                                     uint32_t opt, uint16_t myflags,
+static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
                                      Error **errp)
 {
     int rc;
@@ -401,7 +404,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
         2 bytes: N, number of requests (can be 0)
         N * 2 bytes: N requests
     */
-    if (length < sizeof(namelen) + sizeof(requests)) {
+    if (client->optlen < sizeof(namelen) + sizeof(requests)) {
         msg = "overall request too short";
         goto invalid;
     }
@@ -409,8 +412,10 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
         return -EIO;
     }
     be32_to_cpus(&namelen);
-    length -= sizeof(namelen);
-    if (namelen > length - sizeof(requests) || (length - namelen) % 2) {
+    client->optlen -= sizeof(namelen);
+    if (namelen > client->optlen - sizeof(requests) ||
+        (client->optlen - namelen) % 2)
+    {
         msg = "name length is incorrect";
         goto invalid;
     }
@@ -422,16 +427,16 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
         return -EIO;
     }
     name[namelen] = '\0';
-    length -= namelen;
+    client->optlen -= namelen;
     trace_nbd_negotiate_handle_export_name_request(name);

     if (nbd_read(client->ioc, &requests, sizeof(requests), errp) < 0) {
         return -EIO;
     }
     be16_to_cpus(&requests);
-    length -= sizeof(requests);
+    client->optlen -= sizeof(requests);
     trace_nbd_negotiate_handle_info_requests(requests);
-    if (requests != length / sizeof(request)) {
+    if (requests != client->optlen / sizeof(request)) {
         msg = "incorrect number of  requests for overall length";
         goto invalid;
     }
@@ -440,7 +445,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
             return -EIO;
         }
         be16_to_cpus(&request);
-        length -= sizeof(request);
+        client->optlen -= sizeof(request);
         trace_nbd_negotiate_handle_info_request(request,
                                                 nbd_info_lookup(request));
         /* We care about NBD_INFO_NAME and NBD_INFO_BLOCK_SIZE;
@@ -455,18 +460,18 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
             break;
         }
     }
-    assert(length == 0);
+    assert(client->optlen == 0);

     exp = nbd_export_find(name);
     if (!exp) {
-        return nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_UNKNOWN,
-                                          opt, errp, "export '%s' not present",
+        return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_UNKNOWN,
+                                          errp, "export '%s' not present",
                                           name);
     }

     /* Don't bother sending NBD_INFO_NAME unless client requested it */
     if (sendname) {
-        rc = nbd_negotiate_send_info(client, opt, NBD_INFO_NAME, namelen, name,
+        rc = nbd_negotiate_send_info(client, NBD_INFO_NAME, namelen, name,
                                      errp);
         if (rc < 0) {
             return rc;
@@ -478,7 +483,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
     if (exp->description) {
         size_t len = strlen(exp->description);

-        rc = nbd_negotiate_send_info(client, opt, NBD_INFO_DESCRIPTION,
+        rc = nbd_negotiate_send_info(client, NBD_INFO_DESCRIPTION,
                                      len, exp->description, errp);
         if (rc < 0) {
             return rc;
@@ -490,7 +495,8 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
      * whether this is OPT_INFO or OPT_GO. */
     /* minimum - 1 for back-compat, or 512 if client is new enough.
      * TODO: consult blk_bs(blk)->bl.request_alignment? */
-    sizes[0] = (opt == NBD_OPT_INFO || blocksize) ? BDRV_SECTOR_SIZE : 1;
+    sizes[0] =
+            (client->opt == NBD_OPT_INFO || blocksize) ? BDRV_SECTOR_SIZE : 1;
     /* preferred - Hard-code to 4096 for now.
      * TODO: is blk_bs(blk)->bl.opt_transfer appropriate? */
     sizes[1] = 4096;
@@ -500,7 +506,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
     cpu_to_be32s(&sizes[0]);
     cpu_to_be32s(&sizes[1]);
     cpu_to_be32s(&sizes[2]);
-    rc = nbd_negotiate_send_info(client, opt, NBD_INFO_BLOCK_SIZE,
+    rc = nbd_negotiate_send_info(client, NBD_INFO_BLOCK_SIZE,
                                  sizeof(sizes), sizes, errp);
     if (rc < 0) {
         return rc;
@@ -511,7 +517,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
                                              exp->nbdflags | myflags);
     stq_be_p(buf, exp->size);
     stw_be_p(buf + 8, exp->nbdflags | myflags);
-    rc = nbd_negotiate_send_info(client, opt, NBD_INFO_EXPORT,
+    rc = nbd_negotiate_send_info(client, NBD_INFO_EXPORT,
                                  sizeof(buf), buf, errp);
     if (rc < 0) {
         return rc;
@@ -521,21 +527,21 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
      * request block sizes, return an error.
      * TODO: consult blk_bs(blk)->request_align, and only error if it
      * is not 1? */
-    if (opt == NBD_OPT_INFO && !blocksize) {
-        return nbd_negotiate_send_rep_err(client->ioc,
-                                          NBD_REP_ERR_BLOCK_SIZE_REQD, opt,
+    if (client->opt == NBD_OPT_INFO && !blocksize) {
+        return nbd_negotiate_send_rep_err(client,
+                                          NBD_REP_ERR_BLOCK_SIZE_REQD,
                                           errp,
                                           "request NBD_INFO_BLOCK_SIZE to "
                                           "use this export");
     }

     /* Final reply */
-    rc = nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, opt, errp);
+    rc = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
     if (rc < 0) {
         return rc;
     }

-    if (opt == NBD_OPT_GO) {
+    if (client->opt == NBD_OPT_GO) {
         client->exp = exp;
         QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
         nbd_export_get(client->exp);
@@ -544,10 +550,10 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
     return rc;

  invalid:
-    if (nbd_drop(client->ioc, length, errp) < 0) {
+    if (nbd_drop(client->ioc, client->optlen, errp) < 0) {
         return -EIO;
     }
-    return nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_INVALID, opt,
+    return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_INVALID,
                                       errp, "%s", msg);
 }

@@ -561,11 +567,12 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
     QIOChannelTLS *tioc;
     struct NBDTLSHandshakeData data = { 0 };

+    assert(client->opt == NBD_OPT_STARTTLS);
+
     trace_nbd_negotiate_handle_starttls();
     ioc = client->ioc;

-    if (nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK,
-                               NBD_OPT_STARTTLS, errp) < 0) {
+    if (nbd_negotiate_send_rep(client, NBD_REP_ACK, errp) < 0) {
         return NULL;
     }

@@ -670,12 +677,14 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
             return -EINVAL;
         }
         option = be32_to_cpu(option);
+        client->opt = option;

         if (nbd_read(client->ioc, &length, sizeof(length), errp) < 0) {
             error_prepend(errp, "read failed: ");
             return -EINVAL;
         }
         length = be32_to_cpu(length);
+        client->optlen = length;

         if (length > NBD_MAX_BUFFER_SIZE) {
             error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",
@@ -697,8 +706,7 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
                 if (length) {
                     /* Unconditionally drop the connection if the client
                      * can't start a TLS negotiation correctly */
-                    return nbd_reject_length(client, length, option, true,
-                                             errp);
+                    return nbd_reject_length(client, true, errp);
                 }
                 tioc = nbd_negotiate_handle_starttls(client, errp);
                 if (!tioc) {
@@ -719,9 +727,8 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
                 if (nbd_drop(client->ioc, length, errp) < 0) {
                     return -EIO;
                 }
-                ret = nbd_negotiate_send_rep_err(client->ioc,
-                                                 NBD_REP_ERR_TLS_REQD,
-                                                 option, errp,
+                ret = nbd_negotiate_send_rep_err(client,
+                                                 NBD_REP_ERR_TLS_REQD, errp,
                                                  "Option 0x%" PRIx32
                                                  "not permitted before TLS",
                                                  option);
@@ -737,8 +744,7 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
             switch (option) {
             case NBD_OPT_LIST:
                 if (length) {
-                    ret = nbd_reject_length(client, length, option, false,
-                                            errp);
+                    ret = nbd_reject_length(client, false, errp);
                 } else {
                     ret = nbd_negotiate_handle_list(client, errp);
                 }
@@ -748,18 +754,17 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
                 /* NBD spec says we must try to reply before
                  * disconnecting, but that we must also tolerate
                  * guests that don't wait for our reply. */
-                nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, option, NULL);
+                nbd_negotiate_send_rep(client, NBD_REP_ACK, NULL);
                 return 1;

             case NBD_OPT_EXPORT_NAME:
-                return nbd_negotiate_handle_export_name(client, length,
+                return nbd_negotiate_handle_export_name(client,
                                                         myflags, no_zeroes,
                                                         errp);

             case NBD_OPT_INFO:
             case NBD_OPT_GO:
-                ret = nbd_negotiate_handle_info(client, length, option,
-                                                myflags, errp);
+                ret = nbd_negotiate_handle_info(client, myflags, errp);
                 if (ret == 1) {
                     assert(option == NBD_OPT_GO);
                     return 0;
@@ -768,32 +773,27 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,

             case NBD_OPT_STARTTLS:
                 if (length) {
-                    ret = nbd_reject_length(client, length, option, false,
-                                            errp);
+                    ret = nbd_reject_length(client, false, errp);
                 } else if (client->tlscreds) {
-                    ret = nbd_negotiate_send_rep_err(client->ioc,
-                                                     NBD_REP_ERR_INVALID,
-                                                     option, errp,
+                    ret = nbd_negotiate_send_rep_err(client,
+                                                     NBD_REP_ERR_INVALID, errp,
                                                      "TLS already enabled");
                 } else {
-                    ret = nbd_negotiate_send_rep_err(client->ioc,
-                                                     NBD_REP_ERR_POLICY,
-                                                     option, errp,
+                    ret = nbd_negotiate_send_rep_err(client,
+                                                     NBD_REP_ERR_POLICY, errp,
                                                      "TLS not configured");
                 }
                 break;

             case NBD_OPT_STRUCTURED_REPLY:
                 if (length) {
-                    ret = nbd_reject_length(client, length, option, false,
-                                            errp);
+                    ret = nbd_reject_length(client, false, errp);
                 } else if (client->structured_reply) {
                     ret = nbd_negotiate_send_rep_err(
-                        client->ioc, NBD_REP_ERR_INVALID, option, errp,
+                        client, NBD_REP_ERR_INVALID, errp,
                         "structured reply already negotiated");
                 } else {
-                    ret = nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK,
-                                                 option, errp);
+                    ret = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp);
                     client->structured_reply = true;
                     myflags |= NBD_FLAG_SEND_DF;
                 }
@@ -803,9 +803,8 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
                 if (nbd_drop(client->ioc, length, errp) < 0) {
                     return -EIO;
                 }
-                ret = nbd_negotiate_send_rep_err(client->ioc,
-                                                 NBD_REP_ERR_UNSUP,
-                                                 option, errp,
+                ret = nbd_negotiate_send_rep_err(client,
+                                                 NBD_REP_ERR_UNSUP, errp,
                                                  "Unsupported option 0x%"
                                                  PRIx32 " (%s)", option,
                                                  nbd_opt_lookup(option));
@@ -818,7 +817,7 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
              */
             switch (option) {
             case NBD_OPT_EXPORT_NAME:
-                return nbd_negotiate_handle_export_name(client, length,
+                return nbd_negotiate_handle_export_name(client,
                                                         myflags, no_zeroes,
                                                         errp);

@@ -1707,6 +1706,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
         return;
     }

+    assert(!client->optlen);
     nbd_client_receive_next_request(client);
 }

-- 
2.14.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v2 3/6] nbd/server: Better error for NBD_OPT_EXPORT_NAME failure
  2018-01-10 23:08 [Qemu-devel] [PATCH v2 0/6] NBD server refactoring before BLOCK_STATUS Eric Blake
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 1/6] nbd/server: Hoist nbd_reject_length() earlier Eric Blake
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 2/6] nbd/server: refactor negotiation functions parameters Eric Blake
@ 2018-01-10 23:08 ` Eric Blake
  2018-01-11 17:34   ` Vladimir Sementsov-Ogievskiy
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 4/6] nbd/server: Add va_list form of nbd_negotiate_send_rep_err() Eric Blake
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Eric Blake @ 2018-01-10 23:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, vsementsov, Paolo Bonzini

When a client abruptly disconnects before we've finished reading
the name sent with NBD_OPT_EXPORT_NAME, we are better off logging
the failure as EIO (we can't communicate with the client), rather
than EINVAL (the client sent bogus data).

Signed-off-by: Eric Blake <eblake@redhat.com>
---
 nbd/server.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nbd/server.c b/nbd/server.c
index 08a24b56f4..9943a911c3 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -299,7 +299,7 @@ static int nbd_negotiate_handle_export_name(NBDClient *client,
     }
     if (nbd_read(client->ioc, name, client->optlen, errp) < 0) {
         error_prepend(errp, "read failed: ");
-        return -EINVAL;
+        return -EIO;
     }
     name[client->optlen] = '\0';
     client->optlen = 0;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v2 4/6] nbd/server: Add va_list form of nbd_negotiate_send_rep_err()
  2018-01-10 23:08 [Qemu-devel] [PATCH v2 0/6] NBD server refactoring before BLOCK_STATUS Eric Blake
                   ` (2 preceding siblings ...)
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 3/6] nbd/server: Better error for NBD_OPT_EXPORT_NAME failure Eric Blake
@ 2018-01-10 23:08 ` Eric Blake
  2018-01-11 18:05   ` Vladimir Sementsov-Ogievskiy
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 5/6] nbd/server: Add helper functions for parsing option payload Eric Blake
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 6/6] nbd/server: structurize option reply sending Eric Blake
  5 siblings, 1 reply; 17+ messages in thread
From: Eric Blake @ 2018-01-10 23:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, vsementsov, Paolo Bonzini

This will be useful for the next patch.

Based on a patch by Vladimir Sementsov-Ogievskiy

Signed-off-by: Eric Blake <eblake@redhat.com>
---
 nbd/server.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index 9943a911c3..d23bc2918a 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -186,18 +186,15 @@ static int nbd_negotiate_send_rep(NBDClient *client, uint32_t type,

 /* Send an error reply.
  * Return -errno on error, 0 on success. */
-static int GCC_FMT_ATTR(4, 5)
-nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
-                           Error **errp, const char *fmt, ...)
+static int GCC_FMT_ATTR(4, 0)
+nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type,
+                            Error **errp, const char *fmt, va_list va)
 {
-    va_list va;
     char *msg;
     int ret;
     size_t len;

-    va_start(va, fmt);
     msg = g_strdup_vprintf(fmt, va);
-    va_end(va);
     len = strlen(msg);
     assert(len < 4096);
     trace_nbd_negotiate_send_rep_err(msg);
@@ -217,6 +214,21 @@ out:
     return ret;
 }

+/* Send an error reply.
+ * Return -errno on error, 0 on success. */
+static int GCC_FMT_ATTR(4, 5)
+nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
+                           Error **errp, const char *fmt, ...)
+{
+    va_list va;
+    int ret;
+
+    va_start(va, fmt);
+    ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va);
+    va_end(va);
+    return ret;
+}
+
 /* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
  * Return -errno on error, 0 on success. */
 static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v2 5/6] nbd/server: Add helper functions for parsing option payload
  2018-01-10 23:08 [Qemu-devel] [PATCH v2 0/6] NBD server refactoring before BLOCK_STATUS Eric Blake
                   ` (3 preceding siblings ...)
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 4/6] nbd/server: Add va_list form of nbd_negotiate_send_rep_err() Eric Blake
@ 2018-01-10 23:08 ` Eric Blake
  2018-01-12 10:20   ` Vladimir Sementsov-Ogievskiy
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 6/6] nbd/server: structurize option reply sending Eric Blake
  5 siblings, 1 reply; 17+ messages in thread
From: Eric Blake @ 2018-01-10 23:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, vsementsov, Paolo Bonzini

Rather than making every callsite perform length sanity checks
and error reporting, add the helper functions nbd_opt_read()
and nbd_opt_drop() that use the length stored in the client
struct; also add an assertion that optlen is reduced to zero
after each option is handled.

Note that the call in nbd_negotiate_handle_export_name() does
not use the new helper (in part because the server cannot
reply to NBD_OPT_EXPORT_NAME - it either succeeds or the
connection drops).

Based on patches by Vladimir Sementsov-Ogievskiy.

Signed-off-by: Eric Blake <eblake@redhat.com>
---
 nbd/server.c | 123 ++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 63 insertions(+), 60 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index d23bc2918a..ec8c3be019 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -229,6 +229,41 @@ nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
     return ret;
 }

+/* Drop remainder of the current option, after sending a reply with
+ * the given error type and message. Return -errno on read or write
+ * failure; or 0 if connection is still live. */
+static int GCC_FMT_ATTR(4, 5)
+nbd_opt_drop(NBDClient *client, uint32_t type, Error **errp,
+             const char *fmt, ...)
+{
+    int ret = nbd_drop(client->ioc, client->optlen, errp);
+
+    client->optlen = 0;
+    if (!ret) {
+        va_list va;
+
+        va_start(va, fmt);
+        ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va);
+        va_end(va);
+    }
+    return ret;
+}
+
+/* Read size bytes from the unparsed payload of the current option.
+ * Return -errno on I/O error, 0 if option was completely handled by
+ * sending a reply about inconsistent lengths, or 1 on success. */
+static int nbd_opt_read(NBDClient *client, void *buffer, size_t size,
+                        Error **errp)
+{
+    if (size > client->optlen) {
+        return nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp,
+                            "Inconsistent lengths in option %s",
+                            nbd_opt_lookup(client->opt));
+    }
+    client->optlen -= size;
+    return qio_channel_read_all(client->ioc, buffer, size, errp) < 0 ? -EIO : 1;
+}
+
 /* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
  * Return -errno on error, 0 on success. */
 static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,
@@ -378,14 +413,11 @@ static int nbd_reject_length(NBDClient *client, bool fatal, Error **errp)
     int ret;

     assert(client->optlen);
-    if (nbd_drop(client->ioc, client->optlen, errp) < 0) {
-        return -EIO;
-    }
-    ret = nbd_negotiate_send_rep_err(client, NBD_REP_ERR_INVALID, errp,
-                                     "option '%s' should have zero length",
-                                     nbd_opt_lookup(client->opt));
+    ret = nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp,
+                       "option '%s' has unexpected length",
+                       nbd_opt_lookup(client->opt));
     if (fatal && !ret) {
-        error_setg(errp, "option '%s' should have zero length",
+        error_setg(errp, "option '%s' has unexpected length",
                    nbd_opt_lookup(client->opt));
         return -EINVAL;
     }
@@ -408,7 +440,6 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
     bool blocksize = false;
     uint32_t sizes[3];
     char buf[sizeof(uint64_t) + sizeof(uint16_t)];
-    const char *msg;

     /* Client sends:
         4 bytes: L, name length (can be 0)
@@ -416,48 +447,34 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
         2 bytes: N, number of requests (can be 0)
         N * 2 bytes: N requests
     */
-    if (client->optlen < sizeof(namelen) + sizeof(requests)) {
-        msg = "overall request too short";
-        goto invalid;
-    }
-    if (nbd_read(client->ioc, &namelen, sizeof(namelen), errp) < 0) {
-        return -EIO;
+    rc = nbd_opt_read(client, &namelen, sizeof(namelen), errp);
+    if (rc <= 0) {
+        return rc;
     }
     be32_to_cpus(&namelen);
-    client->optlen -= sizeof(namelen);
-    if (namelen > client->optlen - sizeof(requests) ||
-        (client->optlen - namelen) % 2)
-    {
-        msg = "name length is incorrect";
-        goto invalid;
-    }
     if (namelen >= sizeof(name)) {
-        msg = "name too long for qemu";
-        goto invalid;
+        return nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp,
+                            "name too long for qemu");
     }
-    if (nbd_read(client->ioc, name, namelen, errp) < 0) {
-        return -EIO;
+    rc = nbd_opt_read(client, name, namelen, errp);
+    if (rc <= 0) {
+        return rc;
     }
     name[namelen] = '\0';
-    client->optlen -= namelen;
     trace_nbd_negotiate_handle_export_name_request(name);

-    if (nbd_read(client->ioc, &requests, sizeof(requests), errp) < 0) {
-        return -EIO;
+    rc = nbd_opt_read(client, &requests, sizeof(requests), errp);
+    if (rc <= 0) {
+        return rc;
     }
     be16_to_cpus(&requests);
-    client->optlen -= sizeof(requests);
     trace_nbd_negotiate_handle_info_requests(requests);
-    if (requests != client->optlen / sizeof(request)) {
-        msg = "incorrect number of  requests for overall length";
-        goto invalid;
-    }
     while (requests--) {
-        if (nbd_read(client->ioc, &request, sizeof(request), errp) < 0) {
-            return -EIO;
+        rc = nbd_opt_read(client, &request, sizeof(request), errp);
+        if (rc <= 0) {
+            return rc;
         }
         be16_to_cpus(&request);
-        client->optlen -= sizeof(request);
         trace_nbd_negotiate_handle_info_request(request,
                                                 nbd_info_lookup(request));
         /* We care about NBD_INFO_NAME and NBD_INFO_BLOCK_SIZE;
@@ -472,7 +489,9 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
             break;
         }
     }
-    assert(client->optlen == 0);
+    if (client->optlen) {
+        return nbd_reject_length(client, false, errp);
+    }

     exp = nbd_export_find(name);
     if (!exp) {
@@ -560,13 +579,6 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
         rc = 1;
     }
     return rc;
-
- invalid:
-    if (nbd_drop(client->ioc, client->optlen, errp) < 0) {
-        return -EIO;
-    }
-    return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_INVALID,
-                                      errp, "%s", msg);
 }


@@ -736,14 +748,9 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
                 return -EINVAL;

             default:
-                if (nbd_drop(client->ioc, length, errp) < 0) {
-                    return -EIO;
-                }
-                ret = nbd_negotiate_send_rep_err(client,
-                                                 NBD_REP_ERR_TLS_REQD, errp,
-                                                 "Option 0x%" PRIx32
-                                                 "not permitted before TLS",
-                                                 option);
+                ret = nbd_opt_drop(client, NBD_REP_ERR_TLS_REQD, errp,
+                                   "Option 0x%" PRIx32
+                                   "not permitted before TLS", option);
                 /* Let the client keep trying, unless they asked to
                  * quit. In this mode, we've already sent an error, so
                  * we can't ack the abort.  */
@@ -812,14 +819,9 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
                 break;

             default:
-                if (nbd_drop(client->ioc, length, errp) < 0) {
-                    return -EIO;
-                }
-                ret = nbd_negotiate_send_rep_err(client,
-                                                 NBD_REP_ERR_UNSUP, errp,
-                                                 "Unsupported option 0x%"
-                                                 PRIx32 " (%s)", option,
-                                                 nbd_opt_lookup(option));
+                ret = nbd_opt_drop(client, NBD_REP_ERR_UNSUP, errp,
+                                   "Unsupported option 0x%" PRIx32 " (%s)",
+                                   option, nbd_opt_lookup(option));
                 break;
             }
         } else {
@@ -842,6 +844,7 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
         if (ret < 0) {
             return ret;
         }
+        assert(!client->optlen);
     }
 }

-- 
2.14.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v2 6/6] nbd/server: structurize option reply sending
  2018-01-10 23:08 [Qemu-devel] [PATCH v2 0/6] NBD server refactoring before BLOCK_STATUS Eric Blake
                   ` (4 preceding siblings ...)
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 5/6] nbd/server: Add helper functions for parsing option payload Eric Blake
@ 2018-01-10 23:08 ` Eric Blake
  5 siblings, 0 replies; 17+ messages in thread
From: Eric Blake @ 2018-01-10 23:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, vsementsov, Paolo Bonzini

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20171122101958.17065-6-vsementsov@virtuozzo.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
---
 nbd/server.c | 40 +++++++++++++---------------------------
 1 file changed, 13 insertions(+), 27 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index ec8c3be019..9019ad28f4 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -137,43 +137,29 @@ static void nbd_client_receive_next_request(NBDClient *client);

 */

+static inline void set_be_option_rep(NBDOptionReply *rep, uint32_t option,
+                                     uint32_t type, uint32_t length)
+{
+    stq_be_p(&rep->magic, NBD_REP_MAGIC);
+    stl_be_p(&rep->option, option);
+    stl_be_p(&rep->type, type);
+    stl_be_p(&rep->length, length);
+}
+
 /* Send a reply header, including length, but no payload.
  * Return -errno on error, 0 on success. */
 static int nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type,
                                       uint32_t len, Error **errp)
 {
-    uint64_t magic;
-    QIOChannel *ioc = client->ioc;
-    uint32_t opt = client->opt;
+    NBDOptionReply rep;

-    trace_nbd_negotiate_send_rep_len(opt, nbd_opt_lookup(opt),
+    trace_nbd_negotiate_send_rep_len(client->opt, nbd_opt_lookup(client->opt),
                                      type, nbd_rep_lookup(type), len);

     assert(len < NBD_MAX_BUFFER_SIZE);
-    magic = cpu_to_be64(NBD_REP_MAGIC);
-    if (nbd_write(ioc, &magic, sizeof(magic), errp) < 0) {
-        error_prepend(errp, "write failed (rep magic): ");
-        return -EINVAL;
-    }

-    opt = cpu_to_be32(opt);
-    if (nbd_write(ioc, &opt, sizeof(opt), errp) < 0) {
-        error_prepend(errp, "write failed (rep opt): ");
-        return -EINVAL;
-    }
-
-    type = cpu_to_be32(type);
-    if (nbd_write(ioc, &type, sizeof(type), errp) < 0) {
-        error_prepend(errp, "write failed (rep type): ");
-        return -EINVAL;
-    }
-
-    len = cpu_to_be32(len);
-    if (nbd_write(ioc, &len, sizeof(len), errp) < 0) {
-        error_prepend(errp, "write failed (rep data length): ");
-        return -EINVAL;
-    }
-    return 0;
+    set_be_option_rep(&rep, client->opt, type, len);
+    return nbd_write(client->ioc, &rep, sizeof(rep), errp);
 }

 /* Send a reply header with default 0 length.
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/6] nbd/server: Hoist nbd_reject_length() earlier
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 1/6] nbd/server: Hoist nbd_reject_length() earlier Eric Blake
@ 2018-01-11 17:31   ` Vladimir Sementsov-Ogievskiy
  0 siblings, 0 replies; 17+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2018-01-11 17:31 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: qemu-block, Paolo Bonzini

11.01.2018 02:08, Eric Blake wrote:
> No semantic change, but will make it easier for an upcoming patch
> to refactor code without having to add forward declarations.
>
> Signed-off-by: Eric Blake <eblake@redhat.com>

Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

-- 

Best regards,
Vladimir

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/6] nbd/server: Better error for NBD_OPT_EXPORT_NAME failure
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 3/6] nbd/server: Better error for NBD_OPT_EXPORT_NAME failure Eric Blake
@ 2018-01-11 17:34   ` Vladimir Sementsov-Ogievskiy
  0 siblings, 0 replies; 17+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2018-01-11 17:34 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: qemu-block, Paolo Bonzini

11.01.2018 02:08, Eric Blake wrote:
> When a client abruptly disconnects before we've finished reading
> the name sent with NBD_OPT_EXPORT_NAME, we are better off logging
> the failure as EIO (we can't communicate with the client), rather
> than EINVAL (the client sent bogus data).
>
> Signed-off-by: Eric Blake <eblake@redhat.com>

Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

> ---
>   nbd/server.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/nbd/server.c b/nbd/server.c
> index 08a24b56f4..9943a911c3 100644
> --- a/nbd/server.c
> +++ b/nbd/server.c
> @@ -299,7 +299,7 @@ static int nbd_negotiate_handle_export_name(NBDClient *client,
>       }
>       if (nbd_read(client->ioc, name, client->optlen, errp) < 0) {
>           error_prepend(errp, "read failed: ");
> -        return -EINVAL;
> +        return -EIO;
>       }
>       name[client->optlen] = '\0';
>       client->optlen = 0;


-- 
Best regards,
Vladimir

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/6] nbd/server: refactor negotiation functions parameters
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 2/6] nbd/server: refactor negotiation functions parameters Eric Blake
@ 2018-01-11 17:55   ` Vladimir Sementsov-Ogievskiy
  2018-01-11 19:54     ` Eric Blake
  0 siblings, 1 reply; 17+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2018-01-11 17:55 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: qemu-block, Paolo Bonzini

11.01.2018 02:08, Eric Blake wrote:
> From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
>
> Instead of passing currently negotiating option and its length to
> many of negotiation functions let's just store them on NBDClient
> struct to be state-variables of negotiation phase.
>
> This unifies semantics of negotiation functions and allows
> tracking changes of remaining option length in future patches.
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> Message-Id: <20171122101958.17065-2-vsementsov@virtuozzo.com>
> [eblake: rebase, commit message tweak, assert !optlen after
> negotiation completes]
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
>   nbd/server.c | 168 +++++++++++++++++++++++++++++------------------------------
>   1 file changed, 84 insertions(+), 84 deletions(-)

[..]

> @@ -818,7 +817,7 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
>                */
>               switch (option) {
>               case NBD_OPT_EXPORT_NAME:
> -                return nbd_negotiate_handle_export_name(client, length,
> +                return nbd_negotiate_handle_export_name(client,
>                                                           myflags, no_zeroes,
>                                                           errp);
>
> @@ -1707,6 +1706,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
>           return;
>       }
>
> +    assert(!client->optlen);


hmm, should not it be at the end of nbd_negotiate() ? Looks OK anyway.

>       nbd_client_receive_next_request(client);
>   }
>


-- 
Best regards,
Vladimir

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/6] nbd/server: Add va_list form of nbd_negotiate_send_rep_err()
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 4/6] nbd/server: Add va_list form of nbd_negotiate_send_rep_err() Eric Blake
@ 2018-01-11 18:05   ` Vladimir Sementsov-Ogievskiy
  2018-01-11 19:58     ` Eric Blake
  0 siblings, 1 reply; 17+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2018-01-11 18:05 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: qemu-block, Paolo Bonzini

11.01.2018 02:08, Eric Blake wrote:
> This will be useful for the next patch.
>
> Based on a patch by Vladimir Sementsov-Ogievskiy
>
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
>   nbd/server.c | 24 ++++++++++++++++++------
>   1 file changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/nbd/server.c b/nbd/server.c
> index 9943a911c3..d23bc2918a 100644
> --- a/nbd/server.c
> +++ b/nbd/server.c
> @@ -186,18 +186,15 @@ static int nbd_negotiate_send_rep(NBDClient *client, uint32_t type,
>
>   /* Send an error reply.
>    * Return -errno on error, 0 on success. */
> -static int GCC_FMT_ATTR(4, 5)
> -nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
> -                           Error **errp, const char *fmt, ...)
> +static int GCC_FMT_ATTR(4, 0)
> +nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type,
> +                            Error **errp, const char *fmt, va_list va)

Hmm you placed fmt and va after errp. Previously we discussed one 
exclusion from "errp should be last" -
"...", variable number of arguments. So, it is new exclusion (or I 
missed something?).. Looks good for me,
anyway, as it corresponds to "errp, fmt, ..." notation.

Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

>   {
> -    va_list va;
>       char *msg;
>       int ret;
>       size_t len;
>
> -    va_start(va, fmt);
>       msg = g_strdup_vprintf(fmt, va);
> -    va_end(va);
>       len = strlen(msg);
>       assert(len < 4096);
>       trace_nbd_negotiate_send_rep_err(msg);
> @@ -217,6 +214,21 @@ out:
>       return ret;
>   }
>
> +/* Send an error reply.
> + * Return -errno on error, 0 on success. */
> +static int GCC_FMT_ATTR(4, 5)
> +nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
> +                           Error **errp, const char *fmt, ...)
> +{
> +    va_list va;
> +    int ret;
> +
> +    va_start(va, fmt);
> +    ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va);
> +    va_end(va);
> +    return ret;
> +}
> +
>   /* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
>    * Return -errno on error, 0 on success. */
>   static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp,


-- 
Best regards,
Vladimir

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/6] nbd/server: refactor negotiation functions parameters
  2018-01-11 17:55   ` Vladimir Sementsov-Ogievskiy
@ 2018-01-11 19:54     ` Eric Blake
  2018-01-12 10:18       ` Vladimir Sementsov-Ogievskiy
  0 siblings, 1 reply; 17+ messages in thread
From: Eric Blake @ 2018-01-11 19:54 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, qemu-devel; +Cc: qemu-block, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 1966 bytes --]

On 01/11/2018 11:55 AM, Vladimir Sementsov-Ogievskiy wrote:
> 11.01.2018 02:08, Eric Blake wrote:
>> From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
>>
>> Instead of passing currently negotiating option and its length to
>> many of negotiation functions let's just store them on NBDClient
>> struct to be state-variables of negotiation phase.
>>
>> This unifies semantics of negotiation functions and allows
>> tracking changes of remaining option length in future patches.
>>
>> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
>> Reviewed-by: Eric Blake <eblake@redhat.com>
>> Message-Id: <20171122101958.17065-2-vsementsov@virtuozzo.com>
>> [eblake: rebase, commit message tweak, assert !optlen after
>> negotiation completes]
>> Signed-off-by: Eric Blake <eblake@redhat.com>
>> ---
>>   nbd/server.c | 168
>> +++++++++++++++++++++++++++++------------------------------
>>   1 file changed, 84 insertions(+), 84 deletions(-)
> 

>> @@ -1707,6 +1706,7 @@ static coroutine_fn void
>> nbd_co_client_start(void *opaque)
>>           return;
>>       }
>>
>> +    assert(!client->optlen);
> 
> 
> hmm, should not it be at the end of nbd_negotiate() ? Looks OK anyway.

Sure, I'll squash this in, for no real change in behavior:

diff --git i/nbd/server.c w/nbd/server.c
index c22d5e6ecf..3fd145592e 100644
--- i/nbd/server.c
+++ w/nbd/server.c
@@ -902,6 +902,7 @@ static coroutine_fn int nbd_negotiate(NBDClient
*client, Error **errp)
         }
     }

+    assert(!client->optlen);
     trace_nbd_negotiate_success();

     return 0;
@@ -1726,7 +1727,6 @@ static coroutine_fn void nbd_co_client_start(void
*opaque)
         return;
     }

-    assert(!client->optlen);
     nbd_client_receive_next_request(client);
 }



-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/6] nbd/server: Add va_list form of nbd_negotiate_send_rep_err()
  2018-01-11 18:05   ` Vladimir Sementsov-Ogievskiy
@ 2018-01-11 19:58     ` Eric Blake
  0 siblings, 0 replies; 17+ messages in thread
From: Eric Blake @ 2018-01-11 19:58 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, qemu-devel; +Cc: qemu-block, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 1789 bytes --]

On 01/11/2018 12:05 PM, Vladimir Sementsov-Ogievskiy wrote:
> 11.01.2018 02:08, Eric Blake wrote:
>> This will be useful for the next patch.
>>
>> Based on a patch by Vladimir Sementsov-Ogievskiy
>>
>> Signed-off-by: Eric Blake <eblake@redhat.com>
>> ---
>>   nbd/server.c | 24 ++++++++++++++++++------
>>   1 file changed, 18 insertions(+), 6 deletions(-)
>>

>> -static int GCC_FMT_ATTR(4, 5)
>> -nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
>> -                           Error **errp, const char *fmt, ...)
>> +static int GCC_FMT_ATTR(4, 0)
>> +nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type,
>> +                            Error **errp, const char *fmt, va_list va)
> 
> Hmm you placed fmt and va after errp. Previously we discussed one
> exclusion from "errp should be last" -
> "...", variable number of arguments. So, it is new exclusion (or I
> missed something?).. Looks good for me,
> anyway, as it corresponds to "errp, fmt, ..." notation.

Indeed, it is precisely because I value consistency between 'fmt, ...'
and 'fmt, va_list' higher than 'errp last' that I rearranged things from
your patch into the form I used.  Or worded another way, even though
va_list is only one argument in name, I treat it the same as the
variable number of arguments that warrants the exception to the errp
last rule of thumb.

> 
> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> 

Thanks; I think this series is now ready for staging on my NBD queue;
although my next pull request won't be until after the weekend.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/6] nbd/server: refactor negotiation functions parameters
  2018-01-11 19:54     ` Eric Blake
@ 2018-01-12 10:18       ` Vladimir Sementsov-Ogievskiy
  2018-01-12 14:34         ` Eric Blake
  0 siblings, 1 reply; 17+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2018-01-12 10:18 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: qemu-block, Paolo Bonzini

11.01.2018 22:54, Eric Blake wrote:
> On 01/11/2018 11:55 AM, Vladimir Sementsov-Ogievskiy wrote:
>> 11.01.2018 02:08, Eric Blake wrote:
>>> From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
>>>
>>> Instead of passing currently negotiating option and its length to
>>> many of negotiation functions let's just store them on NBDClient
>>> struct to be state-variables of negotiation phase.
>>>
>>> This unifies semantics of negotiation functions and allows
>>> tracking changes of remaining option length in future patches.
>>>
>>> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
>>> Reviewed-by: Eric Blake <eblake@redhat.com>
>>> Message-Id: <20171122101958.17065-2-vsementsov@virtuozzo.com>
>>> [eblake: rebase, commit message tweak, assert !optlen after
>>> negotiation completes]
>>> Signed-off-by: Eric Blake <eblake@redhat.com>
>>> ---
>>>    nbd/server.c | 168
>>> +++++++++++++++++++++++++++++------------------------------
>>>    1 file changed, 84 insertions(+), 84 deletions(-)
>>> @@ -1707,6 +1706,7 @@ static coroutine_fn void
>>> nbd_co_client_start(void *opaque)
>>>            return;
>>>        }
>>>
>>> +    assert(!client->optlen);
>>
>> hmm, should not it be at the end of nbd_negotiate() ? Looks OK anyway.
> Sure, I'll squash this in, for no real change in behavior:
>
> diff --git i/nbd/server.c w/nbd/server.c
> index c22d5e6ecf..3fd145592e 100644
> --- i/nbd/server.c
> +++ w/nbd/server.c
> @@ -902,6 +902,7 @@ static coroutine_fn int nbd_negotiate(NBDClient
> *client, Error **errp)
>           }
>       }
>
> +    assert(!client->optlen);
>       trace_nbd_negotiate_success();
>
>       return 0;
> @@ -1726,7 +1727,6 @@ static coroutine_fn void nbd_co_client_start(void
> *opaque)
>           return;
>       }
>
> -    assert(!client->optlen);
>       nbd_client_receive_next_request(client);
>   }
>
>
>


or, even better, in nbd_negotiate_options. and you actually do it in 5/6.


-- 
Best regards,
Vladimir

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v2 5/6] nbd/server: Add helper functions for parsing option payload
  2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 5/6] nbd/server: Add helper functions for parsing option payload Eric Blake
@ 2018-01-12 10:20   ` Vladimir Sementsov-Ogievskiy
  2018-01-12 14:37     ` Eric Blake
  0 siblings, 1 reply; 17+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2018-01-12 10:20 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: qemu-block, Paolo Bonzini

11.01.2018 02:08, Eric Blake wrote:
> Rather than making every callsite perform length sanity checks
> and error reporting, add the helper functions nbd_opt_read()
> and nbd_opt_drop() that use the length stored in the client
> struct; also add an assertion that optlen is reduced to zero
> after each option is handled.
>
> Note that the call in nbd_negotiate_handle_export_name() does
> not use the new helper (in part because the server cannot
> reply to NBD_OPT_EXPORT_NAME - it either succeeds or the
> connection drops).
>
> Based on patches by Vladimir Sementsov-Ogievskiy.
>
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
>   nbd/server.c | 123 ++++++++++++++++++++++++++++++-----------------------------
>   1 file changed, 63 insertions(+), 60 deletions(-)
>
> diff --git a/nbd/server.c b/nbd/server.c
> index d23bc2918a..ec8c3be019 100644
> --- a/nbd/server.c
> +++ b/nbd/server.c
> @@ -229,6 +229,41 @@ nbd_negotiate_send_rep_err(NBDClient *client, uint32_t type,
>       return ret;
>   }
>
> +/* Drop remainder of the current option, after sending a reply with

looks a bit weird: actually you drop the remainder _before_ sending a reply)

> + * the given error type and message. Return -errno on read or write

also, unrelated note, -errno is always forced to -EIO, because of 
nbd_read realization.
and this note applies to many other places here. It is correct (EIO is 
errno, why not?),
but it may be not bad to note it somewhere..

> + * failure; or 0 if connection is still live. */
> +static int GCC_FMT_ATTR(4, 5)
> +nbd_opt_drop(NBDClient *client, uint32_t type, Error **errp,
> +             const char *fmt, ...)
> +{
> +    int ret = nbd_drop(client->ioc, client->optlen, errp);
> +
> +    client->optlen = 0;
> +    if (!ret) {
> +        va_list va;
> +
> +        va_start(va, fmt);
> +        ret = nbd_negotiate_send_rep_verr(client, type, errp, fmt, va);
> +        va_end(va);
> +    }
> +    return ret;
> +}

[..]

> @@ -812,14 +819,9 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
>                   break;
>
>               default:
> -                if (nbd_drop(client->ioc, length, errp) < 0) {
> -                    return -EIO;
> -                }
> -                ret = nbd_negotiate_send_rep_err(client,
> -                                                 NBD_REP_ERR_UNSUP, errp,
> -                                                 "Unsupported option 0x%"
> -                                                 PRIx32 " (%s)", option,
> -                                                 nbd_opt_lookup(option));
> +                ret = nbd_opt_drop(client, NBD_REP_ERR_UNSUP, errp,
> +                                   "Unsupported option 0x%" PRIx32 " (%s)",
> +                                   option, nbd_opt_lookup(option));
>                   break;
>               }
>           } else {
> @@ -842,6 +844,7 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
>           if (ret < 0) {
>               return ret;
>           }
> +        assert(!client->optlen);

isn't it from 2/6?

>       }
>   }
>

anyway,

Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

-- 
Best regards,
Vladimir

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/6] nbd/server: refactor negotiation functions parameters
  2018-01-12 10:18       ` Vladimir Sementsov-Ogievskiy
@ 2018-01-12 14:34         ` Eric Blake
  0 siblings, 0 replies; 17+ messages in thread
From: Eric Blake @ 2018-01-12 14:34 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, qemu-devel; +Cc: qemu-block, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 1808 bytes --]

On 01/12/2018 04:18 AM, Vladimir Sementsov-Ogievskiy wrote:

>>> hmm, should not it be at the end of nbd_negotiate() ? Looks OK anyway.
>> Sure, I'll squash this in, for no real change in behavior:
>>
>> diff --git i/nbd/server.c w/nbd/server.c
>> index c22d5e6ecf..3fd145592e 100644
>> --- i/nbd/server.c
>> +++ w/nbd/server.c
>> @@ -902,6 +902,7 @@ static coroutine_fn int nbd_negotiate(NBDClient
>> *client, Error **errp)
>>           }
>>       }
>>
>> +    assert(!client->optlen);
>>       trace_nbd_negotiate_success();
>>

This says that after all negotiation is complete, optlen is 0 (so in
reality, it is only checking NBD_OPT_GO and NBD_OPT_EXPORT_NAME - since
those are the only two options that can end negotiation).  But it does
not check state in between individual options during the actual
negotiation.  Also, this is the only spot in the code that can check
that optlen is 0 even for old-style connections (where we do not call
nbd_negotiate_options), so it's a nice spot to prove that when we move
into transmission phase, we aren't stranding any unread data from
handshake phase.

> 
> 
> or, even better, in nbd_negotiate_options. and you actually do it in 5/6.

Whereas that is stating that optlen is 0 after every option that does
not return early (not possible in this patch, because we need the
nbd_opt_read() helper in 5/6 that clears optlen as we go) - and
meanwhile does NOT cover the places that return early (NBD_OPT_GO and
NBD_OPT_EXPORT_NAME, which we caught here).  So we need both assertions
at the end of the series, and I'm comfortable with introducing them in
separate patches.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v2 5/6] nbd/server: Add helper functions for parsing option payload
  2018-01-12 10:20   ` Vladimir Sementsov-Ogievskiy
@ 2018-01-12 14:37     ` Eric Blake
  0 siblings, 0 replies; 17+ messages in thread
From: Eric Blake @ 2018-01-12 14:37 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, qemu-devel; +Cc: qemu-block, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 3575 bytes --]

On 01/12/2018 04:20 AM, Vladimir Sementsov-Ogievskiy wrote:
> 11.01.2018 02:08, Eric Blake wrote:
>> Rather than making every callsite perform length sanity checks
>> and error reporting, add the helper functions nbd_opt_read()
>> and nbd_opt_drop() that use the length stored in the client
>> struct; also add an assertion that optlen is reduced to zero
>> after each option is handled.
>>
>> Note that the call in nbd_negotiate_handle_export_name() does
>> not use the new helper (in part because the server cannot
>> reply to NBD_OPT_EXPORT_NAME - it either succeeds or the
>> connection drops).
>>

>>
>> +/* Drop remainder of the current option, after sending a reply with
> 
> looks a bit weird: actually you drop the remainder _before_ sending a
> reply)

Good catch. I'll fix it with s/after/and/

> 
>> + * the given error type and message. Return -errno on read or write
> 
> also, unrelated note, -errno is always forced to -EIO, because of
> nbd_read realization.
> and this note applies to many other places here. It is correct (EIO is
> errno, why not?),
> but it may be not bad to note it somewhere..

Someday nbd_read() might fail with something other than EIO (ESHUTDOWN,
perhaps?), in which case leaving this documented as -errno would be
better than hardcoding that EIO is the only failure for now.

>> @@ -812,14 +819,9 @@ static int nbd_negotiate_options(NBDClient
>> *client, uint16_t myflags,
>>                   break;
>>
>>               default:
>> -                if (nbd_drop(client->ioc, length, errp) < 0) {
>> -                    return -EIO;
>> -                }
>> -                ret = nbd_negotiate_send_rep_err(client,
>> -                                                 NBD_REP_ERR_UNSUP,
>> errp,
>> -                                                 "Unsupported option
>> 0x%"
>> -                                                 PRIx32 " (%s)", option,
>> -                                                
>> nbd_opt_lookup(option));
>> +                ret = nbd_opt_drop(client, NBD_REP_ERR_UNSUP, errp,
>> +                                   "Unsupported option 0x%" PRIx32 "
>> (%s)",
>> +                                   option, nbd_opt_lookup(option));
>>                   break;
>>               }
>>           } else {
>> @@ -842,6 +844,7 @@ static int nbd_negotiate_options(NBDClient
>> *client, uint16_t myflags,
>>           if (ret < 0) {
>>               return ret;
>>           }
>> +        assert(!client->optlen);
> 
> isn't it from 2/6?

No, this is a second instance of the assertion, the one that applies
between each option (which I couldn't do in 2/6 because not all options
were manipulating optlen back then).  Maybe I can tweak the commit
messages to make that more obvious.

> 
>>       }
>>   }
>>
> 
> anyway,
> 
> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

Thanks for the careful attention to detail.


-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2018-01-12 14:37 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-10 23:08 [Qemu-devel] [PATCH v2 0/6] NBD server refactoring before BLOCK_STATUS Eric Blake
2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 1/6] nbd/server: Hoist nbd_reject_length() earlier Eric Blake
2018-01-11 17:31   ` Vladimir Sementsov-Ogievskiy
2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 2/6] nbd/server: refactor negotiation functions parameters Eric Blake
2018-01-11 17:55   ` Vladimir Sementsov-Ogievskiy
2018-01-11 19:54     ` Eric Blake
2018-01-12 10:18       ` Vladimir Sementsov-Ogievskiy
2018-01-12 14:34         ` Eric Blake
2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 3/6] nbd/server: Better error for NBD_OPT_EXPORT_NAME failure Eric Blake
2018-01-11 17:34   ` Vladimir Sementsov-Ogievskiy
2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 4/6] nbd/server: Add va_list form of nbd_negotiate_send_rep_err() Eric Blake
2018-01-11 18:05   ` Vladimir Sementsov-Ogievskiy
2018-01-11 19:58     ` Eric Blake
2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 5/6] nbd/server: Add helper functions for parsing option payload Eric Blake
2018-01-12 10:20   ` Vladimir Sementsov-Ogievskiy
2018-01-12 14:37     ` Eric Blake
2018-01-10 23:08 ` [Qemu-devel] [PATCH v2 6/6] nbd/server: structurize option reply sending Eric Blake

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.