diff options
Diffstat (limited to 'migration/qemu-file.c')
-rw-r--r-- | migration/qemu-file.c | 134 |
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)); } } |