summaryrefslogtreecommitdiff
path: root/qemu-file.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-05-07 14:51:21 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-05-07 14:51:21 +0100
commitc9541f67df48b2c01c4a3d0d7b719b51c6ac9f38 (patch)
treef8ad04d1c144321bc43dcee27f0cf29c8c8f837f /qemu-file.c
parent7f8fea8b3d31ca396eb3c88bf97b543a86773774 (diff)
parent8bc3923343e91902ca541112b3bdb5448f8d288e (diff)
downloadqemu-c9541f67df48b2c01c4a3d0d7b719b51c6ac9f38.tar.gz
Merge remote-tracking branch 'remotes/juanquintela/tags/migration/20140505' into staging
migration/next for 20140505 # gpg: Signature made Mon 05 May 2014 21:27:24 BST using RSA key ID 5872D723 # gpg: Can't check signature: public key not found * remotes/juanquintela/tags/migration/20140505: (36 commits) migration: expose xbzrle cache miss rate migration: expose the bitmap_sync_count to the end migration: Add counts of updating the dirty bitmap XBZRLE: Fix one XBZRLE corruption issues migration: remove duplicate code Coverity: Fix failure path for qemu_accept in migration Init the XBZRLE.lock in ram_mig_init Provide init function for ram migration Count used RAMBlock pages for migration_dirty_pages Make qemu_peek_buffer loop until it gets it's data Disallow outward migration while awaiting incoming migration virtio: validate config_len on load virtio-net: out-of-bounds buffer write on load openpic: avoid buffer overrun on incoming migration ssi-sd: fix buffer overrun on invalid state load savevm: Ignore minimum_version_id_old if there is no load_state_old usb: sanity check setup_index+setup_len in post_load vmstate: s/VMSTATE_INT32_LE/VMSTATE_INT32_POSITIVE_LE/ virtio-scsi: fix buffer overrun on invalid state load zaurus: fix buffer overrun on invalid state load ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'qemu-file.c')
-rw-r--r--qemu-file.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/qemu-file.c b/qemu-file.c
index 8d5f45dcb0..a8e39127f2 100644
--- a/qemu-file.c
+++ b/qemu-file.c
@@ -530,7 +530,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;
@@ -554,6 +562,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)
@@ -685,17 +695,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;
}
@@ -711,6 +743,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;
@@ -719,7 +759,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;
}
@@ -731,11 +771,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);