Paolo Bonzini <pbonz...@redhat.com> writes: > This uses system calls directly for Unix file descriptors, so that the > efficient writev_buffer can be used. Pay attention to the possibility > of partial writes in writev. > > Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
Needs rebasing: CC i386-softmmu/savevm.o /home/aliguori/git/qemu/savevm.c:439:5: error: initialization from incompatible pointer type [-Werror] /home/aliguori/git/qemu/savevm.c:439:5: error: (near initialization for ‘unix_write_ops.writev_buffer’) [-Werror] cc1: all warnings being treated as errors make[1]: *** [savevm.o] Error 1 make: *** [subdir-i386-softmmu] Error 2 d13ed415c0ab9f7cf29226022f8c24d1b8dc794d is the first bad commit commit d13ed415c0ab9f7cf29226022f8c24d1b8dc794d Author: Paolo Bonzini <pbonz...@redhat.com> Date: Wed Mar 27 17:36:32 2013 +0100 qemu-file: do not use stdio for qemu_fdopen Regards, Anthony Liguori > --- > savevm.c | 100 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 89 insertions(+), 11 deletions(-) > > diff --git a/savevm.c b/savevm.c > index 0415830..8eb5aab 100644 > --- a/savevm.c > +++ b/savevm.c > @@ -356,9 +356,93 @@ static const QEMUFileOps stdio_file_write_ops = { > .close = stdio_fclose > }; > > +static ssize_t unix_writev_buffer(void *opaque, struct iovec *iov, int > iovcnt) > +{ > + QEMUFileSocket *s = opaque; > + ssize_t len, offset; > + ssize_t size = iov_size(iov, iovcnt); > + ssize_t total = 0; > + > + assert(iovcnt > 0); > + offset = 0; > + while (size > 0) { > + /* Find the next start position; skip all full-sized vector elements > */ > + while (offset >= iov[0].iov_len) { > + offset -= iov[0].iov_len; > + iov++, iovcnt--; > + } > + > + /* skip `offset' bytes from the (now) first element, undo it on exit > */ > + assert(iovcnt > 0); > + iov[0].iov_base += offset; > + iov[0].iov_len -= offset; > + > + do { > + len = writev(s->fd, iov, iovcnt); > + } while (len == -1 && errno == EINTR); > + if (len == -1) { > + return -errno; > + } > + > + /* Undo the changes above */ > + iov[0].iov_base -= offset; > + iov[0].iov_len += offset; > + > + /* Prepare for the next iteration */ > + offset += len; > + total += len; > + size -= len; > + } > + > + return total; > +} > + > +static int unix_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) > +{ > + QEMUFileSocket *s = opaque; > + ssize_t len; > + > + for (;;) { > + len = read(s->fd, buf, size); > + if (len != -1) { > + break; > + } > + if (errno == EAGAIN) { > + yield_until_fd_readable(s->fd); > + } else if (errno != EINTR) { > + break; > + } > + } > + > + if (len == -1) { > + len = -errno; > + } > + return len; > +} > + > +static int unix_close(void *opaque) > +{ > + QEMUFileSocket *s = opaque; > + close(s->fd); > + g_free(s); > + return 0; > +} > + > +static const QEMUFileOps unix_read_ops = { > + .get_fd = socket_get_fd, > + .get_buffer = unix_get_buffer, > + .close = unix_close > +}; > + > +static const QEMUFileOps unix_write_ops = { > + .get_fd = socket_get_fd, > + .writev_buffer = unix_writev_buffer, > + .close = unix_close > +}; > + > QEMUFile *qemu_fdopen(int fd, const char *mode) > { > - QEMUFileStdio *s; > + QEMUFileSocket *s; > > if (mode == NULL || > (mode[0] != 'r' && mode[0] != 'w') || > @@ -367,21 +451,15 @@ QEMUFile *qemu_fdopen(int fd, const char *mode) > return NULL; > } > > - s = g_malloc0(sizeof(QEMUFileStdio)); > - s->stdio_file = fdopen(fd, mode); > - if (!s->stdio_file) > - goto fail; > + s = g_malloc0(sizeof(QEMUFileSocket)); > + s->fd = fd; > > if(mode[0] == 'r') { > - s->file = qemu_fopen_ops(s, &stdio_file_read_ops); > + s->file = qemu_fopen_ops(s, &unix_read_ops); > } else { > - s->file = qemu_fopen_ops(s, &stdio_file_write_ops); > + s->file = qemu_fopen_ops(s, &unix_write_ops); > } > return s->file; > - > -fail: > - g_free(s); > - return NULL; > } > > static const QEMUFileOps socket_read_ops = { > -- > 1.8.1.4