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: Dr. David Alan Gilbert
Subject: Re: [Qemu-devel] [PATCH v1 03/22] migration: ensure qemu_fflush() always writes full data amount
Date: Thu, 28 Jan 2016 17:53:46 +0000
User-agent: Mutt/1.5.24 (2015-08-30)

* 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.

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

Dave

>      }
> +    f->buf_index = 0;
> +    f->iovcnt = 0;
>  }
>  
>  void ram_control_before_iterate(QEMUFile *f, uint64_t flags)
> -- 
> 2.5.0
> 
--
Dr. David Alan Gilbert / address@hidden / Manchester, UK



reply via email to

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