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>
This commit is contained in:
Dr. David Alan Gilbert 2015-11-05 18:10:44 +00:00 committed by Juan Quintela
parent adc468e9b9
commit 3e4097b564

View File

@ -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)