All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
To: ???? <chenliang0016@icloud.com>
Cc: quintela@redhat.com, qemu-devel@nongnu.org, armbru@redhat.com
Subject: Re: [Qemu-devel] [PATCH v4 1/1] Make qemu_peek_buffer loop until it gets it's data
Date: Tue, 8 Apr 2014 17:08:11 +0100	[thread overview]
Message-ID: <20140408160811.GA2505@work-vm> (raw)
In-Reply-To: <E8EF2F0B-69B0-4AD0-BC79-4AAD5EA6921C@icloud.com>

* ???? (chenliang0016@icloud.com) wrote:
> 
> ?? 2014??4??8????????10:29??Dr. David Alan Gilbert (git) <dgilbert@redhat.com> ??????
> 
> > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> > 
> > Make qemu_peek_buffer repeatedly call fill_buffer until it gets
> > all the data it requires, or until there is an error.
> > 
> >  At the moment, qemu_peek_buffer will try one qemu_fill_buffer if there
> >  isn't enough data waiting, however the kernel is entitled to return
> >  just a few bytes, and still leave qemu_peek_buffer with less bytes
> >  than it needed.  I've seen this fail in a dev world, and I think it
> >  could theoretically fail in the peeking of the subsection headers in
> >  the current world.
> hmm, I also have got some errors(infrequently). Maybe It is one point.
> Could you show some messages about the error?

I've only seen the errors in my visitor/ber world where I use the peek_buffer
a lot more; but the one place it is used in the existing code is in
the code to check if we have the start of a subsection; if that goes wrong
I'm not sure what error would be produced.

Dave

