#include "qemu/error-report.h"
#include "qemu/iov.h"
#include "migration.h"
+#include "migration-stats.h"
#include "qemu-file.h"
#include "trace.h"
+#include "options.h"
#include "qapi/error.h"
#define IO_BUF_SIZE 32768
QIOChannel *ioc;
bool is_writable;
- /*
- * Maximum amount of data in bytes to transfer during one
- * rate limiting time window
- */
- int64_t rate_limit_max;
- /*
- * Total amount of data in bytes queued for transfer
- * during this rate limiting time window
- */
- int64_t rate_limit_used;
-
/* The sum of bytes transferred on the wire */
- int64_t total_transferred;
+ uint64_t total_transferred;
int buf_index;
int buf_size; /* 0 when writing */
int last_error;
Error *last_error_obj;
- /* has the file has been shutdown */
- bool shutdown;
};
/*
*/
int qemu_file_shutdown(QEMUFile *f)
{
- int ret = 0;
-
- f->shutdown = true;
-
/*
* We must set qemufile error before the real shutdown(), otherwise
* there can be a race window where we thought IO all went though
}
if (qio_channel_shutdown(f->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL) < 0) {
- ret = -EIO;
- }
-
- return ret;
-}
-
-bool qemu_file_mode_is_not_valid(const char *mode)
-{
- if (mode == NULL ||
- (mode[0] != 'r' && mode[0] != 'w') ||
- mode[1] != 'b' || mode[2] != 0) {
- fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
- return true;
+ return -EIO;
}
- return false;
+ return 0;
}
static QEMUFile *qemu_file_new_impl(QIOChannel *ioc, bool is_writable)
* is not 0.
*
*/
-int qemu_file_get_error_obj(QEMUFile *f, Error **errp)
+static int qemu_file_get_error_obj(QEMUFile *f, Error **errp)
{
if (errp) {
*errp = f->last_error_obj ? error_copy(f->last_error_obj) : NULL;
qemu_file_set_error_obj(f, ret, NULL);
}
-bool qemu_file_is_writable(QEMUFile *f)
+static bool qemu_file_is_writable(QEMUFile *f)
{
return f->is_writable;
}
return;
}
- if (f->shutdown) {
+ if (qemu_file_get_error(f)) {
return;
}
if (f->iovcnt > 0) {
&local_error) < 0) {
qemu_file_set_error_obj(f, -EIO, local_error);
} else {
- f->total_transferred += iov_size(f->iov, f->iovcnt);
+ uint64_t size = iov_size(f->iov, f->iovcnt);
+ f->total_transferred += size;
}
qemu_iovec_release_ram(f);
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, flags, data);
+ int ret = f->hooks->hook_ram_load(f, flags, data);
if (ret < 0) {
qemu_file_set_error(f, ret);
}
- } else {
- /*
- * Hook is a hook specifically requested by the source sending a flag
- * that expects there to be a hook on the destination.
- */
- if (flags == RAM_CONTROL_HOOK) {
- qemu_file_set_error(f, ret);
- }
}
}
if (f->hooks && f->hooks->save_page) {
int ret = f->hooks->save_page(f, block_offset,
offset, size, bytes_sent);
- if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
- f->rate_limit_used += size;
- }
if (ret != RAM_SAVE_CONTROL_DELAYED &&
ret != RAM_SAVE_CONTROL_NOT_SUPP) {
* 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)
+static ssize_t coroutine_mixed_fn qemu_fill_buffer(QEMUFile *f)
{
int len;
int pending;
f->buf_index = 0;
f->buf_size = pending;
- if (f->shutdown) {
+ if (qemu_file_get_error(f)) {
return 0;
}
} else {
if (f->iovcnt >= MAX_IOV_SIZE) {
/* Should only happen if a previous fflush failed */
- assert(f->shutdown || !qemu_file_is_writable(f));
+ assert(qemu_file_get_error(f) || !qemu_file_is_writable(f));
return 1;
}
if (may_free) {
return;
}
- f->rate_limit_used += size;
add_to_iovec(f, buf, size, may_free);
}
l = size;
}
memcpy(f->buf + f->buf_index, buf, l);
- f->rate_limit_used += l;
add_buf_to_iovec(f, l);
if (qemu_file_get_error(f)) {
break;
}
f->buf[f->buf_index] = v;
- f->rate_limit_used++;
add_buf_to_iovec(f, 1);
}
* return as many as it managed to read (assuming blocking fd's which
* all current QEMUFile are)
*/
-size_t qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset)
+size_t coroutine_mixed_fn qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset)
{
ssize_t pending;
size_t index;
* return as many as it managed to read (assuming blocking fd's which
* all current QEMUFile are)
*/
-size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size)
+size_t coroutine_mixed_fn qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size)
{
size_t pending = size;
size_t done = 0;
* Note: Since **buf may get changed, the caller should take care to
* keep a pointer to the original buffer if it needs to deallocate it.
*/
-size_t qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size)
+size_t coroutine_mixed_fn qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size)
{
if (size < IO_BUF_SIZE) {
size_t res;
* 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 coroutine_mixed_fn qemu_peek_byte(QEMUFile *f, int offset)
{
int index = f->buf_index + offset;
return f->buf[index];
}
-int qemu_get_byte(QEMUFile *f)
+int coroutine_mixed_fn qemu_get_byte(QEMUFile *f)
{
int result;
return result;
}
-int64_t qemu_file_total_transferred_fast(QEMUFile *f)
+uint64_t qemu_file_transferred_noflush(QEMUFile *f)
{
- int64_t ret = f->total_transferred;
+ uint64_t ret = f->total_transferred;
int i;
for (i = 0; i < f->iovcnt; i++) {
return ret;
}
-int64_t qemu_file_total_transferred(QEMUFile *f)
+uint64_t qemu_file_transferred(QEMUFile *f)
{
qemu_fflush(f);
return f->total_transferred;
}
-int qemu_file_rate_limit(QEMUFile *f)
-{
- if (f->shutdown) {
- return 1;
- }
- if (qemu_file_get_error(f)) {
- return 1;
- }
- if (f->rate_limit_max > 0 && f->rate_limit_used > f->rate_limit_max) {
- return 1;
- }
- return 0;
-}
-
-int64_t qemu_file_get_rate_limit(QEMUFile *f)
-{
- return f->rate_limit_max;
-}
-
-void qemu_file_set_rate_limit(QEMUFile *f, int64_t limit)
-{
- f->rate_limit_max = limit;
-}
-
-void qemu_file_reset_rate_limit(QEMUFile *f)
-{
- f->rate_limit_used = 0;
-}
-
-void qemu_file_acct_rate_limit(QEMUFile *f, int64_t len)
-{
- f->rate_limit_used += len;
-}
-
void qemu_put_be16(QEMUFile *f, unsigned int v)
{
qemu_put_byte(f, v >> 8);
return len;
}
+/*
+ * Check if the writable buffer is empty
+ */
+
+bool qemu_file_buffer_empty(QEMUFile *file)
+{
+ assert(qemu_file_is_writable(file));
+
+ return !file->iovcnt;
+}
+
/*
* Get a string whose length is determined by a single preceding byte
* A preallocated 256 byte buffer must be passed in.
* else 0
* (Note a 0 length string will return 0 either way)
*/
-size_t qemu_get_counted_string(QEMUFile *f, char buf[256])
+size_t coroutine_fn qemu_get_counted_string(QEMUFile *f, char buf[256])
{
size_t len = qemu_get_byte(f);
size_t res = qemu_get_buffer(f, (uint8_t *)buf, len);