qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v1 03/22] migration: ensure qemu_fflush() always


From: Daniel P. Berrange
Subject: Re: [Qemu-devel] [PATCH v1 03/22] migration: ensure qemu_fflush() always writes full data amount
Date: Wed, 3 Feb 2016 13:31:46 +0000
User-agent: Mutt/1.5.24 (2015-08-30)

On Thu, Jan 28, 2016 at 05:53:46PM +0000, Dr. David Alan Gilbert wrote:
> * Daniel P. Berrange (address@hidden) wrote:
> > The QEMUFile writev_buffer / put_buffer functions are expected
> > to write out the full set of requested data, blocking until
> > complete. The qemu_fflush() caller does not expect to deal with
> > partial writes. Clarify the function comments and add a sanity
> > check to the code to catch mistaken implementations.
> > 
> > Signed-off-by: Daniel P. Berrange <address@hidden>
> > ---
> >  include/migration/qemu-file.h |  6 ++++--
> >  migration/qemu-file.c         | 16 ++++++++++++----
> >  2 files changed, 16 insertions(+), 6 deletions(-)
> > 
> > diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
> > index b5d08d2..5debe8c 100644
> > --- a/include/migration/qemu-file.h
> > +++ b/include/migration/qemu-file.h
> > @@ -29,7 +29,8 @@
> >  
> >  /* This function writes a chunk of data to a file at the given position.
> >   * The pos argument can be ignored if the file is only being used for
> > - * streaming.  The handler should try to write all of the data it can.
> > + * streaming.  The handler must write all of the data or return a negative
> > + * errno value.
> >   */
> >  typedef ssize_t (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf,
> >                                          int64_t pos, size_t size);
> > @@ -55,7 +56,8 @@ typedef int (QEMUFileCloseFunc)(void *opaque);
> >  typedef int (QEMUFileGetFD)(void *opaque);
> >  
> >  /*
> > - * This function writes an iovec to file.
> > + * This function writes an iovec to file. The handler must write all
> > + * of the data or return a negative errno value.
> >   */
> >  typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque, struct iovec *iov,
> >                                             int iovcnt, int64_t pos);
> > diff --git a/migration/qemu-file.c b/migration/qemu-file.c
> > index 0bbd257..f89e64e 100644
> > --- a/migration/qemu-file.c
> > +++ b/migration/qemu-file.c
> > @@ -107,11 +107,13 @@ bool qemu_file_is_writable(QEMUFile *f)
> >   * Flushes QEMUFile buffer
> >   *
> >   * If there is writev_buffer QEMUFileOps it uses it otherwise uses
> > - * put_buffer ops.
> > + * put_buffer ops. This will flush all pending data. If data was
> > + * only partially flushed, it will set an error state.
> >   */
> >  void qemu_fflush(QEMUFile *f)
> >  {
> >      ssize_t ret = 0;
> > +    ssize_t expect = 0;
> >  
> >      if (!qemu_file_is_writable(f)) {
> >          return;
> > @@ -119,21 +121,27 @@ void qemu_fflush(QEMUFile *f)
> >  
> >      if (f->ops->writev_buffer) {
> >          if (f->iovcnt > 0) {
> > +            expect = iov_size(f->iov, f->iovcnt);
> >              ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, 
> > f->pos);
> >          }
> >      } else {
> >          if (f->buf_index > 0) {
> > +            expect = f->buf_index;
> >              ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, 
> > f->buf_index);
> >          }
> >      }
> > +
> >      if (ret >= 0) {
> >          f->pos += ret;
> >      }
> > -    f->buf_index = 0;
> > -    f->iovcnt = 0;
> > -    if (ret < 0) {
> > +    /* We expect the QEMUFile write impl to send the full
> > +     * data set we requested, so sanity check that.
> > +     */
> > +    if (ret < 0 || ret != expect) {
> >          qemu_file_set_error(f, ret);
> 
> You could simplify that to     if (ret != expect)     couldn't you?
> 
> In the case you're trying to guard against, the value past
> to qemu_file_set_error is potentially truncated; which in the worst
> case could make it appear as success; although I doubt that
> can happen in our uses.

qemu_file_set_error expects an errni, so in fact my code was
buggy if the ret != expect part got evaluated, so I'll change
this to

     if (ret != expect) {
        qemu_file_set_error(f, ret < 0 ? ret : -EIO);
     }


> 
> Reviewed-by: Dr. David Alan Gilbert <address@hidden>

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|



reply via email to

[Prev in Thread] Current Thread [Next in Thread]