76daa3
From 32813ec88e7b8868dd7474d01d8c5e4faa9fe290 Mon Sep 17 00:00:00 2001
76daa3
From: Eric Blake <eblake@redhat.com>
76daa3
Date: Wed, 19 Jul 2017 18:02:00 +0200
76daa3
Subject: [PATCH 03/17] nbd: read_sync and friends: return 0 on success
76daa3
76daa3
RH-Author: Eric Blake <eblake@redhat.com>
76daa3
Message-id: <20170719180202.23329-3-eblake@redhat.com>
76daa3
Patchwork-id: 75818
76daa3
O-Subject: [RHEV-7.4.z qemu-kvm-rhev PATCH 2/4] nbd: read_sync and friends: return 0 on success
76daa3
Bugzilla: 1473638
76daa3
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
76daa3
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
76daa3
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
76daa3
76daa3
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
76daa3
76daa3
functions read_sync, drop_sync, write_sync, and also
76daa3
nbd_negotiate_write, nbd_negotiate_read, nbd_negotiate_drop_sync
76daa3
returns number of processed bytes. But what this number can be,
76daa3
except requested number of bytes?
76daa3
76daa3
Actually, underlying nbd_wr_syncv function returns a value >= 0 and
76daa3
!= requested_bytes only on eof on read operation. So, firstly, it is
76daa3
impossible on write (let's add an assert) and on read it actually
76daa3
means, that communication is broken (except nbd_receive_reply, see
76daa3
below).
76daa3
76daa3
Most of callers operate like this:
76daa3
   if (func(..., size) != size) {
76daa3
       /* error path */
76daa3
   }
76daa3
, i.e.:
76daa3
  1. They are not interested in partial success
76daa3
  2. Extra duplications in code (especially bad are duplications of
76daa3
     magic numbers)
76daa3
  3. User doesn't see actual error message, as return code is lost.
76daa3
     (this patch doesn't fix this point, but it makes fixing easier)
76daa3
76daa3
Several callers handles ret >= 0 and != requested-size separately, by
76daa3
just returning EINVAL in this case. This patch makes read_sync and
76daa3
friends return EINVAL in this case, so final behavior is the same.
76daa3
76daa3
And only one caller - nbd_receive_reply() does something not so
76daa3
obvious. It returns EINVAL for ret > 0 and != requested-size, like
76daa3
previous group, but for ret == 0 it returns 0. The only caller of
76daa3
nbd_receive_reply() - nbd_read_reply_entry() handles ret == 0 in the
76daa3
same way as ret < 0, so for now it doesn't matter. However, in
76daa3
following commits error path handling will be improved and we'll need
76daa3
to distinguish success from fail in this case too. So, this patch adds
76daa3
separate helper for this case - read_sync_eof.
76daa3
76daa3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
76daa3
Message-Id: <20170516094533.6160-3-vsementsov@virtuozzo.com>
76daa3
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
76daa3
(cherry picked from commit f5d406fe86bb28da85824b6581e58980cc1a07f3)
76daa3
Signed-off-by: Eric Blake <eblake@redhat.com>
76daa3
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
76daa3
---
76daa3
 nbd/client.c       | 63 ++++++++++++++++------------------------
76daa3
 nbd/nbd-internal.h | 34 +++++++++++++++++++---
76daa3
 nbd/server.c       | 84 +++++++++++++++++++++---------------------------------
76daa3
 3 files changed, 88 insertions(+), 93 deletions(-)
76daa3
76daa3
diff --git a/nbd/client.c b/nbd/client.c
76daa3
index a58fb02..6b74a62 100644
76daa3
--- a/nbd/client.c
76daa3
+++ b/nbd/client.c
76daa3
@@ -86,9 +86,9 @@ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
76daa3
 
76daa3
 */
76daa3
 
76daa3
-/* Discard length bytes from channel.  Return -errno on failure, or
76daa3
- * the amount of bytes consumed. */
76daa3
-static ssize_t drop_sync(QIOChannel *ioc, size_t size)
76daa3
+/* Discard length bytes from channel.  Return -errno on failure and 0 on
76daa3
+ * success*/
76daa3
+static int drop_sync(QIOChannel *ioc, size_t size)
76daa3
 {
76daa3
     ssize_t ret = 0;
76daa3
     char small[1024];
76daa3
@@ -96,14 +96,13 @@ static ssize_t drop_sync(QIOChannel *ioc, size_t size)
76daa3
 
76daa3
     buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size));
76daa3
     while (size > 0) {
76daa3
-        ssize_t count = read_sync(ioc, buffer, MIN(65536, size));
76daa3
+        ssize_t count = MIN(65536, size);
76daa3
+        ret = read_sync(ioc, buffer, MIN(65536, size));
76daa3
 
76daa3
-        if (count <= 0) {
76daa3
+        if (ret < 0) {
76daa3
             goto cleanup;
76daa3
         }
76daa3
-        assert(count <= size);
76daa3
         size -= count;
76daa3
-        ret += count;
76daa3
     }
76daa3
 
76daa3
  cleanup:
76daa3
@@ -136,12 +135,12 @@ static int nbd_send_option_request(QIOChannel *ioc, uint32_t opt,
76daa3
     stl_be_p(&req.option, opt);
76daa3
     stl_be_p(&req.length, len);
76daa3
 
76daa3
-    if (write_sync(ioc, &req, sizeof(req)) != sizeof(req)) {
76daa3
+    if (write_sync(ioc, &req, sizeof(req)) < 0) {
76daa3
         error_setg(errp, "Failed to send option request header");
76daa3
         return -1;
76daa3
     }
76daa3
 
76daa3
-    if (len && write_sync(ioc, (char *) data, len) != len) {
76daa3
+    if (len && write_sync(ioc, (char *) data, len) < 0) {
76daa3
         error_setg(errp, "Failed to send option request data");
76daa3
         return -1;
76daa3
     }
76daa3
@@ -170,7 +169,7 @@ static int nbd_receive_option_reply(QIOChannel *ioc, uint32_t opt,
76daa3
                                     nbd_opt_reply *reply, Error **errp)
76daa3
 {
76daa3
     QEMU_BUILD_BUG_ON(sizeof(*reply) != 20);
76daa3
-    if (read_sync(ioc, reply, sizeof(*reply)) != sizeof(*reply)) {
76daa3
+    if (read_sync(ioc, reply, sizeof(*reply)) < 0) {
76daa3
         error_setg(errp, "failed to read option reply");
76daa3
         nbd_send_opt_abort(ioc);
76daa3
         return -1;
76daa3
@@ -219,7 +218,7 @@ static int nbd_handle_reply_err(QIOChannel *ioc, nbd_opt_reply *reply,
76daa3
             goto cleanup;
76daa3
         }
76daa3
         msg = g_malloc(reply->length + 1);
76daa3
-        if (read_sync(ioc, msg, reply->length) != reply->length) {
76daa3
+        if (read_sync(ioc, msg, reply->length) < 0) {
76daa3
             error_setg(errp, "failed to read option error message");
76daa3
             goto cleanup;
76daa3
         }
76daa3
@@ -321,7 +320,7 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
76daa3
         nbd_send_opt_abort(ioc);
76daa3
         return -1;
76daa3
     }
76daa3
-    if (read_sync(ioc, &namelen, sizeof(namelen)) != sizeof(namelen)) {
76daa3
+    if (read_sync(ioc, &namelen, sizeof(namelen)) < 0) {
76daa3
         error_setg(errp, "failed to read option name length");
76daa3
         nbd_send_opt_abort(ioc);
76daa3
         return -1;
76daa3
@@ -334,7 +333,7 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
76daa3
         return -1;
76daa3
     }
76daa3
     if (namelen != strlen(want)) {
76daa3
-        if (drop_sync(ioc, len) != len) {
76daa3
+        if (drop_sync(ioc, len) < 0) {
76daa3
             error_setg(errp, "failed to skip export name with wrong length");
76daa3
             nbd_send_opt_abort(ioc);
76daa3
             return -1;
76daa3
@@ -343,14 +342,14 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
76daa3
     }
76daa3
 
76daa3
     assert(namelen < sizeof(name));
76daa3
-    if (read_sync(ioc, name, namelen) != namelen) {
76daa3
+    if (read_sync(ioc, name, namelen) < 0) {
76daa3
         error_setg(errp, "failed to read export name");
76daa3
         nbd_send_opt_abort(ioc);
76daa3
         return -1;
76daa3
     }
76daa3
     name[namelen] = '\0';
76daa3
     len -= namelen;
76daa3
-    if (drop_sync(ioc, len) != len) {
76daa3
+    if (drop_sync(ioc, len) < 0) {
76daa3
         error_setg(errp, "failed to read export description");
76daa3
         nbd_send_opt_abort(ioc);
76daa3
         return -1;
76daa3
@@ -477,7 +476,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
76daa3
         goto fail;
76daa3
     }
76daa3
 
76daa3
-    if (read_sync(ioc, buf, 8) != 8) {
76daa3
+    if (read_sync(ioc, buf, 8) < 0) {
76daa3
         error_setg(errp, "Failed to read data");
76daa3
         goto fail;
76daa3
     }
76daa3
@@ -503,7 +502,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
76daa3
         goto fail;
76daa3
     }
76daa3
 
76daa3
-    if (read_sync(ioc, &magic, sizeof(magic)) != sizeof(magic)) {
76daa3
+    if (read_sync(ioc, &magic, sizeof(magic)) < 0) {
76daa3
         error_setg(errp, "Failed to read magic");
76daa3
         goto fail;
76daa3
     }
76daa3
@@ -515,8 +514,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
76daa3
         uint16_t globalflags;
76daa3
         bool fixedNewStyle = false;
76daa3
 
76daa3
-        if (read_sync(ioc, &globalflags, sizeof(globalflags)) !=
76daa3
-            sizeof(globalflags)) {
76daa3
+        if (read_sync(ioc, &globalflags, sizeof(globalflags)) < 0) {
76daa3
             error_setg(errp, "Failed to read server flags");
76daa3
             goto fail;
76daa3
         }
76daa3
@@ -534,8 +532,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
76daa3
         }
76daa3
         /* client requested flags */
76daa3
         clientflags = cpu_to_be32(clientflags);
76daa3
-        if (write_sync(ioc, &clientflags, sizeof(clientflags)) !=
76daa3
-            sizeof(clientflags)) {
76daa3
+        if (write_sync(ioc, &clientflags, sizeof(clientflags)) < 0) {
76daa3
             error_setg(errp, "Failed to send clientflags field");
76daa3
             goto fail;
76daa3
         }
76daa3
@@ -573,13 +570,13 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
76daa3
         }
76daa3
 
76daa3
         /* Read the response */
76daa3
-        if (read_sync(ioc, &s, sizeof(s)) != sizeof(s)) {
76daa3
+        if (read_sync(ioc, &s, sizeof(s)) < 0) {
76daa3
             error_setg(errp, "Failed to read export length");
76daa3
             goto fail;
76daa3
         }
76daa3
         *size = be64_to_cpu(s);
76daa3
 
76daa3
-        if (read_sync(ioc, flags, sizeof(*flags)) != sizeof(*flags)) {
76daa3
+        if (read_sync(ioc, flags, sizeof(*flags)) < 0) {
76daa3
             error_setg(errp, "Failed to read export flags");
76daa3
             goto fail;
76daa3
         }
76daa3
@@ -596,14 +593,14 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
76daa3
             goto fail;
76daa3
         }
76daa3
 
76daa3
-        if (read_sync(ioc, &s, sizeof(s)) != sizeof(s)) {
76daa3
+        if (read_sync(ioc, &s, sizeof(s)) < 0) {
76daa3
             error_setg(errp, "Failed to read export length");
76daa3
             goto fail;
76daa3
         }
76daa3
         *size = be64_to_cpu(s);
76daa3
         TRACE("Size is %" PRIu64, *size);
76daa3
 
76daa3
-        if (read_sync(ioc, &oldflags, sizeof(oldflags)) != sizeof(oldflags)) {
76daa3
+        if (read_sync(ioc, &oldflags, sizeof(oldflags)) < 0) {
76daa3
             error_setg(errp, "Failed to read export flags");
76daa3
             goto fail;
76daa3
         }
76daa3
@@ -619,7 +616,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
76daa3
     }
76daa3
 
76daa3
     TRACE("Size is %" PRIu64 ", export flags %" PRIx16, *size, *flags);
76daa3
-    if (zeroes && drop_sync(ioc, 124) != 124) {
76daa3
+    if (zeroes && drop_sync(ioc, 124) < 0) {
76daa3
         error_setg(errp, "Failed to read reserved block");
76daa3
         goto fail;
76daa3
     }
76daa3
@@ -744,7 +741,6 @@ int nbd_disconnect(int fd)
76daa3
 ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request)
76daa3
 {
76daa3
     uint8_t buf[NBD_REQUEST_SIZE];
76daa3
-    ssize_t ret;
76daa3
 
76daa3
     TRACE("Sending request to server: "
76daa3
           "{ .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64
76daa3
@@ -759,16 +755,7 @@ ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request)
76daa3
     stq_be_p(buf + 16, request->from);
76daa3
     stl_be_p(buf + 24, request->len);
76daa3
 
76daa3
-    ret = write_sync(ioc, buf, sizeof(buf));
76daa3
-    if (ret < 0) {
76daa3
-        return ret;
76daa3
-    }
76daa3
-
76daa3
-    if (ret != sizeof(buf)) {
76daa3
-        LOG("writing to socket failed");
76daa3
-        return -EINVAL;
76daa3
-    }
76daa3
-    return 0;
76daa3
+    return write_sync(ioc, buf, sizeof(buf));
76daa3
 }
76daa3
 
76daa3
 ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply)
76daa3
@@ -777,7 +764,7 @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply)
76daa3
     uint32_t magic;
76daa3
     ssize_t ret;
76daa3
 
76daa3
-    ret = read_sync(ioc, buf, sizeof(buf));
76daa3
+    ret = read_sync_eof(ioc, buf, sizeof(buf));
76daa3
     if (ret <= 0) {
76daa3
         return ret;
76daa3
     }
76daa3
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
76daa3
index f43d990..e6bbc7c 100644
76daa3
--- a/nbd/nbd-internal.h
76daa3
+++ b/nbd/nbd-internal.h
76daa3
@@ -94,7 +94,13 @@
76daa3
 #define NBD_ENOSPC     28
76daa3
 #define NBD_ESHUTDOWN  108
76daa3
 
76daa3
-static inline ssize_t read_sync(QIOChannel *ioc, void *buffer, size_t size)
76daa3
+/* read_sync_eof
76daa3
+ * Tries to read @size bytes from @ioc. Returns number of bytes actually read.
76daa3
+ * May return a value >= 0 and < size only on EOF, i.e. when iteratively called
76daa3
+ * qio_channel_readv() returns 0. So, there are no needs to call read_sync_eof
76daa3
+ * iteratively.
76daa3
+ */
76daa3
+static inline ssize_t read_sync_eof(QIOChannel *ioc, void *buffer, size_t size)
76daa3
 {
76daa3
     struct iovec iov = { .iov_base = buffer, .iov_len = size };
76daa3
     /* Sockets are kept in blocking mode in the negotiation phase.  After
76daa3
@@ -105,12 +111,32 @@ static inline ssize_t read_sync(QIOChannel *ioc, void *buffer, size_t size)
76daa3
     return nbd_wr_syncv(ioc, &iov, 1, size, true);
76daa3
 }
76daa3
 
76daa3
-static inline ssize_t write_sync(QIOChannel *ioc, const void *buffer,
76daa3
-                                 size_t size)
76daa3
+/* read_sync
76daa3
+ * Reads @size bytes from @ioc. Returns 0 on success.
76daa3
+ */
76daa3
+static inline int read_sync(QIOChannel *ioc, void *buffer, size_t size)
76daa3
+{
76daa3
+    ssize_t ret = read_sync_eof(ioc, buffer, size);
76daa3
+
76daa3
+    if (ret >= 0 && ret != size) {
76daa3
+        ret = -EINVAL;
76daa3
+    }
76daa3
+
76daa3
+    return ret < 0 ? ret : 0;
76daa3
+}
76daa3
+
76daa3
+/* write_sync
76daa3
+ * Writes @size bytes to @ioc. Returns 0 on success.
76daa3
+ */
76daa3
+static inline int write_sync(QIOChannel *ioc, const void *buffer, size_t size)
76daa3
 {
76daa3
     struct iovec iov = { .iov_base = (void *) buffer, .iov_len = size };
76daa3
 
76daa3
-    return nbd_wr_syncv(ioc, &iov, 1, size, false);
76daa3
+    ssize_t ret = nbd_wr_syncv(ioc, &iov, 1, size, false);
76daa3
+
76daa3
+    assert(ret < 0 || ret == size);
76daa3
+
76daa3
+    return ret < 0 ? ret : 0;
76daa3
 }
76daa3
 
76daa3
 struct NBDTLSHandshakeData {
76daa3
diff --git a/nbd/server.c b/nbd/server.c
76daa3
index a98bb21..b44cbe6 100644
76daa3
--- a/nbd/server.c
76daa3
+++ b/nbd/server.c
76daa3
@@ -112,7 +112,7 @@ static gboolean nbd_negotiate_continue(QIOChannel *ioc,
76daa3
     return TRUE;
76daa3
 }
76daa3
 
76daa3
-static ssize_t nbd_negotiate_read(QIOChannel *ioc, void *buffer, size_t size)
76daa3
+static int nbd_negotiate_read(QIOChannel *ioc, void *buffer, size_t size)
76daa3
 {
76daa3
     ssize_t ret;
76daa3
     guint watch;
76daa3
@@ -130,8 +130,7 @@ static ssize_t nbd_negotiate_read(QIOChannel *ioc, void *buffer, size_t size)
76daa3
 
76daa3
 }
76daa3
 
76daa3
-static ssize_t nbd_negotiate_write(QIOChannel *ioc, const void *buffer,
76daa3
-                                   size_t size)
76daa3
+static int nbd_negotiate_write(QIOChannel *ioc, const void *buffer, size_t size)
76daa3
 {
76daa3
     ssize_t ret;
76daa3
     guint watch;
76daa3
@@ -148,24 +147,24 @@ static ssize_t nbd_negotiate_write(QIOChannel *ioc, const void *buffer,
76daa3
     return ret;
76daa3
 }
76daa3
 
76daa3
-static ssize_t nbd_negotiate_drop_sync(QIOChannel *ioc, size_t size)
76daa3
+static int nbd_negotiate_drop_sync(QIOChannel *ioc, size_t size)
76daa3
 {
76daa3
-    ssize_t ret, dropped = size;
76daa3
+    ssize_t ret;
76daa3
     uint8_t *buffer = g_malloc(MIN(65536, size));
76daa3
 
76daa3
     while (size > 0) {
76daa3
-        ret = nbd_negotiate_read(ioc, buffer, MIN(65536, size));
76daa3
+        size_t count = MIN(65536, size);
76daa3
+        ret = nbd_negotiate_read(ioc, buffer, count);
76daa3
         if (ret < 0) {
76daa3
             g_free(buffer);
76daa3
             return ret;
76daa3
         }
76daa3
 
76daa3
-        assert(ret <= size);
76daa3
-        size -= ret;
76daa3
+        size -= count;
76daa3
     }
76daa3
 
76daa3
     g_free(buffer);
76daa3
-    return dropped;
76daa3
+    return 0;
76daa3
 }
76daa3
 
76daa3
 /* Basic flow for negotiation
76daa3
@@ -206,22 +205,22 @@ static int nbd_negotiate_send_rep_len(QIOChannel *ioc, uint32_t type,
76daa3
           type, opt, len);
76daa3
 
76daa3
     magic = cpu_to_be64(NBD_REP_MAGIC);
76daa3
-    if (nbd_negotiate_write(ioc, &magic, sizeof(magic)) != sizeof(magic)) {
76daa3
+    if (nbd_negotiate_write(ioc, &magic, sizeof(magic)) < 0) {
76daa3
         LOG("write failed (rep magic)");
76daa3
         return -EINVAL;
76daa3
     }
76daa3
     opt = cpu_to_be32(opt);
76daa3
-    if (nbd_negotiate_write(ioc, &opt, sizeof(opt)) != sizeof(opt)) {
76daa3
+    if (nbd_negotiate_write(ioc, &opt, sizeof(opt)) < 0) {
76daa3
         LOG("write failed (rep opt)");
76daa3
         return -EINVAL;
76daa3
     }
76daa3
     type = cpu_to_be32(type);
76daa3
-    if (nbd_negotiate_write(ioc, &type, sizeof(type)) != sizeof(type)) {
76daa3
+    if (nbd_negotiate_write(ioc, &type, sizeof(type)) < 0) {
76daa3
         LOG("write failed (rep type)");
76daa3
         return -EINVAL;
76daa3
     }
76daa3
     len = cpu_to_be32(len);
76daa3
-    if (nbd_negotiate_write(ioc, &len, sizeof(len)) != sizeof(len)) {
76daa3
+    if (nbd_negotiate_write(ioc, &len, sizeof(len)) < 0) {
76daa3
         LOG("write failed (rep data length)");
76daa3
         return -EINVAL;
76daa3
     }
76daa3
@@ -256,7 +255,7 @@ nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type,
76daa3
     if (ret < 0) {
76daa3
         goto out;
76daa3
     }
76daa3
-    if (nbd_negotiate_write(ioc, msg, len) != len) {
76daa3
+    if (nbd_negotiate_write(ioc, msg, len) < 0) {
76daa3
         LOG("write failed (error message)");
76daa3
         ret = -EIO;
76daa3
     } else {
76daa3
@@ -287,15 +286,15 @@ static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp)
76daa3
     }
76daa3
 
76daa3
     len = cpu_to_be32(name_len);
76daa3
-    if (nbd_negotiate_write(ioc, &len, sizeof(len)) != sizeof(len)) {
76daa3
+    if (nbd_negotiate_write(ioc, &len, sizeof(len)) < 0) {
76daa3
         LOG("write failed (name length)");
76daa3
         return -EINVAL;
76daa3
     }
76daa3
-    if (nbd_negotiate_write(ioc, name, name_len) != name_len) {
76daa3
+    if (nbd_negotiate_write(ioc, name, name_len) < 0) {
76daa3
         LOG("write failed (name buffer)");
76daa3
         return -EINVAL;
76daa3
     }
76daa3
-    if (nbd_negotiate_write(ioc, desc, desc_len) != desc_len) {
76daa3
+    if (nbd_negotiate_write(ioc, desc, desc_len) < 0) {
76daa3
         LOG("write failed (description buffer)");
76daa3
         return -EINVAL;
76daa3
     }
76daa3
@@ -309,7 +308,7 @@ static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length)
76daa3
     NBDExport *exp;
76daa3
 
76daa3
     if (length) {
76daa3
-        if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
76daa3
+        if (nbd_negotiate_drop_sync(client->ioc, length) < 0) {
76daa3
             return -EIO;
76daa3
         }
76daa3
         return nbd_negotiate_send_rep_err(client->ioc,
76daa3
@@ -340,7 +339,7 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length)
76daa3
         LOG("Bad length received");
76daa3
         goto fail;
76daa3
     }
76daa3
-    if (nbd_negotiate_read(client->ioc, name, length) != length) {
76daa3
+    if (nbd_negotiate_read(client->ioc, name, length) < 0) {
76daa3
         LOG("read failed");
76daa3
         goto fail;
76daa3
     }
76daa3
@@ -373,7 +372,7 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
76daa3
     TRACE("Setting up TLS");
76daa3
     ioc = client->ioc;
76daa3
     if (length) {
76daa3
-        if (nbd_negotiate_drop_sync(ioc, length) != length) {
76daa3
+        if (nbd_negotiate_drop_sync(ioc, length) < 0) {
76daa3
             return NULL;
76daa3
         }
76daa3
         nbd_negotiate_send_rep_err(ioc, NBD_REP_ERR_INVALID, NBD_OPT_STARTTLS,
76daa3
@@ -437,8 +436,7 @@ static int nbd_negotiate_options(NBDClient *client)
76daa3
         ...           Rest of request
76daa3
     */
76daa3
 
76daa3
-    if (nbd_negotiate_read(client->ioc, &flags, sizeof(flags)) !=
76daa3
-        sizeof(flags)) {
76daa3
+    if (nbd_negotiate_read(client->ioc, &flags, sizeof(flags)) < 0) {
76daa3
         LOG("read failed");
76daa3
         return -EIO;
76daa3
     }
76daa3
@@ -464,8 +462,7 @@ static int nbd_negotiate_options(NBDClient *client)
76daa3
         uint32_t clientflags, length;
76daa3
         uint64_t magic;
76daa3
 
76daa3
-        if (nbd_negotiate_read(client->ioc, &magic, sizeof(magic)) !=
76daa3
-            sizeof(magic)) {
76daa3
+        if (nbd_negotiate_read(client->ioc, &magic, sizeof(magic)) < 0) {
76daa3
             LOG("read failed");
76daa3
             return -EINVAL;
76daa3
         }
76daa3
@@ -476,14 +473,14 @@ static int nbd_negotiate_options(NBDClient *client)
76daa3
         }
76daa3
 
76daa3
         if (nbd_negotiate_read(client->ioc, &clientflags,
76daa3
-                               sizeof(clientflags)) != sizeof(clientflags)) {
76daa3
+                               sizeof(clientflags)) < 0)
76daa3
+        {
76daa3
             LOG("read failed");
76daa3
             return -EINVAL;
76daa3
         }
76daa3
         clientflags = be32_to_cpu(clientflags);
76daa3
 
76daa3
-        if (nbd_negotiate_read(client->ioc, &length, sizeof(length)) !=
76daa3
-            sizeof(length)) {
76daa3
+        if (nbd_negotiate_read(client->ioc, &length, sizeof(length)) < 0) {
76daa3
             LOG("read failed");
76daa3
             return -EINVAL;
76daa3
         }
76daa3
@@ -513,7 +510,7 @@ static int nbd_negotiate_options(NBDClient *client)
76daa3
                 return -EINVAL;
76daa3
 
76daa3
             default:
76daa3
-                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
76daa3
+                if (nbd_negotiate_drop_sync(client->ioc, length) < 0) {
76daa3
                     return -EIO;
76daa3
                 }
76daa3
                 ret = nbd_negotiate_send_rep_err(client->ioc,
76daa3
@@ -551,7 +548,7 @@ static int nbd_negotiate_options(NBDClient *client)
76daa3
                 return nbd_negotiate_handle_export_name(client, length);
76daa3
 
76daa3
             case NBD_OPT_STARTTLS:
76daa3
-                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
76daa3
+                if (nbd_negotiate_drop_sync(client->ioc, length) < 0) {
76daa3
                     return -EIO;
76daa3
                 }
76daa3
                 if (client->tlscreds) {
76daa3
@@ -570,7 +567,7 @@ static int nbd_negotiate_options(NBDClient *client)
76daa3
                 }
76daa3
                 break;
76daa3
             default:
76daa3
-                if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
76daa3
+                if (nbd_negotiate_drop_sync(client->ioc, length) < 0) {
76daa3
                     return -EIO;
76daa3
                 }
76daa3
                 ret = nbd_negotiate_send_rep_err(client->ioc,
76daa3
@@ -659,12 +656,12 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
76daa3
             TRACE("TLS cannot be enabled with oldstyle protocol");
76daa3
             goto fail;
76daa3
         }
76daa3
-        if (nbd_negotiate_write(client->ioc, buf, sizeof(buf)) != sizeof(buf)) {
76daa3
+        if (nbd_negotiate_write(client->ioc, buf, sizeof(buf)) < 0) {
76daa3
             LOG("write failed");
76daa3
             goto fail;
76daa3
         }
76daa3
     } else {
76daa3
-        if (nbd_negotiate_write(client->ioc, buf, 18) != 18) {
76daa3
+        if (nbd_negotiate_write(client->ioc, buf, 18) < 0) {
76daa3
             LOG("write failed");
76daa3
             goto fail;
76daa3
         }
76daa3
@@ -679,7 +676,7 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
76daa3
         stq_be_p(buf + 18, client->exp->size);
76daa3
         stw_be_p(buf + 26, client->exp->nbdflags | myflags);
76daa3
         len = client->no_zeroes ? 10 : sizeof(buf) - 18;
76daa3
-        if (nbd_negotiate_write(client->ioc, buf + 18, len) != len) {
76daa3
+        if (nbd_negotiate_write(client->ioc, buf + 18, len) < 0) {
76daa3
             LOG("write failed");
76daa3
             goto fail;
76daa3
         }
76daa3
@@ -702,11 +699,6 @@ static ssize_t nbd_receive_request(QIOChannel *ioc, NBDRequest *request)
76daa3
         return ret;
76daa3
     }
76daa3
 
76daa3
-    if (ret != sizeof(buf)) {
76daa3
-        LOG("read failed");
76daa3
-        return -EINVAL;
76daa3
-    }
76daa3
-
76daa3
     /* Request
76daa3
        [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
76daa3
        [ 4 ..  5]   flags   (NBD_CMD_FLAG_FUA, ...)
76daa3
@@ -737,7 +729,6 @@ static ssize_t nbd_receive_request(QIOChannel *ioc, NBDRequest *request)
76daa3
 static ssize_t nbd_send_reply(QIOChannel *ioc, NBDReply *reply)
76daa3
 {
76daa3
     uint8_t buf[NBD_REPLY_SIZE];
76daa3
-    ssize_t ret;
76daa3
 
76daa3
     reply->error = system_errno_to_nbd_errno(reply->error);
76daa3
 
76daa3
@@ -754,16 +745,7 @@ static ssize_t nbd_send_reply(QIOChannel *ioc, NBDReply *reply)
76daa3
     stl_be_p(buf + 4, reply->error);
76daa3
     stq_be_p(buf + 8, reply->handle);
76daa3
 
76daa3
-    ret = write_sync(ioc, buf, sizeof(buf));
76daa3
-    if (ret < 0) {
76daa3
-        return ret;
76daa3
-    }
76daa3
-
76daa3
-    if (ret != sizeof(buf)) {
76daa3
-        LOG("writing to socket failed");
76daa3
-        return -EINVAL;
76daa3
-    }
76daa3
-    return 0;
76daa3
+    return write_sync(ioc, buf, sizeof(buf));
76daa3
 }
76daa3
 
76daa3
 #define MAX_NBD_REQUESTS 16
76daa3
@@ -1067,7 +1049,7 @@ static ssize_t nbd_co_send_reply(NBDRequestData *req, NBDReply *reply,
76daa3
         rc = nbd_send_reply(client->ioc, reply);
76daa3
         if (rc >= 0) {
76daa3
             ret = write_sync(client->ioc, req->data, len);
76daa3
-            if (ret != len) {
76daa3
+            if (ret < 0) {
76daa3
                 rc = -EIO;
76daa3
             }
76daa3
         }
76daa3
@@ -1141,7 +1123,7 @@ static ssize_t nbd_co_receive_request(NBDRequestData *req,
76daa3
     if (request->type == NBD_CMD_WRITE) {
76daa3
         TRACE("Reading %" PRIu32 " byte(s)", request->len);
76daa3
 
76daa3
-        if (read_sync(client->ioc, req->data, request->len) != request->len) {
76daa3
+        if (read_sync(client->ioc, req->data, request->len) < 0) {
76daa3
             LOG("reading from socket failed");
76daa3
             rc = -EIO;
76daa3
             goto out;
76daa3
-- 
76daa3
1.8.3.1
76daa3