diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-09-27 22:44:51 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-09-27 22:44:51 +0100 |
commit | ab161529261928ae7f3556e3220829c34b2686ec (patch) | |
tree | a19806665ba984fec11c0d1175cc39d0d3a4edd8 /migration | |
parent | 1d8934408135ac03b1c753c3b0a819cf7f387d60 (diff) | |
parent | 2f168d0708581c33baf6c78d75a89e8cd705f9f6 (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.c | 5 | ||||
-rw-r--r-- | migration/block.h | 7 | ||||
-rw-r--r-- | migration/colo-comm.c | 4 | ||||
-rw-r--r-- | migration/global_state.c | 4 | ||||
-rw-r--r-- | migration/ram.c | 6 | ||||
-rw-r--r-- | migration/savevm.c | 23 | ||||
-rw-r--r-- | migration/trace-events | 1 | ||||
-rw-r--r-- | migration/vmstate-types.c | 11 | ||||
-rw-r--r-- | migration/vmstate.c | 43 |
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; } |