> 
> However, this patch avoids one potential issue, thanks.
> 
> Reviewed-by: ChenLiang <chenliang0016@icloud.com>
> > 
> > Comment qemu_peek_byte to point out it's not guaranteed to work for
> >  non-continuous peeks
> > 
> > Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> > ---
> > 
> > v4:
> >  Limit the size qemu_get_buffer passes to qemu_fill_buffer on each loop
> > 
> > v3:
> >  Make qemu_fill_buffer return ssize_t
> >  Remove the other size_t cleanup from this patch - I'll get back to them later
> >  Comment additions/cleanups from review
> >  Stretch my -ve
> > 
> > include/migration/qemu-file.h |  5 ++++
> > qemu-file.c                   | 53 +++++++++++++++++++++++++++++++++++++++----
> > 2 files changed, 54 insertions(+), 4 deletions(-)
> > 
> > diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
> > index a191fb6..c90f529 100644
> > --- a/include/migration/qemu-file.h
> > +++ b/include/migration/qemu-file.h
> > @@ -123,6 +123,11 @@ void qemu_put_be32(QEMUFile *f, unsigned int v);
> > void qemu_put_be64(QEMUFile *f, uint64_t v);
> > int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset);
> > int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size);
> > +/*
> > + * Note that you can only peek continuous bytes from where the current pointer
> > + * is; you aren't guaranteed to be able to peak to +n bytes unless you've
> > + * previously peeked +n-1.
> > + */
> > int qemu_peek_byte(QEMUFile *f, int offset);
> > int qemu_get_byte(QEMUFile *f);
> > void qemu_file_skip(QEMUFile *f, int size);
> > diff --git a/qemu-file.c b/qemu-file.c
> > index e5ec798..6ae37d0 100644
> > --- a/qemu-file.c
> > +++ b/qemu-file.c
> > @@ -529,7 +529,15 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
> >     return RAM_SAVE_CONTROL_NOT_SUPP;
> > }
> > 
> > -static void qemu_fill_buffer(QEMUFile *f)
> > +/*
> > + * Attempt to fill the buffer from the underlying file
> > + * Returns the number of bytes read, or negative value for an error.
> > + *
> > + * Note that it can return a partially full buffer even in a not error/not EOF
> > + * case if the underlying file descriptor gives a short read, and that can
> > + * happen even on a blocking fd.
> > + */
> > +static ssize_t qemu_fill_buffer(QEMUFile *f)
> > {
> >     int len;
> >     int pending;
> > @@ -553,6 +561,8 @@ static void qemu_fill_buffer(QEMUFile *f)
> >     } else if (len != -EAGAIN) {
> >         qemu_file_set_error(f, len);
> >     }
> > +
> > +    return len;
> > }
> > 
> > int qemu_get_fd(QEMUFile *f)
> > @@ -683,17 +693,39 @@ void qemu_file_skip(QEMUFile *f, int size)
> >     }
> > }
> > 
> > +/*
> > + * Read 'size' bytes from file (at 'offset') into buf without moving the
> > + * pointer.
> > + *
> > + * It will return size bytes unless there was an error, in which case it will
> > + * return as many as it managed to read (assuming blocking fd's which
> > + * all current QEMUFile are)
> > + */
> > int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
> > {
> >     int pending;
> >     int index;
> > 
> >     assert(!qemu_file_is_writable(f));
> > +    assert(offset < IO_BUF_SIZE);
> > +    assert(size <= IO_BUF_SIZE - offset);
> > 
> > +    /* The 1st byte to read from */
> >     index = f->buf_index + offset;
> > +    /* The number of available bytes starting at index */
> >     pending = f->buf_size - index;
> > -    if (pending < size) {
> > -        qemu_fill_buffer(f);
> > +
> > +    /*
> > +     * qemu_fill_buffer might return just a few bytes, even when there isn't
> > +     * an error, so loop collecting them until we get enough.
> > +     */
> > +    while (pending < size) {
> > +        int received = qemu_fill_buffer(f);
> > +
> > +        if (received <= 0) {
> > +            break;
> > +        }
> > +
> >         index = f->buf_index + offset;
> >         pending = f->buf_size - index;
> >     }
> > @@ -709,6 +741,14 @@ int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
> >     return size;
> > }
> > 
> > +/*
> > + * Read 'size' bytes of data from the file into buf.
> > + * 'size' can be larger than the internal buffer.
> > + *
> > + * It will return size bytes unless there was an error, in which case it will
> > + * return as many as it managed to read (assuming blocking fd's which
> > + * all current QEMUFile are)
> > + */
> > int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
> > {
> >     int pending = size;
> > @@ -717,7 +757,7 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
> >     while (pending > 0) {
> >         int res;
> > 
> > -        res = qemu_peek_buffer(f, buf, pending, 0);
> > +        res = qemu_peek_buffer(f, buf, MIN(pending, IO_BUF_SIZE), 0);
> >         if (res == 0) {
> >             return done;
> >         }
> > @@ -729,11 +769,16 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
> >     return done;
> > }
> > 
> > +/*
> > + * Peeks a single byte from the buffer; this isn't guaranteed to work if
> > + * offset leaves a gap after the previous read/peeked data.
> > + */
> > int qemu_peek_byte(QEMUFile *f, int offset)
> > {
> >     int index = f->buf_index + offset;
> > 
> >     assert(!qemu_file_is_writable(f));
> > +    assert(offset < IO_BUF_SIZE);
> > 
> >     if (index >= f->buf_size) {
> >         qemu_fill_buffer(f);
> > -- 
> > 1.9.0
> > 
> > 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

  parent reply	other threads:[~2014-04-08 16:08 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-08 14:29 [Qemu-devel] [PATCH v4 1/1] Make qemu_peek_buffer loop until it gets it's data Dr. David Alan Gilbert (git)
     [not found] ` <E8EF2F0B-69B0-4AD0-BC79-4AAD5EA6921C@icloud.com>
2014-04-08 16:08   ` Dr. David Alan Gilbert [this message]
2014-04-09 11:56     ` 陈梁
2014-04-09 11:58       ` Dr. David Alan Gilbert
2014-04-09 12:00         ` 陈梁
2014-04-09 12:59           ` Dr. David Alan Gilbert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140408160811.GA2505@work-vm \
    --to=dgilbert@redhat.com \
    --cc=armbru@redhat.com \
    --cc=chenliang0016@icloud.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.