summaryrefslogtreecommitdiffstats
path: root/migration
diff options
context:
space:
mode:
Diffstat (limited to 'migration')
-rw-r--r--migration/block-dirty-bitmap.c2
-rw-r--r--migration/block.c2
-rw-r--r--migration/migration.c14
-rw-r--r--migration/migration.h1
-rw-r--r--migration/qemu-file.c50
-rw-r--r--migration/ram.c7
-rw-r--r--migration/savevm.c80
7 files changed, 98 insertions, 58 deletions
diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
index dd40724b9e..5121f86d73 100644
--- a/migration/block-dirty-bitmap.c
+++ b/migration/block-dirty-bitmap.c
@@ -733,7 +733,7 @@ void dirty_bitmap_mig_init(void)
{
QSIMPLEQ_INIT(&dirty_bitmap_mig_state.dbms_list);
- register_savevm_live(NULL, "dirty-bitmap", 0, 1,
+ register_savevm_live("dirty-bitmap", 0, 1,
&savevm_dirty_bitmap_handlers,
&dirty_bitmap_mig_state);
}
diff --git a/migration/block.c b/migration/block.c
index aa747b55fa..0de9d84198 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -1030,6 +1030,6 @@ void blk_mig_init(void)
QSIMPLEQ_INIT(&block_mig_state.blk_list);
qemu_mutex_init(&block_mig_state.lock);
- register_savevm_live(NULL, "block", 0, 1, &savevm_block_handlers,
+ register_savevm_live("block", 0, 1, &savevm_block_handlers,
&block_mig_state);
}
diff --git a/migration/migration.c b/migration/migration.c
index 8b9f2fe30a..01863a95f5 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -2140,6 +2140,15 @@ bool migrate_ignore_shared(void)
return s->enabled_capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
}
+bool migrate_validate_uuid(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->enabled_capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
+}
+
bool migrate_use_events(void)
{
MigrationState *s;
@@ -3016,7 +3025,7 @@ static MigThrError migration_detect_error(MigrationState *s)
}
}
-/* How many bytes have we transferred since the beggining of the migration */
+/* How many bytes have we transferred since the beginning of the migration */
static uint64_t migration_total_bytes(MigrationState *s)
{
return qemu_ftell(s->to_dst_file) + ram_counters.multifd_bytes;
@@ -3327,7 +3336,8 @@ void migrate_fd_connect(MigrationState *s, Error *error_in)
if (resume) {
/* This is a resumed migration */
- rate_limit = INT64_MAX;
+ rate_limit = s->parameters.max_postcopy_bandwidth /
+ XFER_LIMIT_RATIO;
} else {
/* This is a fresh new migration */
rate_limit = s->parameters.max_bandwidth / XFER_LIMIT_RATIO;
diff --git a/migration/migration.h b/migration/migration.h
index 3e1ea2b5dc..4f2fe193dc 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -290,6 +290,7 @@ bool migrate_postcopy_ram(void);
bool migrate_zero_blocks(void);
bool migrate_dirty_bitmaps(void);
bool migrate_ignore_shared(void);
+bool migrate_validate_uuid(void);
bool migrate_auto_converge(void);
bool migrate_use_multifd(void);
diff --git a/migration/qemu-file.c b/migration/qemu-file.c
index e33c46764f..26fb25ddc1 100644
--- a/migration/qemu-file.c
+++ b/migration/qemu-file.c
@@ -201,9 +201,8 @@ static void qemu_iovec_release_ram(QEMUFile *f)
/**
* 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.
+ * This will flush all pending data. If data was only partially flushed, it
+ * will set an error state.
*/
void qemu_fflush(QEMUFile *f)
{
@@ -382,8 +381,16 @@ int qemu_fclose(QEMUFile *f)
return ret;
}
-static void add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size,
- bool may_free)
+/*
+ * Add buf to iovec. Do flush if iovec is full.
+ *
+ * Return values:
+ * 1 iovec is full and flushed
+ * 0 iovec is not flushed
+ *
+ */
+static int add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size,
+ bool may_free)
{
/* check for adjacent buffer and coalesce them */
if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base +
@@ -401,6 +408,19 @@ static void add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size,
if (f->iovcnt >= MAX_IOV_SIZE) {
qemu_fflush(f);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void add_buf_to_iovec(QEMUFile *f, size_t len)
+{
+ if (!add_to_iovec(f, f->buf + f->buf_index, len, false)) {
+ f->buf_index += len;
+ if (f->buf_index == IO_BUF_SIZE) {
+ qemu_fflush(f);
+ }
}
}
@@ -430,11 +450,7 @@ 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, false);
- f->buf_index += l;
- if (f->buf_index == IO_BUF_SIZE) {
- qemu_fflush(f);
- }
+ add_buf_to_iovec(f, l);
if (qemu_file_get_error(f)) {
break;
}
@@ -451,11 +467,7 @@ 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, false);
- f->buf_index++;
- if (f->buf_index == IO_BUF_SIZE) {
- qemu_fflush(f);
- }
+ add_buf_to_iovec(f, 1);
}
void qemu_file_skip(QEMUFile *f, int size)
@@ -761,13 +773,7 @@ ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream,
}
qemu_put_be32(f, blen);
- if (f->ops->writev_buffer) {
- add_to_iovec(f, f->buf + f->buf_index, blen, false);
- }
- f->buf_index += blen;
- if (f->buf_index == IO_BUF_SIZE) {
- qemu_fflush(f);
- }
+ add_buf_to_iovec(f, blen);
return blen + sizeof(int32_t);
}
diff --git a/migration/ram.c b/migration/ram.c
index b01a37e7ca..01df326767 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -1112,6 +1112,7 @@ static void *multifd_send_thread(void *opaque)
rcu_register_thread();
if (multifd_send_initial_packet(p, &local_err) < 0) {
+ ret = -1;
goto out;
}
/* initial packet */
@@ -1179,9 +1180,7 @@ out:
* who pay attention to me.
*/
if (ret != 0) {
- if (flags & MULTIFD_FLAG_SYNC) {
- qemu_sem_post(&p->sem_sync);
- }
+ qemu_sem_post(&p->sem_sync);
qemu_sem_post(&multifd_send_state->channels_ready);
}
@@ -4676,5 +4675,5 @@ static SaveVMHandlers savevm_ram_handlers = {
void ram_mig_init(void)
{
qemu_mutex_init(&XBZRLE.lock);
- register_savevm_live(NULL, "ram", 0, 4, &savevm_ram_handlers, &ram_state);
+ register_savevm_live("ram", 0, 4, &savevm_ram_handlers, &ram_state);
}
diff --git a/migration/savevm.c b/migration/savevm.c
index 4a86128ac4..ee06f91d42 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -256,6 +256,7 @@ typedef struct SaveState {
uint32_t target_page_bits;
uint32_t caps_count;
MigrationCapability *capabilities;
+ QemuUUID uuid;
} SaveState;
static SaveState savevm_state = {
@@ -307,6 +308,7 @@ static int configuration_pre_save(void *opaque)
state->capabilities[j++] = i;
}
}
+ state->uuid = qemu_uuid;
return 0;
}
@@ -464,6 +466,48 @@ static const VMStateDescription vmstate_capabilites = {
}
};
+static bool vmstate_uuid_needed(void *opaque)
+{
+ return qemu_uuid_set && migrate_validate_uuid();
+}
+
+static int vmstate_uuid_post_load(void *opaque, int version_id)
+{
+ SaveState *state = opaque;
+ char uuid_src[UUID_FMT_LEN + 1];
+ char uuid_dst[UUID_FMT_LEN + 1];
+
+ if (!qemu_uuid_set) {
+ /*
+ * It's warning because user might not know UUID in some cases,
+ * e.g. load an old snapshot
+ */
+ qemu_uuid_unparse(&state->uuid, uuid_src);
+ warn_report("UUID is received %s, but local uuid isn't set",
+ uuid_src);
+ return 0;
+ }
+ if (!qemu_uuid_is_equal(&state->uuid, &qemu_uuid)) {
+ qemu_uuid_unparse(&state->uuid, uuid_src);
+ qemu_uuid_unparse(&qemu_uuid, uuid_dst);
+ error_report("UUID received is %s and local is %s", uuid_src, uuid_dst);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static const VMStateDescription vmstate_uuid = {
+ .name = "configuration/uuid",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = vmstate_uuid_needed,
+ .post_load = vmstate_uuid_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8_ARRAY_V(uuid.data, SaveState, sizeof(QemuUUID), 1),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_configuration = {
.name = "configuration",
.version_id = 1,
@@ -478,6 +522,7 @@ static const VMStateDescription vmstate_configuration = {
.subsections = (const VMStateDescription*[]) {
&vmstate_target_page_bits,
&vmstate_capabilites,
+ &vmstate_uuid,
NULL
}
};
@@ -684,8 +729,7 @@ static void savevm_state_handler_insert(SaveStateEntry *nse)
of the system, so instance_id should be removed/replaced.
Meanwhile pass -1 as instance_id if you do not already have a clearly
distinguishing id for all instances of your device class. */
-int register_savevm_live(DeviceState *dev,
- const char *idstr,
+int register_savevm_live(const char *idstr,
int instance_id,
int version_id,
const SaveVMHandlers *ops,
@@ -704,26 +748,6 @@ int register_savevm_live(DeviceState *dev,
se->is_ram = 1;
}
- if (dev) {
- char *id = qdev_get_dev_path(dev);
- if (id) {
- if (snprintf(se->idstr, sizeof(se->idstr), "%s/", id) >=
- sizeof(se->idstr)) {
- error_report("Path too long for VMState (%s)", id);
- g_free(id);
- g_free(se);
-
- return -1;
- }
- g_free(id);
-
- se->compat = g_new0(CompatEntry, 1);
- pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), idstr);
- se->compat->instance_id = instance_id == -1 ?
- calculate_compat_instance_id(idstr) : instance_id;
- instance_id = -1;
- }
- }
pstrcat(se->idstr, sizeof(se->idstr), idstr);
if (instance_id == -1) {
@@ -1100,7 +1124,7 @@ void qemu_savevm_state_setup(QEMUFile *f)
if (!se->ops || !se->ops->save_setup) {
continue;
}
- if (se->ops && se->ops->is_active) {
+ if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
@@ -1131,7 +1155,7 @@ int qemu_savevm_state_resume_prepare(MigrationState *s)
if (!se->ops || !se->ops->resume_prepare) {
continue;
}
- if (se->ops && se->ops->is_active) {
+ if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
@@ -1227,7 +1251,7 @@ void qemu_savevm_state_complete_postcopy(QEMUFile *f)
if (!se->ops || !se->ops->save_live_complete_postcopy) {
continue;
}
- if (se->ops && se->ops->is_active) {
+ if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
@@ -1264,7 +1288,7 @@ int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy)
continue;
}
- if (se->ops && se->ops->is_active) {
+ if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
@@ -1413,7 +1437,7 @@ void qemu_savevm_state_pending(QEMUFile *f, uint64_t threshold_size,
if (!se->ops || !se->ops->save_live_pending) {
continue;
}
- if (se->ops && se->ops->is_active) {
+ if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
@@ -2334,7 +2358,7 @@ static int qemu_loadvm_state_setup(QEMUFile *f)
if (!se->ops || !se->ops->load_setup) {
continue;
}
- if (se->ops && se->ops->is_active) {
+ if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}