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:
parent
adc468e9b9
commit
3e4097b564
@ -22,6 +22,7 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/iov.h"
|
#include "qemu/iov.h"
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
#include "qemu/coroutine.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;
|
QEMUFileSocket *s = opaque;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
ssize_t size = iov_size(iov, iovcnt);
|
ssize_t size = iov_size(iov, iovcnt);
|
||||||
|
ssize_t offset = 0;
|
||||||
|
int err;
|
||||||
|
|
||||||
len = iov_send(s->fd, iov, iovcnt, 0, size);
|
while (size > 0) {
|
||||||
if (len < size) {
|
len = iov_send(s->fd, iov, iovcnt, offset, size);
|
||||||
len = -socket_error();
|
|
||||||
|
if (len > 0) {
|
||||||
|
size -= len;
|
||||||
|
offset += len;
|
||||||
}
|
}
|
||||||
return 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)
|
static int socket_get_fd(void *opaque)
|
||||||
|
Loading…
Reference in New Issue
Block a user