summaryrefslogtreecommitdiff
path: root/nbd/nbd-internal.h
diff options
context:
space:
mode:
authorVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>2017-05-16 12:45:30 +0300
committerPaolo Bonzini <pbonzini@redhat.com>2017-06-06 20:18:35 +0200
commitf5d406fe86bb28da85824b6581e58980cc1a07f3 (patch)
tree885a0d7cbd54bb822f3c0185164388b47e4786db /nbd/nbd-internal.h
parentf250a42ddaee042ad2eb02022a3ebd18fcf987de (diff)
downloadqemu-f5d406fe86bb28da85824b6581e58980cc1a07f3.tar.gz
nbd: read_sync and friends: return 0 on success
functions read_sync, drop_sync, write_sync, and also nbd_negotiate_write, nbd_negotiate_read, nbd_negotiate_drop_sync returns number of processed bytes. But what this number can be, except requested number of bytes? Actually, underlying nbd_wr_syncv function returns a value >= 0 and != requested_bytes only on eof on read operation. So, firstly, it is impossible on write (let's add an assert) and on read it actually means, that communication is broken (except nbd_receive_reply, see below). Most of callers operate like this: if (func(..., size) != size) { /* error path */ } , i.e.: 1. They are not interested in partial success 2. Extra duplications in code (especially bad are duplications of magic numbers) 3. User doesn't see actual error message, as return code is lost. (this patch doesn't fix this point, but it makes fixing easier) Several callers handles ret >= 0 and != requested-size separately, by just returning EINVAL in this case. This patch makes read_sync and friends return EINVAL in this case, so final behavior is the same. And only one caller - nbd_receive_reply() does something not so obvious. It returns EINVAL for ret > 0 and != requested-size, like previous group, but for ret == 0 it returns 0. The only caller of nbd_receive_reply() - nbd_read_reply_entry() handles ret == 0 in the same way as ret < 0, so for now it doesn't matter. However, in following commits error path handling will be improved and we'll need to distinguish success from fail in this case too. So, this patch adds separate helper for this case - read_sync_eof. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Message-Id: <20170516094533.6160-3-vsementsov@virtuozzo.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'nbd/nbd-internal.h')
-rw-r--r--nbd/nbd-internal.h34
1 files changed, 30 insertions, 4 deletions
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
index f43d990a05..e6bbc7c4b4 100644
--- a/nbd/nbd-internal.h
+++ b/nbd/nbd-internal.h
@@ -94,7 +94,13 @@
#define NBD_ENOSPC 28
#define NBD_ESHUTDOWN 108
-static inline ssize_t read_sync(QIOChannel *ioc, void *buffer, size_t size)
+/* read_sync_eof
+ * Tries to read @size bytes from @ioc. Returns number of bytes actually read.
+ * May return a value >= 0 and < size only on EOF, i.e. when iteratively called
+ * qio_channel_readv() returns 0. So, there are no needs to call read_sync_eof
+ * iteratively.
+ */
+static inline ssize_t read_sync_eof(QIOChannel *ioc, void *buffer, size_t size)
{
struct iovec iov = { .iov_base = buffer, .iov_len = size };
/* Sockets are kept in blocking mode in the negotiation phase. After
@@ -105,12 +111,32 @@ static inline ssize_t read_sync(QIOChannel *ioc, void *buffer, size_t size)
return nbd_wr_syncv(ioc, &iov, 1, size, true);
}
-static inline ssize_t write_sync(QIOChannel *ioc, const void *buffer,
- size_t size)
+/* read_sync
+ * Reads @size bytes from @ioc. Returns 0 on success.
+ */
+static inline int read_sync(QIOChannel *ioc, void *buffer, size_t size)
+{
+ ssize_t ret = read_sync_eof(ioc, buffer, size);
+
+ if (ret >= 0 && ret != size) {
+ ret = -EINVAL;
+ }
+
+ return ret < 0 ? ret : 0;
+}
+
+/* write_sync
+ * Writes @size bytes to @ioc. Returns 0 on success.
+ */
+static inline int write_sync(QIOChannel *ioc, const void *buffer, size_t size)
{
struct iovec iov = { .iov_base = (void *) buffer, .iov_len = size };
- return nbd_wr_syncv(ioc, &iov, 1, size, false);
+ ssize_t ret = nbd_wr_syncv(ioc, &iov, 1, size, false);
+
+ assert(ret < 0 || ret == size);
+
+ return ret < 0 ? ret : 0;
}
struct NBDTLSHandshakeData {