aboutsummaryrefslogtreecommitdiff
path: root/migration/qemu-file-unix.c
diff options
context:
space:
mode:
authorDr. David Alan Gilbert <dgilbert@redhat.com>2015-11-05 18:10:44 +0000
committerJuan Quintela <quintela@redhat.com>2015-11-10 15:00:25 +0100
commit3e4097b564386b1fd1b62f2cd20e056d4b3403da (patch)
tree6296a68cabab71cb0ecab0979e53a9cbc1eddda3 /migration/qemu-file-unix.c
parentadc468e9b9ad866cd95b1e567291f9dcc1f49f1c (diff)
downloadqemu-3e4097b564386b1fd1b62f2cd20e056d4b3403da.zip
qemu-3e4097b564386b1fd1b62f2cd20e056d4b3403da.tar.gz
qemu-3e4097b564386b1fd1b62f2cd20e056d4b3403da.tar.bz2
Return path: socket_writev_buffer: Block even on non-blocking fd's
The destination sets the fd to non-blocking on incoming migrations; this also affects the return path from the destination, and thus we need to make sure we can safely write to the return path. Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Amit Shah <amit.shah@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Signed-off-by: Juan Quintela <quintela@redhat.com>
Diffstat (limited to 'migration/qemu-file-unix.c')
-rw-r--r--migration/qemu-file-unix.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/migration/qemu-file-unix.c b/migration/qemu-file-unix.c
index bcb744b..c503b02 100644
--- a/migration/qemu-file-unix.c
+++ b/migration/qemu-file-unix.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "qemu-common.h"
+#include "qemu/error-report.h"
#include "qemu/iov.h"
#include "qemu/sockets.h"
#include "qemu/coroutine.h"
@@ -39,12 +40,43 @@ static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
QEMUFileSocket *s = opaque;
ssize_t len;
ssize_t size = iov_size(iov, iovcnt);
+ ssize_t offset = 0;
+ int err;
- len = iov_send(s->fd, iov, iovcnt, 0, size);
- if (len < size) {
- len = -socket_error();
- }
- return len;
+ while (size > 0) {
+ len = iov_send(s->fd, iov, iovcnt, offset, size);
+
+ if (len > 0) {
+ size -= len;
+ offset += len;
+ }
+
+ if (size > 0) {
+ err = socket_error();
+
+ if (err != EAGAIN && err != EWOULDBLOCK) {
+ error_report("socket_writev_buffer: Got err=%d for (%zu/%zu)",
+ err, (size_t)size, (size_t)len);
+ /*
+ * If I've already sent some but only just got the error, I
+ * could return the amount validly sent so far and wait for the
+ * next call to report the error, but I'd rather flag the error
+ * immediately.
+ */
+ return -err;
+ }
+
+ /* Emulate blocking */
+ GPollFD pfd;
+
+ pfd.fd = s->fd;
+ pfd.events = G_IO_OUT | G_IO_ERR;
+ pfd.revents = 0;
+ g_poll(&pfd, 1 /* 1 fd */, -1 /* no timeout */);
+ }
+ }
+
+ return offset;
}
static int socket_get_fd(void *opaque)