X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=migration%2Fsavevm.c;h=8d95e261f60acda0a173b9c46d20f490cee0d7c4;hb=0197d89025d768f3a2505ea50816fbc6b161b992;hp=69a827a92fdb6b78319c238ee64031146f7b30aa;hpb=e326767b455e031a9bd187adfcbaca4362cb9f40;p=mirror_qemu.git diff --git a/migration/savevm.c b/migration/savevm.c index 69a827a92f..8d95e261f6 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -32,6 +32,7 @@ #include "net/net.h" #include "migration.h" #include "migration/snapshot.h" +#include "migration/vmstate.h" #include "migration/misc.h" #include "migration/register.h" #include "migration/global_state.h" @@ -50,11 +51,14 @@ #include "exec/target_page.h" #include "trace.h" #include "qemu/iov.h" +#include "qemu/main-loop.h" #include "block/snapshot.h" #include "qemu/cutils.h" #include "io/channel-buffer.h" #include "io/channel-file.h" #include "sysemu/replay.h" +#include "sysemu/runstate.h" +#include "sysemu/sysemu.h" #include "qjson.h" #include "migration/colo.h" #include "qemu/bitmap.h" @@ -252,6 +256,7 @@ typedef struct SaveState { uint32_t target_page_bits; uint32_t caps_count; MigrationCapability *capabilities; + QemuUUID uuid; } SaveState; static SaveState savevm_state = { @@ -303,6 +308,7 @@ static int configuration_pre_save(void *opaque) state->capabilities[j++] = i; } } + state->uuid = qemu_uuid; return 0; } @@ -460,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, @@ -474,6 +522,7 @@ static const VMStateDescription vmstate_configuration = { .subsections = (const VMStateDescription*[]) { &vmstate_target_page_bits, &vmstate_capabilites, + &vmstate_uuid, NULL } }; @@ -680,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, @@ -700,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) { @@ -1096,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; } @@ -1127,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; } @@ -1187,6 +1215,8 @@ int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy) save_section_footer(f, se); if (ret < 0) { + error_report("failed to save SaveStateEntry with id(name): %d(%s)", + se->section_id, se->idstr); qemu_file_set_error(f, ret); } if (ret <= 0) { @@ -1223,7 +1253,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; } @@ -1260,7 +1290,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; } @@ -1286,7 +1316,7 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, bool in_postcopy, bool inactivate_disks) { - QJSON *vmdesc; + g_autoptr(QJSON) vmdesc = NULL; int vmdesc_len; SaveStateEntry *se; int ret; @@ -1347,7 +1377,6 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, qemu_put_be32(f, vmdesc_len); qemu_put_buffer(f, (uint8_t *)qjson_get_str(vmdesc), vmdesc_len); } - qjson_destroy(vmdesc); return 0; } @@ -1409,7 +1438,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; } @@ -1456,6 +1485,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) } migrate_init(ms); + memset(&ram_counters, 0, sizeof(ram_counters)); ms->to_dst_file = f; qemu_mutex_unlock_iothread(); @@ -1648,8 +1678,6 @@ static int loadvm_postcopy_handle_advise(MigrationIncomingState *mis, return -1; } - postcopy_state_set(POSTCOPY_INCOMING_ADVISE); - return 0; } @@ -1809,6 +1837,8 @@ static void *postcopy_ram_listen_thread(void *opaque) rcu_unregister_thread(); mis->have_listen_thread = false; + postcopy_state_set(POSTCOPY_INCOMING_END); + return NULL; } @@ -1839,7 +1869,7 @@ static int loadvm_postcopy_handle_listen(MigrationIncomingState *mis) * shouldn't be doing anything yet so don't actually expect requests */ if (migrate_postcopy_ram()) { - if (postcopy_ram_enable_notify(mis)) { + if (postcopy_ram_incoming_setup(mis)) { postcopy_ram_incoming_cleanup(mis); return -1; } @@ -1850,11 +1880,6 @@ static int loadvm_postcopy_handle_listen(MigrationIncomingState *mis) return -1; } - if (mis->have_listen_thread) { - error_report("CMD_POSTCOPY_RAM_LISTEN already has a listen thread"); - return -1; - } - mis->have_listen_thread = true; /* Start up the listening thread and wait for it to signal ready */ qemu_sem_init(&mis->listen_thread_sem, 0); @@ -1867,16 +1892,10 @@ static int loadvm_postcopy_handle_listen(MigrationIncomingState *mis) return 0; } - -typedef struct { - QEMUBH *bh; -} HandleRunBhData; - static void loadvm_postcopy_handle_run_bh(void *opaque) { Error *local_err = NULL; - HandleRunBhData *data = opaque; - MigrationIncomingState *mis = migration_incoming_get_current(); + MigrationIncomingState *mis = opaque; /* TODO we should move all of this lot into postcopy_ram.c or a shared code * in migration.c @@ -1908,15 +1927,13 @@ static void loadvm_postcopy_handle_run_bh(void *opaque) runstate_set(RUN_STATE_PAUSED); } - qemu_bh_delete(data->bh); - g_free(data); + qemu_bh_delete(mis->bh); } /* After all discards we can start running and asking for pages */ static int loadvm_postcopy_handle_run(MigrationIncomingState *mis) { - PostcopyState ps = postcopy_state_set(POSTCOPY_INCOMING_RUNNING); - HandleRunBhData *data; + PostcopyState ps = postcopy_state_get(); trace_loadvm_postcopy_handle_run(); if (ps != POSTCOPY_INCOMING_LISTENING) { @@ -1924,9 +1941,9 @@ static int loadvm_postcopy_handle_run(MigrationIncomingState *mis) return -1; } - data = g_new(HandleRunBhData, 1); - data->bh = qemu_bh_new(loadvm_postcopy_handle_run_bh, data); - qemu_bh_schedule(data->bh); + postcopy_state_set(POSTCOPY_INCOMING_RUNNING); + mis->bh = qemu_bh_new(loadvm_postcopy_handle_run_bh, mis); + qemu_bh_schedule(mis->bh); /* We need to finish reading the stream from the package * and also stop reading anything more from the stream that loaded the @@ -2340,7 +2357,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; } @@ -2439,7 +2456,7 @@ retry: case QEMU_VM_COMMAND: ret = loadvm_process_command(f); trace_qemu_loadvm_state_section_command(ret); - if ((ret < 0) || (ret & LOADVM_QUIT)) { + if ((ret < 0) || (ret == LOADVM_QUIT)) { goto out; } break;