qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com>
To: qemu-devel@nongnu.org
Cc: quintela@redhat.com
Subject: [Qemu-devel] [PATCH 1/1] Make qemu_peek_buffer loop until it gets it's data
Date: Thu, 20 Mar 2014 12:58:47 +0000	[thread overview]
Message-ID: <1395320327-16613-1-git-send-email-dgilbert@redhat.com> (raw)

From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

Make qemu_peek_buffer repatedly 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.

Ditto for qemu_peek_byte (which can only be affected due to it's
offset).

Simplify qemu_get_buffer since it can now rely on qemu_peek_buffer to
loop.

Use size_t rather than int for size parameters, (and result for
those functions that never return -errno).

Fail vmstate_subsection_load if idstr couldn't be peek'd

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
 include/migration/qemu-file.h |  6 ++--
 qemu-file.c                   | 64 +++++++++++++++++++++++++++----------------
 vmstate.c                     |  2 +-
 3 files changed, 44 insertions(+), 28 deletions(-)

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index a191fb6..cc45c87 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -121,11 +121,11 @@ static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v)
 void qemu_put_be16(QEMUFile *f, unsigned int v);
 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);
+size_t qemu_peek_buffer(QEMUFile *f, uint8_t *buf, size_t size, size_t offset);
+size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size);
 int qemu_peek_byte(QEMUFile *f, int offset);
 int qemu_get_byte(QEMUFile *f);
-void qemu_file_skip(QEMUFile *f, int size);
+void qemu_file_skip(QEMUFile *f, size_t size);
 void qemu_update_position(QEMUFile *f, size_t size);
 
 static inline unsigned int qemu_get_ubyte(QEMUFile *f)
diff --git a/qemu-file.c b/qemu-file.c
index e5ec798..eb388a7 100644
--- a/qemu-file.c
+++ b/qemu-file.c
@@ -529,7 +529,11 @@ 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 -ve value for an error.
+ */
+static int qemu_fill_buffer(QEMUFile *f)
 {
     int len;
     int pending;
@@ -553,6 +557,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)
@@ -676,24 +682,41 @@ void qemu_put_byte(QEMUFile *f, int v)
     }
 }
 
-void qemu_file_skip(QEMUFile *f, int size)
+void qemu_file_skip(QEMUFile *f, size_t size)
 {
     if (f->buf_index + size <= f->buf_size) {
         f->buf_index += size;
     }
 }
 
-int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
+/*
+ * Read 'size' bytes from file (at 'offset') into buf without moving the
+ * pointer.
+ *
+ * If the underlying fd blocks, then it will return size bytes
+ * unless there was an error, in which case it will return as many as it
+ * managed to read.
+ */
+size_t qemu_peek_buffer(QEMUFile *f, uint8_t *buf, size_t size, size_t offset)
 {
     int pending;
     int index;
 
     assert(!qemu_file_is_writable(f));
+    assert(offset < IO_BUF_SIZE);
+    assert(size + offset < IO_BUF_SIZE);
 
+    /* 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);
+    while (pending < size) {
+        int received = qemu_fill_buffer(f);
+
+        if (received <= 0) {
+            break;
+        }
+
         index = f->buf_index + offset;
         pending = f->buf_size - index;
     }
@@ -709,24 +732,15 @@ int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
     return size;
 }
 
-int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
+size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size)
 {
-    int pending = size;
-    int done = 0;
+    size_t res;
 
-    while (pending > 0) {
-        int res;
+    res = qemu_peek_buffer(f, buf, size, 0);
 
-        res = qemu_peek_buffer(f, buf, pending, 0);
-        if (res == 0) {
-            return done;
-        }
-        qemu_file_skip(f, res);
-        buf += res;
-        pending -= res;
-        done += res;
-    }
-    return done;
+    qemu_file_skip(f, res);
+
+    return res;
 }
 
 int qemu_peek_byte(QEMUFile *f, int offset)
@@ -735,12 +749,14 @@ int qemu_peek_byte(QEMUFile *f, int offset)
 
     assert(!qemu_file_is_writable(f));
 
-    if (index >= f->buf_size) {
-        qemu_fill_buffer(f);
-        index = f->buf_index + offset;
-        if (index >= f->buf_size) {
+    while (index >= f->buf_size) {
+        int received = qemu_fill_buffer(f);
+
+        if (received <= 0) {
             return 0;
         }
+
+        index = f->buf_index + offset;
     }
     return f->buf[index];
 }
diff --git a/vmstate.c b/vmstate.c
index d1f5eb0..b8e6e31 100644
--- a/vmstate.c
+++ b/vmstate.c
@@ -170,7 +170,7 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
         }
         size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2);
         if (size != len) {
-            return 0;
+            return -EIO;
         }
         idstr[size] = 0;
 
-- 
1.8.5.3

             reply	other threads:[~2014-03-20 12:59 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-20 12:58 Dr. David Alan Gilbert (git) [this message]
2014-03-21 13:24 ` [Qemu-devel] [PATCH 1/1] Make qemu_peek_buffer loop until it gets it's data Juan Quintela
2014-03-21 14:39   ` Dr. David Alan Gilbert
2014-03-21 16:05     ` Juan Quintela
2014-03-21 16:26       ` Dr. David Alan Gilbert
2014-03-21 17:55         ` Juan Quintela

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=1395320327-16613-1-git-send-email-dgilbert@redhat.com \
    --to=dgilbert@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).