aboutsummaryrefslogtreecommitdiff
path: root/migration
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-09-27 22:44:51 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-09-27 22:44:51 +0100
commitab161529261928ae7f3556e3220829c34b2686ec (patch)
treea19806665ba984fec11c0d1175cc39d0d3a4edd8 /migration
parent1d8934408135ac03b1c753c3b0a819cf7f387d60 (diff)
parent2f168d0708581c33baf6c78d75a89e8cd705f9f6 (diff)
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20170927a' into staging
Migration pull 2017-09-27 # gpg: Signature made Wed 27 Sep 2017 14:56:23 BST # gpg: using RSA key 0x0516331EBC5BFDE7 # gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A 9FA9 0516 331E BC5B FDE7 * remotes/dgilbert/tags/pull-migration-20170927a: migration: Route more error paths migration: Route errors up through vmstate_save migration: wire vmstate_save_state errors up to vmstate_subsection_save migration: Check field save returns migration: check pre_save return in vmstate_save_state migration: pre_save return int migration: disable auto-converge during bulk block migration Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'migration')
-rw-r--r--migration/block.c5
-rw-r--r--migration/block.h7
-rw-r--r--migration/colo-comm.c4
-rw-r--r--migration/global_state.c4
-rw-r--r--migration/ram.c6
-rw-r--r--migration/savevm.c23
-rw-r--r--migration/trace-events1
-rw-r--r--migration/vmstate-types.c11
-rw-r--r--migration/vmstate.c43
9 files changed, 81 insertions, 23 deletions
diff --git a/migration/block.c b/migration/block.c
index 9171f60028..606ad4db92 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -161,6 +161,11 @@ int blk_mig_active(void)
return !QSIMPLEQ_EMPTY(&block_mig_state.bmds_list);
}
+int blk_mig_bulk_active(void)
+{
+ return blk_mig_active() && !block_mig_state.bulk_completed;
+}
+
uint64_t blk_mig_bytes_transferred(void)
{
BlkMigDevState *bmds;
diff --git a/migration/block.h b/migration/block.h
index 22ebe94259..3178609dbd 100644
--- a/migration/block.h
+++ b/migration/block.h
@@ -16,6 +16,7 @@
#ifdef CONFIG_LIVE_BLOCK_MIGRATION
int blk_mig_active(void);
+int blk_mig_bulk_active(void);
uint64_t blk_mig_bytes_transferred(void);
uint64_t blk_mig_bytes_remaining(void);
uint64_t blk_mig_bytes_total(void);
@@ -25,6 +26,12 @@ static inline int blk_mig_active(void)
{
return false;
}
+
+static inline int blk_mig_bulk_active(void)
+{
+ return false;
+}
+
static inline uint64_t blk_mig_bytes_transferred(void)
{
return 0;
diff --git a/migration/colo-comm.c b/migration/colo-comm.c
index b61aa19a38..df26e4dfe7 100644
--- a/migration/colo-comm.c
+++ b/migration/colo-comm.c
@@ -34,11 +34,13 @@ COLOMode get_colo_mode(void)
}
}
-static void colo_info_pre_save(void *opaque)
+static int colo_info_pre_save(void *opaque)
{
COLOInfo *s = opaque;
s->colo_requested = migrate_colo_enabled();
+
+ return 0;
}
static bool colo_info_need(void *opaque)
diff --git a/migration/global_state.c b/migration/global_state.c
index dfdaf63910..8e8ab5c51e 100644
--- a/migration/global_state.c
+++ b/migration/global_state.c
@@ -101,12 +101,14 @@ static int global_state_post_load(void *opaque, int version_id)
return 0;
}
-static void global_state_pre_save(void *opaque)
+static int global_state_pre_save(void *opaque)
{
GlobalState *s = opaque;
trace_migrate_global_state_pre_save((char *)s->runstate);
s->size = strlen((char *)s->runstate) + 1;
+
+ return 0;
}
static const VMStateDescription vmstate_globalstate = {
diff --git a/migration/ram.c b/migration/ram.c
index 88ca69e7b2..b83f8977c5 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -46,6 +46,7 @@
#include "exec/ram_addr.h"
#include "qemu/rcu_queue.h"
#include "migration/colo.h"
+#include "migration/block.h"
/***********************************************************/
/* ram save/restore */
@@ -825,7 +826,10 @@ static void migration_bitmap_sync(RAMState *rs)
/ (end_time - rs->time_last_bitmap_sync);
bytes_xfer_now = ram_counters.transferred;
- if (migrate_auto_converge()) {
+ /* During block migration the auto-converge logic incorrectly detects
+ * that ram migration makes no progress. Avoid this by disabling the
+ * throttling logic during the bulk phase of block migration. */
+ if (migrate_auto_converge() && !blk_mig_bulk_active()) {
/* The following detection logic can be refined later. For now:
Check to see if the dirtied bytes is 50% more than the approx.
amount of bytes that just got transferred since the last time we
diff --git a/migration/savevm.c b/migration/savevm.c
index 2478352baf..4a88228614 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -312,7 +312,7 @@ static SaveState savevm_state = {
.global_section_id = 0,
};
-static void configuration_pre_save(void *opaque)
+static int configuration_pre_save(void *opaque)
{
SaveState *state = opaque;
const char *current_name = MACHINE_GET_CLASS(current_machine)->name;
@@ -320,6 +320,8 @@ static void configuration_pre_save(void *opaque)
state->len = strlen(current_name);
state->name = current_name;
state->target_page_bits = qemu_target_page_bits();
+
+ return 0;
}
static int configuration_pre_load(void *opaque)
@@ -766,14 +768,14 @@ static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se, QJSON *vmdes
}
}
-static void vmstate_save(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc)
+static int vmstate_save(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc)
{
trace_vmstate_save(se->idstr, se->vmsd ? se->vmsd->name : "(old)");
if (!se->vmsd) {
vmstate_save_old_style(f, se, vmdesc);
- return;
+ return 0;
}
- vmstate_save_state(f, se->vmsd, se->opaque, vmdesc);
+ return vmstate_save_state(f, se->vmsd, se->opaque, vmdesc);
}
/*
@@ -1169,7 +1171,11 @@ int qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only,
json_prop_int(vmdesc, "instance_id", se->instance_id);
save_section_header(f, se, QEMU_VM_SECTION_FULL);
- vmstate_save(f, se, vmdesc);
+ ret = vmstate_save(f, se, vmdesc);
+ if (ret) {
+ qemu_file_set_error(f, ret);
+ return ret;
+ }
trace_savevm_section_end(se->idstr, se->section_id, 0);
save_section_footer(f, se);
@@ -1311,6 +1317,8 @@ static int qemu_save_device_state(QEMUFile *f)
cpu_synchronize_all_states();
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
+ int ret;
+
if (se->is_ram) {
continue;
}
@@ -1323,7 +1331,10 @@ static int qemu_save_device_state(QEMUFile *f)
save_section_header(f, se, QEMU_VM_SECTION_FULL);
- vmstate_save(f, se, NULL);
+ ret = vmstate_save(f, se, NULL);
+ if (ret) {
+ return ret;
+ }
save_section_footer(f, se);
}
diff --git a/migration/trace-events b/migration/trace-events
index d2910a6e7b..6f29fcc686 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -40,6 +40,7 @@ savevm_state_iterate(void) ""
savevm_state_cleanup(void) ""
savevm_state_complete_precopy(void) ""
vmstate_save(const char *idstr, const char *vmsd_name) "%s, %s"
+vmstate_save_state_pre_save_res(const char *name, int res) "%s/%d"
vmstate_save_state_loop(const char *name, const char *field, int n_elems) "%s/%s[%d]"
vmstate_save_state_top(const char *idstr) "%s"
vmstate_subsection_save_loop(const char *name, const char *sub) "%s/%s"
diff --git a/migration/vmstate-types.c b/migration/vmstate-types.c
index c056c98bdb..48184c380d 100644
--- a/migration/vmstate-types.c
+++ b/migration/vmstate-types.c
@@ -550,13 +550,14 @@ static int put_tmp(QEMUFile *f, void *pv, size_t size, VMStateField *field,
{
const VMStateDescription *vmsd = field->vmsd;
void *tmp = g_malloc(size);
+ int ret;
/* Writes the parent field which is at the start of the tmp */
*(void **)tmp = pv;
- vmstate_save_state(f, vmsd, tmp, vmdesc);
+ ret = vmstate_save_state(f, vmsd, tmp, vmdesc);
g_free(tmp);
- return 0;
+ return ret;
}
const VMStateInfo vmstate_info_tmp = {
@@ -657,12 +658,16 @@ static int put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
/* offset of the QTAILQ entry in a QTAILQ element*/
size_t entry_offset = field->start;
void *elm;
+ int ret;
trace_put_qtailq(vmsd->name, vmsd->version_id);
QTAILQ_RAW_FOREACH(elm, pv, entry_offset) {
qemu_put_byte(f, true);
- vmstate_save_state(f, vmsd, elm, vmdesc);
+ ret = vmstate_save_state(f, vmsd, elm, vmdesc);
+ if (ret) {
+ return ret;
+ }
}
qemu_put_byte(f, false);
diff --git a/migration/vmstate.c b/migration/vmstate.c
index 3226e8eb45..0b3282c9df 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -21,8 +21,8 @@
#include "trace.h"
#include "qjson.h"
-static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, QJSON *vmdesc);
+static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
+ void *opaque, QJSON *vmdesc);
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque);
@@ -308,15 +308,21 @@ bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
}
-void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
+int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, QJSON *vmdesc)
{
+ int ret = 0;
VMStateField *field = vmsd->fields;
trace_vmstate_save_state_top(vmsd->name);
if (vmsd->pre_save) {
- vmsd->pre_save(opaque);
+ ret = vmsd->pre_save(opaque);
+ trace_vmstate_save_state_pre_save_res(vmsd->name, ret);
+ if (ret) {
+ error_report("pre-save failed: %s", vmsd->name);
+ return ret;
+ }
}
if (vmdesc) {
@@ -341,6 +347,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
}
for (i = 0; i < n_elems; i++) {
void *curr_elem = first_elem + size * i;
+ ret = 0;
vmsd_desc_field_start(vmsd, vmdesc_loop, field, i, n_elems);
old_offset = qemu_ftell_fast(f);
@@ -351,11 +358,19 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
if (!curr_elem && size) {
/* if null pointer write placeholder and do not follow */
assert(field->flags & VMS_ARRAY_OF_POINTER);
- vmstate_info_nullptr.put(f, curr_elem, size, NULL, NULL);
+ ret = vmstate_info_nullptr.put(f, curr_elem, size, NULL,
+ NULL);
} else if (field->flags & VMS_STRUCT) {
- vmstate_save_state(f, field->vmsd, curr_elem, vmdesc_loop);
+ ret = vmstate_save_state(f, field->vmsd, curr_elem,
+ vmdesc_loop);
} else {
- field->info->put(f, curr_elem, size, field, vmdesc_loop);
+ ret = field->info->put(f, curr_elem, size, field,
+ vmdesc_loop);
+ }
+ if (ret) {
+ error_report("Save of field %s/%s failed",
+ vmsd->name, field->name);
+ return ret;
}
written_bytes = qemu_ftell_fast(f) - old_offset;
@@ -380,7 +395,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
json_end_array(vmdesc);
}
- vmstate_subsection_save(f, vmsd, opaque, vmdesc);
+ return vmstate_subsection_save(f, vmsd, opaque, vmdesc);
}
static const VMStateDescription *
@@ -446,11 +461,12 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
return 0;
}
-static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, QJSON *vmdesc)
+static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
+ void *opaque, QJSON *vmdesc)
{
const VMStateDescription **sub = vmsd->subsections;
bool subsection_found = false;
+ int ret = 0;
trace_vmstate_subsection_save_top(vmsd->name);
while (sub && *sub && (*sub)->needed) {
@@ -474,7 +490,10 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
qemu_put_byte(f, len);
qemu_put_buffer(f, (uint8_t *)vmsdsub->name, len);
qemu_put_be32(f, vmsdsub->version_id);
- vmstate_save_state(f, vmsdsub, opaque, vmdesc);
+ ret = vmstate_save_state(f, vmsdsub, opaque, vmdesc);
+ if (ret) {
+ return ret;
+ }
if (vmdesc) {
json_end_object(vmdesc);
@@ -486,4 +505,6 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
if (vmdesc && subsection_found) {
json_end_array(vmdesc);
}
+
+ return ret;
}