summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorDan McGee <dpmcgee@gmail.com>2012-02-16 23:30:12 -0600
committerAlon Levy <alevy@redhat.com>2012-02-21 10:20:46 +0200
commitbdfd6c234bca76232f4bac308fc21321ebba7f1a (patch)
tree07ff0c118827f6a39c8a046ae0820ec6e33cb1ae /server
parent143a1df24e83e9c1e173c16aeb76d61ffdce9598 (diff)
downloadspice-bdfd6c234bca76232f4bac308fc21321ebba7f1a.tar.gz
spice-bdfd6c234bca76232f4bac308fc21321ebba7f1a.tar.xz
spice-bdfd6c234bca76232f4bac308fc21321ebba7f1a.zip
Respect IOV_MAX if defined
Solaris has a pitiful maximum writev vector size of only 16, so the ping request at initial startup destroyed this call and broke things immediately. Reimplement stream_writev_cb() to respect IOV_MAX and break the writev() calls into chunks as necessary. Care was taken to return the correct values as necessary so the EAGAIN handling logic can determine where to resume the writev call the next time around. Signed-off-by: Dan McGee <dpmcgee@gmail.com>
Diffstat (limited to 'server')
-rw-r--r--server/reds.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/server/reds.c b/server/reds.c
index 250e0ca4..797d9d52 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
+#include <sys/uio.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
@@ -340,7 +341,31 @@ static ssize_t stream_write_cb(RedsStream *s, const void *buf, size_t size)
static ssize_t stream_writev_cb(RedsStream *s, const struct iovec *iov, int iovcnt)
{
- return writev(s->socket, iov, iovcnt);
+ ssize_t ret = 0;
+ do {
+ int tosend;
+ ssize_t n, expected = 0;
+ int i;
+#ifdef IOV_MAX
+ tosend = MIN(iovcnt, IOV_MAX);
+#else
+ tosend = iovcnt;
+#endif
+ for (i = 0; i < tosend; i++) {
+ expected += iov[i].iov_len;
+ }
+ n = writev(s->socket, iov, tosend);
+ if (n <= expected) {
+ if (n > 0)
+ ret += n;
+ return ret == 0 ? n : ret;
+ }
+ ret += n;
+ iov += tosend;
+ iovcnt -= tosend;
+ } while(iovcnt > 0);
+
+ return ret;
}
static ssize_t stream_read_cb(RedsStream *s, void *buf, size_t size)