summaryrefslogtreecommitdiff
path: root/migration/qemu-file.c
diff options
context:
space:
mode:
Diffstat (limited to 'migration/qemu-file.c')
-rw-r--r--migration/qemu-file.c134
1 files changed, 54 insertions, 80 deletions
diff --git a/migration/qemu-file.c b/migration/qemu-file.c
index e9fae3115..6f4a1299b 100644
--- a/migration/qemu-file.c
+++ b/migration/qemu-file.c
@@ -30,31 +30,9 @@
#include "qemu/coroutine.h"
#include "migration/migration.h"
#include "migration/qemu-file.h"
+#include "migration/qemu-file-internal.h"
#include "trace.h"
-#define IO_BUF_SIZE 32768
-#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
-
-struct QEMUFile {
- const QEMUFileOps *ops;
- const QEMUFileHooks *hooks;
- void *opaque;
-
- int64_t bytes_xfer;
- int64_t xfer_limit;
-
- int64_t pos; /* start of buffer when writing, end of buffer
- when reading */
- int buf_index;
- int buf_size; /* 0 when writing */
- uint8_t buf[IO_BUF_SIZE];
-
- struct iovec iov[MAX_IOV_SIZE];
- unsigned int iovcnt;
-
- int last_error;
-};
-
/*
* Stop a file from being read/written - not all backing files can do this
* typically only sockets can.
@@ -102,12 +80,6 @@ QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops)
return f;
}
-
-void qemu_file_set_hooks(QEMUFile *f, const QEMUFileHooks *hooks)
-{
- f->hooks = hooks;
-}
-
/*
* Get last error for stream f
*
@@ -129,49 +101,48 @@ void qemu_file_set_error(QEMUFile *f, int ret)
bool qemu_file_is_writable(QEMUFile *f)
{
- return f->ops->writev_buffer;
+ return f->ops->writev_buffer || f->ops->put_buffer;
}
/**
* Flushes QEMUFile buffer
*
* If there is writev_buffer QEMUFileOps it uses it otherwise uses
- * put_buffer ops. This will flush all pending data. If data was
- * only partially flushed, it will set an error state.
+ * put_buffer ops.
*/
void qemu_fflush(QEMUFile *f)
{
ssize_t ret = 0;
- ssize_t expect = 0;
if (!qemu_file_is_writable(f)) {
return;
}
- if (f->iovcnt > 0) {
- expect = iov_size(f->iov, f->iovcnt);
- ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
+ if (f->ops->writev_buffer) {
+ if (f->iovcnt > 0) {
+ ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
+ }
+ } else {
+ if (f->buf_index > 0) {
+ ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
+ }
}
-
if (ret >= 0) {
f->pos += ret;
}
- /* We expect the QEMUFile write impl to send the full
- * data set we requested, so sanity check that.
- */
- if (ret != expect) {
- qemu_file_set_error(f, ret < 0 ? ret : -EIO);
- }
f->buf_index = 0;
f->iovcnt = 0;
+ if (ret < 0) {
+ qemu_file_set_error(f, ret);
+ }
}
void ram_control_before_iterate(QEMUFile *f, uint64_t flags)
{
int ret = 0;
- if (f->hooks && f->hooks->before_ram_iterate) {
- ret = f->hooks->before_ram_iterate(f, f->opaque, flags, NULL);
+ if (f->ops->before_ram_iterate) {
+ ret = f->ops->before_ram_iterate(f, f->opaque, flags, NULL);
if (ret < 0) {
qemu_file_set_error(f, ret);
}
@@ -182,8 +153,8 @@ void ram_control_after_iterate(QEMUFile *f, uint64_t flags)
{
int ret = 0;
- if (f->hooks && f->hooks->after_ram_iterate) {
- ret = f->hooks->after_ram_iterate(f, f->opaque, flags, NULL);
+ if (f->ops->after_ram_iterate) {
+ ret = f->ops->after_ram_iterate(f, f->opaque, flags, NULL);
if (ret < 0) {
qemu_file_set_error(f, ret);
}
@@ -194,8 +165,8 @@ void ram_control_load_hook(QEMUFile *f, uint64_t flags, void *data)
{
int ret = -EINVAL;
- if (f->hooks && f->hooks->hook_ram_load) {
- ret = f->hooks->hook_ram_load(f, f->opaque, flags, data);
+ if (f->ops->hook_ram_load) {
+ ret = f->ops->hook_ram_load(f, f->opaque, flags, data);
if (ret < 0) {
qemu_file_set_error(f, ret);
}
@@ -214,9 +185,9 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
ram_addr_t offset, size_t size,
uint64_t *bytes_sent)
{
- if (f->hooks && f->hooks->save_page) {
- int ret = f->hooks->save_page(f, f->opaque, block_offset,
- offset, size, bytes_sent);
+ if (f->ops->save_page) {
+ int ret = f->ops->save_page(f, f->opaque, block_offset,
+ offset, size, bytes_sent);
if (ret != RAM_SAVE_CONTROL_DELAYED) {
if (bytes_sent && *bytes_sent > 0) {
@@ -268,6 +239,14 @@ static ssize_t qemu_fill_buffer(QEMUFile *f)
return len;
}
+int qemu_get_fd(QEMUFile *f)
+{
+ if (f->ops->get_fd) {
+ return f->ops->get_fd(f->opaque);
+ }
+ return -1;
+}
+
void qemu_update_position(QEMUFile *f, size_t size)
{
f->pos += size;
@@ -322,6 +301,11 @@ static void add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size)
void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, size_t size)
{
+ if (!f->ops->writev_buffer) {
+ qemu_put_buffer(f, buf, size);
+ return;
+ }
+
if (f->last_error) {
return;
}
@@ -345,7 +329,9 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size)
}
memcpy(f->buf + f->buf_index, buf, l);
f->bytes_xfer += l;
- add_to_iovec(f, f->buf + f->buf_index, l);
+ if (f->ops->writev_buffer) {
+ add_to_iovec(f, f->buf + f->buf_index, l);
+ }
f->buf_index += l;
if (f->buf_index == IO_BUF_SIZE) {
qemu_fflush(f);
@@ -366,7 +352,9 @@ void qemu_put_byte(QEMUFile *f, int v)
f->buf[f->buf_index] = v;
f->bytes_xfer++;
- add_to_iovec(f, f->buf + f->buf_index, 1);
+ if (f->ops->writev_buffer) {
+ add_to_iovec(f, f->buf + f->buf_index, 1);
+ }
f->buf_index++;
if (f->buf_index == IO_BUF_SIZE) {
qemu_fflush(f);
@@ -530,8 +518,12 @@ int64_t qemu_ftell_fast(QEMUFile *f)
int64_t ret = f->pos;
int i;
- for (i = 0; i < f->iovcnt; i++) {
- ret += f->iov[i].iov_len;
+ if (f->ops->writev_buffer) {
+ for (i = 0; i < f->iovcnt; i++) {
+ ret += f->iov[i].iov_len;
+ }
+ } else {
+ ret += f->buf_index;
}
return ret;
@@ -615,14 +607,8 @@ uint64_t qemu_get_be64(QEMUFile *f)
return v;
}
-/* Compress size bytes of data start at p with specific compression
+/* compress size bytes of data start at p with specific compression
* level and store the compressed data to the buffer of f.
- *
- * When f is not writable, return -1 if f has no space to save the
- * compressed data.
- * When f is wirtable and it has no space to save the compressed data,
- * do fflush first, if f still has no space to save the compressed
- * data, return -1.
*/
ssize_t qemu_put_compression_data(QEMUFile *f, const uint8_t *p, size_t size,
@@ -631,14 +617,7 @@ ssize_t qemu_put_compression_data(QEMUFile *f, const uint8_t *p, size_t size,
ssize_t blen = IO_BUF_SIZE - f->buf_index - sizeof(int32_t);
if (blen < compressBound(size)) {
- if (!qemu_file_is_writable(f)) {
- return -1;
- }
- qemu_fflush(f);
- blen = IO_BUF_SIZE - sizeof(int32_t);
- if (blen < compressBound(size)) {
- return -1;
- }
+ return 0;
}
if (compress2(f->buf + f->buf_index + sizeof(int32_t), (uLongf *)&blen,
(Bytef *)p, size, level) != Z_OK) {
@@ -646,13 +625,7 @@ ssize_t qemu_put_compression_data(QEMUFile *f, const uint8_t *p, size_t size,
return 0;
}
qemu_put_be32(f, blen);
- if (f->ops->writev_buffer) {
- add_to_iovec(f, f->buf + f->buf_index, blen);
- }
f->buf_index += blen;
- if (f->buf_index == IO_BUF_SIZE) {
- qemu_fflush(f);
- }
return blen + sizeof(int32_t);
}
@@ -668,7 +641,6 @@ int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src)
len = f_src->buf_index;
qemu_put_buffer(f_des, f_src->buf, f_src->buf_index);
f_src->buf_index = 0;
- f_src->iovcnt = 0;
}
return len;
}
@@ -698,7 +670,9 @@ size_t qemu_get_counted_string(QEMUFile *f, char buf[256])
*/
void qemu_file_set_blocking(QEMUFile *f, bool block)
{
- if (f->ops->set_blocking) {
- f->ops->set_blocking(f->opaque, block);
+ if (block) {
+ qemu_set_block(qemu_get_fd(f));
+ } else {
+ qemu_set_nonblock(qemu_get_fd(f));
}
}