From 3ed7fcacd9951153c9b935714282369abf0405c2 Mon Sep 17 00:00:00 2001 Message-Id: <3ed7fcacd9951153c9b935714282369abf0405c2.1368111914.git.minovotn@redhat.com> In-Reply-To: <405603258af5154387bea676be1f904b6713f6ae.1368111913.git.minovotn@redhat.com> References: <405603258af5154387bea676be1f904b6713f6ae.1368111913.git.minovotn@redhat.com> From: Amit Shah Date: Wed, 24 Apr 2013 08:18:22 +0200 Subject: [PATCH 48/65] qemu-char: rewrite io_channel_send_all and drop the '_all' suffix RH-Author: Amit Shah Message-id: Patchwork-id: 50826 O-Subject: [RHEL6.5 qemu-kvm PATCH 48/65] qemu-char: rewrite io_channel_send_all and drop the '_all' suffix Bugzilla: 909059 RH-Acked-by: Hans de Goede RH-Acked-by: Gerd Hoffmann RH-Acked-by: Paolo Bonzini From: Anthony Liguori The current code is oddly written and have equally odd semantics. Despite the '_all' suffix, upon EAGAIN the result will be a partial write but instead of returning the partial write, we return EAGAIN. Change the behavior to write as much as we can until we get an EAGAIN returning a partial write if we do. Reported-by: Amit Shah Signed-off-by: Anthony Liguori Message-id: 1364575190-731-1-git-send-email-aliguori@us.ibm.com (cherry picked from commit 684a096eafbe37ab6c9a1fdb5e0185f04098b166) Signed-off-by: Amit Shah --- qemu-char.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) Signed-off-by: Michal Novotny --- qemu-char.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 3ef2ae4..adc2bb3 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -672,33 +672,37 @@ static GIOChannel *io_channel_from_socket(int fd) return chan; } -static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1) +static int io_channel_send(GIOChannel *fd, const void *buf, size_t len) { GIOStatus status; - gsize bytes_written; - int len; - const uint8_t *buf = _buf; + size_t offset; - len = len1; - while (len > 0) { - status = g_io_channel_write_chars(fd, (const gchar *)buf, len, + offset = 0; + while (offset < len) { + gsize bytes_written; + + status = g_io_channel_write_chars(fd, buf + offset, len - offset, &bytes_written, NULL); if (status != G_IO_STATUS_NORMAL) { if (status == G_IO_STATUS_AGAIN) { + /* If we've written any data, return a partial write. */ + if (offset) { + break; + } errno = EAGAIN; - return -1; } else { errno = EINVAL; - return -1; } + + return -1; } else if (status == G_IO_STATUS_EOF) { break; - } else { - buf += bytes_written; - len -= bytes_written; } + + offset += bytes_written; } - return len1 - len; + + return offset; } typedef struct FDCharDriver { @@ -713,7 +717,7 @@ static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { FDCharDriver *s = chr->opaque; - return io_channel_send_all(s->fd_out, buf, len); + return io_channel_send(s->fd_out, buf, len); } static gboolean fd_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) @@ -1033,7 +1037,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) pty_chr_update_read_handler(chr); return 0; } - return io_channel_send_all(s->fd, buf, len); + return io_channel_send(s->fd, buf, len); } static GSource *pty_chr_add_watch(CharDriverState *chr, GIOCondition cond) @@ -2120,7 +2124,7 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { TCPCharDriver *s = chr->opaque; if (s->connected) { - return io_channel_send_all(s->chan, buf, len); + return io_channel_send(s->chan, buf, len); } else { /* XXX: indicate an error ? */ return len; -- 1.7.11.7