* [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections
@ 2015-07-01 8:51 Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 01/12] runstate: Add runstate store Juan Quintela
` (11 more replies)
0 siblings, 12 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
Hi
At the end, Daved asked for a couple of things on previous series.
[v2]
- Ensure that we start in NONE even after failed/canceled migration
- move printf's to traces
- make sure that we can migrate the new states like guest-panicked
(not sure if it is a good idea to enable migrate a guest-panicked, but
it is not this series the place to forbid it)
- address all comments from Dave and Eric.
Please, review.
[v1]
As the beggining of both series have been accepted, I merged both here. Changes:
- answered all comments on list and applied suggested changes
- Use migrate_set_state() consistently
- we were misusing atomic_cmpxchg(), it didn't matter until now because
we were missing only traces, but it showed with events missing.
- Reorganized how the migration events are generated, now only on migrate_set_state.
Please review.
Juan Quintela (12):
runstate: Add runstate store
runstate: migration allows more transitions now
migration: create new section to store global state
global_state: Make section optional
vmstate: Create optional sections
migration: Add configuration section
migration: Use cmpxchg correctly
migration: ensure we start in NONE state
migration: Use always helper to set state
migration: No need to call trace_migrate_set_state()
migration: create migration event
migration: Add migration events on target side
docs/qmp/qmp-events.txt | 14 ++++
hw/i386/pc_piix.c | 2 +
hw/i386/pc_q35.c | 2 +
include/migration/migration.h | 4 ++
include/migration/vmstate.h | 2 +
include/sysemu/sysemu.h | 1 +
migration/migration.c | 157 ++++++++++++++++++++++++++++++++++++++----
migration/savevm.c | 69 +++++++++++++++++++
migration/vmstate.c | 11 +++
qapi/event.json | 12 ++++
trace-events | 4 ++
vl.c | 21 +++++-
12 files changed, 283 insertions(+), 16 deletions(-)
--
2.4.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 01/12] runstate: Add runstate store
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 02/12] runstate: migration allows more transitions now Juan Quintela
` (10 subsequent siblings)
11 siblings, 0 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
This allows us to store the current state to send it through migration.
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
include/sysemu/sysemu.h | 1 +
vl.c | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index df80951..44570d1 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -28,6 +28,7 @@ bool runstate_check(RunState state);
void runstate_set(RunState new_state);
int runstate_is_running(void);
bool runstate_needs_reset(void);
+bool runstate_store(char *str, size_t size);
typedef struct vm_change_state_entry VMChangeStateEntry;
typedef void VMChangeStateHandler(void *opaque, int running, RunState state);
diff --git a/vl.c b/vl.c
index 69ad90c..fec7e93 100644
--- a/vl.c
+++ b/vl.c
@@ -634,6 +634,18 @@ bool runstate_check(RunState state)
return current_run_state == state;
}
+bool runstate_store(char *str, size_t size)
+{
+ const char *state = RunState_lookup[current_run_state];
+ size_t len = strlen(state) + 1;
+
+ if (len > size) {
+ return false;
+ }
+ memcpy(str, state, len);
+ return true;
+}
+
static void runstate_init(void)
{
const RunStateTransition *p;
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 02/12] runstate: migration allows more transitions now
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 01/12] runstate: Add runstate store Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 03/12] migration: create new section to store global state Juan Quintela
` (9 subsequent siblings)
11 siblings, 0 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
Next commit would allow to move from incoming migration to error happening on source.
Should we add more states to this transition? Luiz?
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
vl.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/vl.c b/vl.c
index fec7e93..d4d9ca8 100644
--- a/vl.c
+++ b/vl.c
@@ -573,8 +573,14 @@ static const RunStateTransition runstate_transitions_def[] = {
{ RUN_STATE_DEBUG, RUN_STATE_RUNNING },
{ RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
- { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
+ { RUN_STATE_INMIGRATE, RUN_STATE_INTERNAL_ERROR },
+ { RUN_STATE_INMIGRATE, RUN_STATE_IO_ERROR },
{ RUN_STATE_INMIGRATE, RUN_STATE_PAUSED },
+ { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
+ { RUN_STATE_INMIGRATE, RUN_STATE_SHUTDOWN },
+ { RUN_STATE_INMIGRATE, RUN_STATE_SUSPENDED },
+ { RUN_STATE_INMIGRATE, RUN_STATE_WHATCHDOG },
+ { RUN_STATE_INMIGRATE, RUN_STATE_GUEST_PANICKED },
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 03/12] migration: create new section to store global state
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 01/12] runstate: Add runstate store Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 02/12] runstate: migration allows more transitions now Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 9:13 ` Dr. David Alan Gilbert
2015-07-01 8:51 ` [Qemu-devel] [PATCH 04/12] global_state: Make section optional Juan Quintela
` (8 subsequent siblings)
11 siblings, 1 reply; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
This includes a new section that for now just stores the current qemu state.
Right now, there are only one way to control what is the state of the
target after migration.
- If you run the target qemu with -S, it would start stopped.
- If you run the target qemu without -S, it would run just after migration finishes.
The problem here is what happens if we start the target without -S and
there happens one error during migration that puts current state as
-EIO. Migration would ends (notice that the error happend doing block
IO, network IO, i.e. nothing related with migration), and when
migration finish, we would just "continue" running on destination,
probably hanging the guest/corruption data, whatever.
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
include/migration/migration.h | 1 +
migration/migration.c | 105 +++++++++++++++++++++++++++++++++++++++---
trace-events | 3 ++
vl.c | 1 +
4 files changed, 103 insertions(+), 7 deletions(-)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index 9387c8c..1280193 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -197,4 +197,5 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
void ram_mig_init(void);
void savevm_skip_section_footers(void);
+void register_global_state(void);
#endif
diff --git a/migration/migration.c b/migration/migration.c
index c6ac08a..b4b6d69 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -26,6 +26,7 @@
#include "qemu/thread.h"
#include "qmp-commands.h"
#include "trace.h"
+#include "qapi/util.h"
#define MAX_THROTTLE (32 << 20) /* Migration speed throttling */
@@ -97,6 +98,83 @@ void migration_incoming_state_destroy(void)
mis_current = NULL;
}
+
+typedef struct {
+ uint32_t size;
+ uint8_t runstate[100];
+} GlobalState;
+
+static GlobalState global_state;
+
+static int global_state_store(void)
+{
+ if (!runstate_store((char *)global_state.runstate,
+ sizeof(global_state.runstate))) {
+ trace_migrate_state_too_big();
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static char *global_state_get_runstate(void)
+{
+ return (char *)global_state.runstate;
+}
+
+static int global_state_post_load(void *opaque, int version_id)
+{
+ GlobalState *s = opaque;
+ int ret = 0;
+ char *runstate = (char *)s->runstate;
+
+ trace_migrate_global_state_post_load(runstate);
+
+ if (strcmp(runstate, "running") != 0) {
+ Error *local_err = NULL;
+ int r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE_MAX,
+ -1, &local_err);
+
+ if (r == -1) {
+ if (local_err) {
+ error_report_err(local_err);
+ }
+ return -EINVAL;
+ }
+ ret = vm_stop_force_state(r);
+ }
+
+ return ret;
+}
+
+static void 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;
+ printf("saved state: %s\n", s->runstate);
+}
+
+static const VMStateDescription vmstate_globalstate = {
+ .name = "globalstate",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .post_load = global_state_post_load,
+ .pre_save = global_state_pre_save,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(size, GlobalState),
+ VMSTATE_BUFFER(runstate, GlobalState),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+void register_global_state(void)
+{
+ /* We would use it independently that we receive it */
+ strcpy((char *)&global_state.runstate, "");
+ vmstate_register(NULL, 0, &vmstate_globalstate, &global_state);
+}
+
/*
* Called on -incoming with a defer: uri.
* The migration can be started later after any parameters have been
@@ -164,10 +242,20 @@ static void process_incoming_migration_co(void *opaque)
exit(EXIT_FAILURE);
}
- if (autostart) {
+ /* runstate == "" means that we haven't received it through the
+ * wire, so we obey autostart. runstate == runing means that we
+ * need to run it, we need to make sure that we do it after
+ * everything else has finished. Every other state change is done
+ * at the post_load function */
+
+ if (strcmp(global_state_get_runstate(), "running") == 0) {
vm_start();
- } else {
- runstate_set(RUN_STATE_PAUSED);
+ } else if (strcmp(global_state_get_runstate(), "") == 0) {
+ if (autostart) {
+ vm_start();
+ } else {
+ runstate_set(RUN_STATE_PAUSED);
+ }
}
migrate_decompress_threads_join();
}
@@ -793,10 +881,13 @@ static void *migration_thread(void *opaque)
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
old_vm_running = runstate_is_running();
- ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
- if (ret >= 0) {
- qemu_file_set_rate_limit(s->file, INT64_MAX);
- qemu_savevm_state_complete(s->file);
+ ret = global_state_store();
+ if (!ret) {
+ ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
+ if (ret >= 0) {
+ qemu_file_set_rate_limit(s->file, INT64_MAX);
+ qemu_savevm_state_complete(s->file);
+ }
}
qemu_mutex_unlock_iothread();
diff --git a/trace-events b/trace-events
index 52b7efa..5d5cae2 100644
--- a/trace-events
+++ b/trace-events
@@ -1403,6 +1403,9 @@ migrate_fd_error(void) ""
migrate_fd_cancel(void) ""
migrate_pending(uint64_t size, uint64_t max) "pending size %" PRIu64 " max %" PRIu64
migrate_transferred(uint64_t tranferred, uint64_t time_spent, double bandwidth, uint64_t size) "transferred %" PRIu64 " time_spent %" PRIu64 " bandwidth %g max_size %" PRId64
+migrate_state_too_big(void) ""
+migrate_global_state_post_load(const char *state) "loaded state: %s"
+migrate_global_state_pre_save(const char *state) "saved state: %s"
# migration/rdma.c
qemu_dma_accept_incoming_migration(void) ""
diff --git a/vl.c b/vl.c
index d4d9ca8..ce39f60 100644
--- a/vl.c
+++ b/vl.c
@@ -4624,6 +4624,7 @@ int main(int argc, char **argv, char **envp)
return 0;
}
+ register_global_state();
if (incoming) {
Error *local_err = NULL;
qemu_start_incoming_migration(incoming, &local_err);
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 04/12] global_state: Make section optional
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
` (2 preceding siblings ...)
2015-07-01 8:51 ` [Qemu-devel] [PATCH 03/12] migration: create new section to store global state Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 9:16 ` Dr. David Alan Gilbert
2015-07-01 9:38 ` Yang Hongyang
2015-07-01 8:51 ` [Qemu-devel] [PATCH 05/12] vmstate: Create optional sections Juan Quintela
` (7 subsequent siblings)
11 siblings, 2 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
This section would be sent:
a- for all new machine types
b- for old achine types if section state is different form {running,paused}
that were the only giving us troubles.
So, in new qemus: it is alwasy there. In old qemus: they are only
there if it an error has happened, basically stoping on target.
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
hw/i386/pc_piix.c | 1 +
hw/i386/pc_q35.c | 1 +
include/migration/migration.h | 1 +
migration/migration.c | 30 +++++++++++++++++++++++++++++-
4 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index e142f75..735fb22 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -307,6 +307,7 @@ static void pc_init1(MachineState *machine)
static void pc_compat_2_3(MachineState *machine)
{
savevm_skip_section_footers();
+ global_state_set_optional();
}
static void pc_compat_2_2(MachineState *machine)
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 082cd93..26104ca 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -291,6 +291,7 @@ static void pc_q35_init(MachineState *machine)
static void pc_compat_2_3(MachineState *machine)
{
savevm_skip_section_footers();
+ global_state_set_optional();
}
static void pc_compat_2_2(MachineState *machine)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index 1280193..bb53d93 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -198,4 +198,5 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
void ram_mig_init(void);
void savevm_skip_section_footers(void);
void register_global_state(void);
+void global_state_set_optional(void);
#endif
diff --git a/migration/migration.c b/migration/migration.c
index b4b6d69..0fd5962 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -100,6 +100,7 @@ void migration_incoming_state_destroy(void)
typedef struct {
+ bool optional;
uint32_t size;
uint8_t runstate[100];
} GlobalState;
@@ -121,6 +122,33 @@ static char *global_state_get_runstate(void)
return (char *)global_state.runstate;
}
+void global_state_set_optional(void)
+{
+ global_state.optional = true;
+}
+
+static bool global_state_needed(void *opaque)
+{
+ GlobalState *s = opaque;
+ char *runstate = (char *)s->runstate;
+
+ /* If it is not optional, it is mandatory */
+
+ if (s->optional == false) {
+ return true;
+ }
+
+ /* If state is running or paused, it is not needed */
+
+ if (strcmp(runstate, "running") == 0 ||
+ strcmp(runstate, "paused") == 0) {
+ return false;
+ }
+
+ /* for any other state it is needed */
+ return true;
+}
+
static int global_state_post_load(void *opaque, int version_id)
{
GlobalState *s = opaque;
@@ -152,7 +180,6 @@ static void global_state_pre_save(void *opaque)
trace_migrate_global_state_pre_save((char *)s->runstate);
s->size = strlen((char *)s->runstate) + 1;
- printf("saved state: %s\n", s->runstate);
}
static const VMStateDescription vmstate_globalstate = {
@@ -161,6 +188,7 @@ static const VMStateDescription vmstate_globalstate = {
.minimum_version_id = 1,
.post_load = global_state_post_load,
.pre_save = global_state_pre_save,
+ .needed = global_state_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT32(size, GlobalState),
VMSTATE_BUFFER(runstate, GlobalState),
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 05/12] vmstate: Create optional sections
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
` (3 preceding siblings ...)
2015-07-01 8:51 ` [Qemu-devel] [PATCH 04/12] global_state: Make section optional Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 06/12] migration: Add configuration section Juan Quintela
` (6 subsequent siblings)
11 siblings, 0 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
To make sections optional, we need to do it at the beggining of the code.
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
include/migration/vmstate.h | 2 ++
migration/savevm.c | 8 ++++++++
migration/vmstate.c | 11 +++++++++++
trace-events | 1 +
4 files changed, 22 insertions(+)
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 0695d7c..f51ff69 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -820,6 +820,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, QJSON *vmdesc);
+bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque);
+
int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
const VMStateDescription *vmsd,
void *base, int alias_id,
diff --git a/migration/savevm.c b/migration/savevm.c
index 9e0e286..8a15021 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -836,6 +836,11 @@ void qemu_savevm_state_complete(QEMUFile *f)
if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
continue;
}
+ if (se->vmsd && !vmstate_save_needed(se->vmsd, se->opaque)) {
+ trace_savevm_section_skip(se->idstr, se->section_id);
+ continue;
+ }
+
trace_savevm_section_start(se->idstr, se->section_id);
json_start_object(vmdesc, NULL);
@@ -949,6 +954,9 @@ static int qemu_save_device_state(QEMUFile *f)
if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
continue;
}
+ if (se->vmsd && !vmstate_save_needed(se->vmsd, se->opaque)) {
+ continue;
+ }
save_section_header(f, se, QEMU_VM_SECTION_FULL);
diff --git a/migration/vmstate.c b/migration/vmstate.c
index 6138d1a..e8ccf22 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -276,6 +276,17 @@ static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc,
json_end_object(vmdesc);
}
+
+bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
+{
+ if (vmsd->needed && !vmsd->needed(opaque)) {
+ /* optional section not needed */
+ return false;
+ }
+ return true;
+}
+
+
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, QJSON *vmdesc)
{
diff --git a/trace-events b/trace-events
index 5d5cae2..8b85fbb 100644
--- a/trace-events
+++ b/trace-events
@@ -1191,6 +1191,7 @@ qemu_loadvm_state_section_partend(uint32_t section_id) "%u"
qemu_loadvm_state_section_startfull(uint32_t section_id, const char *idstr, uint32_t instance_id, uint32_t version_id) "%u(%s) %u %u"
savevm_section_start(const char *id, unsigned int section_id) "%s, section_id %u"
savevm_section_end(const char *id, unsigned int section_id, int ret) "%s, section_id %u -> %d"
+savevm_section_skip(const char *id, unsigned int section_id) "%s, section_id %u"
savevm_state_begin(void) ""
savevm_state_header(void) ""
savevm_state_iterate(void) ""
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 06/12] migration: Add configuration section
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
` (4 preceding siblings ...)
2015-07-01 8:51 ` [Qemu-devel] [PATCH 05/12] vmstate: Create optional sections Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 9:47 ` Yang Hongyang
2015-07-01 8:51 ` [Qemu-devel] [PATCH 07/12] migration: Use cmpxchg correctly Juan Quintela
` (5 subsequent siblings)
11 siblings, 1 reply; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
It needs to be the first one and it is not optional, that is the reason
why it is opencoded. For new machine types, it is required than machine
type name is the same in both sides.
It is just done right now for pc's.
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
hw/i386/pc_piix.c | 1 +
hw/i386/pc_q35.c | 1 +
include/migration/migration.h | 2 ++
migration/savevm.c | 61 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 65 insertions(+)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 735fb22..5009836 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -308,6 +308,7 @@ static void pc_compat_2_3(MachineState *machine)
{
savevm_skip_section_footers();
global_state_set_optional();
+ savevm_skip_configuration();
}
static void pc_compat_2_2(MachineState *machine)
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 26104ca..d00766e 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -292,6 +292,7 @@ static void pc_compat_2_3(MachineState *machine)
{
savevm_skip_section_footers();
global_state_set_optional();
+ savevm_skip_configuration();
}
static void pc_compat_2_2(MachineState *machine)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index bb53d93..cfc0608 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -34,6 +34,7 @@
#define QEMU_VM_SECTION_FULL 0x04
#define QEMU_VM_SUBSECTION 0x05
#define QEMU_VM_VMDESCRIPTION 0x06
+#define QEMU_VM_CONFIGURATION 0x07
#define QEMU_VM_SECTION_FOOTER 0x7e
struct MigrationParams {
@@ -199,4 +200,5 @@ void ram_mig_init(void);
void savevm_skip_section_footers(void);
void register_global_state(void);
void global_state_set_optional(void);
+void savevm_skip_configuration(void);
#endif
diff --git a/migration/savevm.c b/migration/savevm.c
index 8a15021..db8e943 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -246,11 +246,55 @@ typedef struct SaveStateEntry {
typedef struct SaveState {
QTAILQ_HEAD(, SaveStateEntry) handlers;
int global_section_id;
+ bool skip_configuration;
+ uint32_t len;
+ const char *name;
} SaveState;
static SaveState savevm_state = {
.handlers = QTAILQ_HEAD_INITIALIZER(savevm_state.handlers),
.global_section_id = 0,
+ .skip_configuration = false,
+};
+
+void savevm_skip_configuration(void)
+{
+ savevm_state.skip_configuration = true;
+}
+
+
+static void configuration_pre_save(void *opaque)
+{
+ SaveState *state = opaque;
+ const char *current_name = MACHINE_GET_CLASS(current_machine)->name;
+
+ state->len = strlen(current_name);
+ state->name = current_name;
+}
+
+static int configuration_post_load(void *opaque, int version_id)
+{
+ SaveState *state = opaque;
+ const char *current_name = MACHINE_GET_CLASS(current_machine)->name;
+
+ if (strncmp(state->name, current_name, state->len) != 0) {
+ error_report("Machine type received is '%s' and local is '%s'",
+ state->name, current_name);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static const VMStateDescription vmstate_configuration = {
+ .name = "configuration",
+ .version_id = 1,
+ .post_load = configuration_post_load,
+ .pre_save = configuration_pre_save,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(len, SaveState),
+ VMSTATE_VBUFFER_ALLOC_UINT32(name, SaveState, 0, NULL, 0, len),
+ VMSTATE_END_OF_LIST()
+ },
};
static void dump_vmstate_vmsd(FILE *out_file,
@@ -723,6 +767,11 @@ void qemu_savevm_state_begin(QEMUFile *f,
se->ops->set_params(params, se->opaque);
}
+ if (!savevm_state.skip_configuration) {
+ qemu_put_byte(f, QEMU_VM_CONFIGURATION);
+ vmstate_save_state(f, &vmstate_configuration, &savevm_state, 0);
+ }
+
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (!se->ops || !se->ops->save_live_setup) {
continue;
@@ -1037,6 +1086,18 @@ int qemu_loadvm_state(QEMUFile *f)
return -ENOTSUP;
}
+ if (!savevm_state.skip_configuration) {
+ if (qemu_get_byte(f) != QEMU_VM_CONFIGURATION) {
+ error_report("Configuration section missing");
+ return -EINVAL;
+ }
+ ret = vmstate_load_state(f, &vmstate_configuration, &savevm_state, 0);
+
+ if (ret) {
+ return ret;
+ }
+ }
+
while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
uint32_t instance_id, version_id, section_id;
SaveStateEntry *se;
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 07/12] migration: Use cmpxchg correctly
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
` (5 preceding siblings ...)
2015-07-01 8:51 ` [Qemu-devel] [PATCH 06/12] migration: Add configuration section Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 08/12] migration: ensure we start in NONE state Juan Quintela
` (4 subsequent siblings)
11 siblings, 0 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
cmpxchg returns the old value
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
migration/migration.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/migration/migration.c b/migration/migration.c
index 0fd5962..cfcc227 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -508,7 +508,7 @@ void qmp_migrate_set_parameters(bool has_compress_level,
static void migrate_set_state(MigrationState *s, int old_state, int new_state)
{
- if (atomic_cmpxchg(&s->state, old_state, new_state) == new_state) {
+ if (atomic_cmpxchg(&s->state, old_state, new_state) == old_state) {
trace_migrate_set_state(new_state);
}
}
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 08/12] migration: ensure we start in NONE state
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
` (6 preceding siblings ...)
2015-07-01 8:51 ` [Qemu-devel] [PATCH 07/12] migration: Use cmpxchg correctly Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 9:29 ` Dr. David Alan Gilbert
2015-07-01 9:51 ` Yang Hongyang
2015-07-01 8:51 ` [Qemu-devel] [PATCH 09/12] migration: Use always helper to set state Juan Quintela
` (3 subsequent siblings)
11 siblings, 2 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
migration/migration.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/migration/migration.c b/migration/migration.c
index cfcc227..c5b778b 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -693,7 +693,6 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
error_setg(errp, QERR_MIGRATION_ACTIVE);
return;
}
-
if (runstate_check(RUN_STATE_INMIGRATE)) {
error_setg(errp, "Guest is waiting for an incoming migration");
return;
@@ -708,6 +707,12 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
return;
}
+ /* We are starting a new migration, so we want to start in a clean
+ state. This change is only needed if previous migration
+ failed/was cancelled. We don't use migrate_set_state() because
+ we are setting the initial state, not changing it. */
+ s->state = MIGRATION_STATUS_NONE;
+
s = migrate_init(¶ms);
if (strstart(uri, "tcp:", &p)) {
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 09/12] migration: Use always helper to set state
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
` (7 preceding siblings ...)
2015-07-01 8:51 ` [Qemu-devel] [PATCH 08/12] migration: ensure we start in NONE state Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 9:37 ` Dr. David Alan Gilbert
2015-07-01 10:04 ` Yang Hongyang
2015-07-01 8:51 ` [Qemu-devel] [PATCH 10/12] migration: No need to call trace_migrate_set_state() Juan Quintela
` (2 subsequent siblings)
11 siblings, 2 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
There were three places that were not using the migrate_set_state()
helper, just fix that.
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
migration/migration.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/migration/migration.c b/migration/migration.c
index c5b778b..a8d2da5 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -548,7 +548,7 @@ void migrate_fd_error(MigrationState *s)
{
trace_migrate_fd_error();
assert(s->file == NULL);
- s->state = MIGRATION_STATUS_FAILED;
+ migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED);
trace_migrate_set_state(MIGRATION_STATUS_FAILED);
notifier_list_notify(&migration_state_notifiers, s);
}
@@ -633,7 +633,7 @@ static MigrationState *migrate_init(const MigrationParams *params)
s->parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS] =
decompress_thread_count;
s->bandwidth_limit = bandwidth_limit;
- s->state = MIGRATION_STATUS_SETUP;
+ migrate_set_state(s, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP);
trace_migrate_set_state(MIGRATION_STATUS_SETUP);
s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
@@ -732,7 +732,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
} else {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri",
"a valid migration protocol");
- s->state = MIGRATION_STATUS_FAILED;
+ migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED);
return;
}
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 10/12] migration: No need to call trace_migrate_set_state()
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
` (8 preceding siblings ...)
2015-07-01 8:51 ` [Qemu-devel] [PATCH 09/12] migration: Use always helper to set state Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 11/12] migration: create migration event Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 12/12] migration: Add migration events on target side Juan Quintela
11 siblings, 0 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
We now use the helper everywhere, so no need to call this on this two
places. See on previous commit that there were a place where we missed
to mark the trace. Now all tracing is done in migrate_set_state().
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
migration/migration.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/migration/migration.c b/migration/migration.c
index a8d2da5..ef1e4a4 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -549,7 +549,6 @@ void migrate_fd_error(MigrationState *s)
trace_migrate_fd_error();
assert(s->file == NULL);
migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED);
- trace_migrate_set_state(MIGRATION_STATUS_FAILED);
notifier_list_notify(&migration_state_notifiers, s);
}
@@ -634,7 +633,6 @@ static MigrationState *migrate_init(const MigrationParams *params)
decompress_thread_count;
s->bandwidth_limit = bandwidth_limit;
migrate_set_state(s, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP);
- trace_migrate_set_state(MIGRATION_STATUS_SETUP);
s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
return s;
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 11/12] migration: create migration event
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
` (9 preceding siblings ...)
2015-07-01 8:51 ` [Qemu-devel] [PATCH 10/12] migration: No need to call trace_migrate_set_state() Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 12/12] migration: Add migration events on target side Juan Quintela
11 siblings, 0 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
We have one argument that tells us what event has happened.
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
docs/qmp/qmp-events.txt | 14 ++++++++++++++
migration/migration.c | 2 ++
qapi/event.json | 12 ++++++++++++
3 files changed, 28 insertions(+)
diff --git a/docs/qmp/qmp-events.txt b/docs/qmp/qmp-events.txt
index 4c13d48..d92cc48 100644
--- a/docs/qmp/qmp-events.txt
+++ b/docs/qmp/qmp-events.txt
@@ -473,6 +473,20 @@ Example:
{ "timestamp": {"seconds": 1290688046, "microseconds": 417172},
"event": "SPICE_MIGRATE_COMPLETED" }
+MIGRATION
+---------
+
+Emitted when a migration event happens
+
+Data: None.
+
+ - "status": migration status
+ See MigrationStatus in ~/qapi-schema.json for possible values
+
+Example:
+
+{"timestamp": {"seconds": 1432121972, "microseconds": 744001},
+ "event": "MIGRATION", "data": {"status": "completed"}}
STOP
----
diff --git a/migration/migration.c b/migration/migration.c
index ef1e4a4..fee2186 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -27,6 +27,7 @@
#include "qmp-commands.h"
#include "trace.h"
#include "qapi/util.h"
+#include "qapi-event.h"
#define MAX_THROTTLE (32 << 20) /* Migration speed throttling */
@@ -509,6 +510,7 @@ void qmp_migrate_set_parameters(bool has_compress_level,
static void migrate_set_state(MigrationState *s, int old_state, int new_state)
{
if (atomic_cmpxchg(&s->state, old_state, new_state) == old_state) {
+ qapi_event_send_migration(new_state, &error_abort);
trace_migrate_set_state(new_state);
}
}
diff --git a/qapi/event.json b/qapi/event.json
index 378dda5..f0cef01 100644
--- a/qapi/event.json
+++ b/qapi/event.json
@@ -243,6 +243,18 @@
{ 'event': 'SPICE_MIGRATE_COMPLETED' }
##
+# @MIGRATION
+#
+# Emitted when a migration event happens
+#
+# @status: @MigrationStatus describing the current migration status.
+#
+# Since: 2.4
+##
+{ 'event': 'MIGRATION',
+ 'data': {'status': 'MigrationStatus'}}
+
+##
# @ACPI_DEVICE_OST
#
# Emitted when guest executes ACPI _OST method.
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 12/12] migration: Add migration events on target side
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
` (10 preceding siblings ...)
2015-07-01 8:51 ` [Qemu-devel] [PATCH 11/12] migration: create migration event Juan Quintela
@ 2015-07-01 8:51 ` Juan Quintela
11 siblings, 0 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 8:51 UTC (permalink / raw)
To: qemu-devel; +Cc: amit.shah, dgilbert
We reuse the migration events from the source side, sending them on the
appropiate place.
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
migration/migration.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/migration/migration.c b/migration/migration.c
index fee2186..8fe4e73 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -221,6 +221,7 @@ void qemu_start_incoming_migration(const char *uri, Error **errp)
{
const char *p;
+ qapi_event_send_migration(MIGRATION_STATUS_SETUP, &error_abort);
if (!strcmp(uri, "defer")) {
deferred_incoming_migration(errp);
} else if (strstart(uri, "tcp:", &p)) {
@@ -249,7 +250,7 @@ static void process_incoming_migration_co(void *opaque)
int ret;
migration_incoming_state_new(f);
-
+ qapi_event_send_migration(MIGRATION_STATUS_ACTIVE, &error_abort);
ret = qemu_loadvm_state(f);
qemu_fclose(f);
@@ -257,10 +258,12 @@ static void process_incoming_migration_co(void *opaque)
migration_incoming_state_destroy();
if (ret < 0) {
+ qapi_event_send_migration(MIGRATION_STATUS_FAILED, &error_abort);
error_report("load of migration failed: %s", strerror(-ret));
migrate_decompress_threads_join();
exit(EXIT_FAILURE);
}
+ qapi_event_send_migration(MIGRATION_STATUS_COMPLETED, &error_abort);
qemu_announce_self();
/* Make sure all file formats flush their mutable metadata */
--
2.4.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 03/12] migration: create new section to store global state
2015-07-01 8:51 ` [Qemu-devel] [PATCH 03/12] migration: create new section to store global state Juan Quintela
@ 2015-07-01 9:13 ` Dr. David Alan Gilbert
2015-07-01 9:34 ` Juan Quintela
0 siblings, 1 reply; 24+ messages in thread
From: Dr. David Alan Gilbert @ 2015-07-01 9:13 UTC (permalink / raw)
To: Juan Quintela; +Cc: amit.shah, qemu-devel
* Juan Quintela (quintela@redhat.com) wrote:
> This includes a new section that for now just stores the current qemu state.
>
> Right now, there are only one way to control what is the state of the
> target after migration.
>
> - If you run the target qemu with -S, it would start stopped.
> - If you run the target qemu without -S, it would run just after migration finishes.
>
> The problem here is what happens if we start the target without -S and
> there happens one error during migration that puts current state as
> -EIO. Migration would ends (notice that the error happend doing block
> IO, network IO, i.e. nothing related with migration), and when
> migration finish, we would just "continue" running on destination,
> probably hanging the guest/corruption data, whatever.
>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---
> include/migration/migration.h | 1 +
> migration/migration.c | 105 +++++++++++++++++++++++++++++++++++++++---
> trace-events | 3 ++
> vl.c | 1 +
> 4 files changed, 103 insertions(+), 7 deletions(-)
>
> diff --git a/include/migration/migration.h b/include/migration/migration.h
> index 9387c8c..1280193 100644
> --- a/include/migration/migration.h
> +++ b/include/migration/migration.h
> @@ -197,4 +197,5 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
>
> void ram_mig_init(void);
> void savevm_skip_section_footers(void);
> +void register_global_state(void);
> #endif
> diff --git a/migration/migration.c b/migration/migration.c
> index c6ac08a..b4b6d69 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -26,6 +26,7 @@
> #include "qemu/thread.h"
> #include "qmp-commands.h"
> #include "trace.h"
> +#include "qapi/util.h"
>
> #define MAX_THROTTLE (32 << 20) /* Migration speed throttling */
>
> @@ -97,6 +98,83 @@ void migration_incoming_state_destroy(void)
> mis_current = NULL;
> }
>
> +
> +typedef struct {
> + uint32_t size;
> + uint8_t runstate[100];
> +} GlobalState;
> +
> +static GlobalState global_state;
> +
> +static int global_state_store(void)
> +{
> + if (!runstate_store((char *)global_state.runstate,
> + sizeof(global_state.runstate))) {
> + trace_migrate_state_too_big();
Hmm ok, but that should have stayed as the error_report - the only
problem with that in the previous version was a \n
(error_report for errors, trace_ for debug)
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> +static char *global_state_get_runstate(void)
> +{
> + return (char *)global_state.runstate;
> +}
> +
> +static int global_state_post_load(void *opaque, int version_id)
> +{
> + GlobalState *s = opaque;
> + int ret = 0;
> + char *runstate = (char *)s->runstate;
> +
> + trace_migrate_global_state_post_load(runstate);
> +
> + if (strcmp(runstate, "running") != 0) {
> + Error *local_err = NULL;
> + int r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE_MAX,
> + -1, &local_err);
> +
> + if (r == -1) {
> + if (local_err) {
> + error_report_err(local_err);
> + }
> + return -EINVAL;
> + }
> + ret = vm_stop_force_state(r);
> + }
> +
> + return ret;
> +}
> +
> +static void 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;
> + printf("saved state: %s\n", s->runstate);
Stray printf
Other than that,
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> +}
> +
> +static const VMStateDescription vmstate_globalstate = {
> + .name = "globalstate",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .post_load = global_state_post_load,
> + .pre_save = global_state_pre_save,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT32(size, GlobalState),
> + VMSTATE_BUFFER(runstate, GlobalState),
> + VMSTATE_END_OF_LIST()
> + },
> +};
> +
> +void register_global_state(void)
> +{
> + /* We would use it independently that we receive it */
> + strcpy((char *)&global_state.runstate, "");
> + vmstate_register(NULL, 0, &vmstate_globalstate, &global_state);
> +}
> +
> /*
> * Called on -incoming with a defer: uri.
> * The migration can be started later after any parameters have been
> @@ -164,10 +242,20 @@ static void process_incoming_migration_co(void *opaque)
> exit(EXIT_FAILURE);
> }
>
> - if (autostart) {
> + /* runstate == "" means that we haven't received it through the
> + * wire, so we obey autostart. runstate == runing means that we
> + * need to run it, we need to make sure that we do it after
> + * everything else has finished. Every other state change is done
> + * at the post_load function */
> +
> + if (strcmp(global_state_get_runstate(), "running") == 0) {
> vm_start();
> - } else {
> - runstate_set(RUN_STATE_PAUSED);
> + } else if (strcmp(global_state_get_runstate(), "") == 0) {
> + if (autostart) {
> + vm_start();
> + } else {
> + runstate_set(RUN_STATE_PAUSED);
> + }
> }
> migrate_decompress_threads_join();
> }
> @@ -793,10 +881,13 @@ static void *migration_thread(void *opaque)
> qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
> old_vm_running = runstate_is_running();
>
> - ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
> - if (ret >= 0) {
> - qemu_file_set_rate_limit(s->file, INT64_MAX);
> - qemu_savevm_state_complete(s->file);
> + ret = global_state_store();
> + if (!ret) {
> + ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
> + if (ret >= 0) {
> + qemu_file_set_rate_limit(s->file, INT64_MAX);
> + qemu_savevm_state_complete(s->file);
> + }
> }
> qemu_mutex_unlock_iothread();
>
> diff --git a/trace-events b/trace-events
> index 52b7efa..5d5cae2 100644
> --- a/trace-events
> +++ b/trace-events
> @@ -1403,6 +1403,9 @@ migrate_fd_error(void) ""
> migrate_fd_cancel(void) ""
> migrate_pending(uint64_t size, uint64_t max) "pending size %" PRIu64 " max %" PRIu64
> migrate_transferred(uint64_t tranferred, uint64_t time_spent, double bandwidth, uint64_t size) "transferred %" PRIu64 " time_spent %" PRIu64 " bandwidth %g max_size %" PRId64
> +migrate_state_too_big(void) ""
> +migrate_global_state_post_load(const char *state) "loaded state: %s"
> +migrate_global_state_pre_save(const char *state) "saved state: %s"
>
> # migration/rdma.c
> qemu_dma_accept_incoming_migration(void) ""
> diff --git a/vl.c b/vl.c
> index d4d9ca8..ce39f60 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -4624,6 +4624,7 @@ int main(int argc, char **argv, char **envp)
> return 0;
> }
>
> + register_global_state();
> if (incoming) {
> Error *local_err = NULL;
> qemu_start_incoming_migration(incoming, &local_err);
> --
> 2.4.3
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 04/12] global_state: Make section optional
2015-07-01 8:51 ` [Qemu-devel] [PATCH 04/12] global_state: Make section optional Juan Quintela
@ 2015-07-01 9:16 ` Dr. David Alan Gilbert
2015-07-01 9:38 ` Yang Hongyang
1 sibling, 0 replies; 24+ messages in thread
From: Dr. David Alan Gilbert @ 2015-07-01 9:16 UTC (permalink / raw)
To: Juan Quintela; +Cc: amit.shah, qemu-devel
* Juan Quintela (quintela@redhat.com) wrote:
> This section would be sent:
>
> a- for all new machine types
> b- for old achine types if section state is different form {running,paused}
> that were the only giving us troubles.
>
> So, in new qemus: it is alwasy there. In old qemus: they are only
> there if it an error has happened, basically stoping on target.
>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
Note you should probably also fix Power (see my 'Fix for section footers for power')
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> ---
> hw/i386/pc_piix.c | 1 +
> hw/i386/pc_q35.c | 1 +
> include/migration/migration.h | 1 +
> migration/migration.c | 30 +++++++++++++++++++++++++++++-
> 4 files changed, 32 insertions(+), 1 deletion(-)
>
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index e142f75..735fb22 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -307,6 +307,7 @@ static void pc_init1(MachineState *machine)
> static void pc_compat_2_3(MachineState *machine)
> {
> savevm_skip_section_footers();
> + global_state_set_optional();
> }
>
> static void pc_compat_2_2(MachineState *machine)
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index 082cd93..26104ca 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -291,6 +291,7 @@ static void pc_q35_init(MachineState *machine)
> static void pc_compat_2_3(MachineState *machine)
> {
> savevm_skip_section_footers();
> + global_state_set_optional();
> }
>
> static void pc_compat_2_2(MachineState *machine)
> diff --git a/include/migration/migration.h b/include/migration/migration.h
> index 1280193..bb53d93 100644
> --- a/include/migration/migration.h
> +++ b/include/migration/migration.h
> @@ -198,4 +198,5 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
> void ram_mig_init(void);
> void savevm_skip_section_footers(void);
> void register_global_state(void);
> +void global_state_set_optional(void);
> #endif
> diff --git a/migration/migration.c b/migration/migration.c
> index b4b6d69..0fd5962 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -100,6 +100,7 @@ void migration_incoming_state_destroy(void)
>
>
> typedef struct {
> + bool optional;
> uint32_t size;
> uint8_t runstate[100];
> } GlobalState;
> @@ -121,6 +122,33 @@ static char *global_state_get_runstate(void)
> return (char *)global_state.runstate;
> }
>
> +void global_state_set_optional(void)
> +{
> + global_state.optional = true;
> +}
> +
> +static bool global_state_needed(void *opaque)
> +{
> + GlobalState *s = opaque;
> + char *runstate = (char *)s->runstate;
> +
> + /* If it is not optional, it is mandatory */
> +
> + if (s->optional == false) {
> + return true;
> + }
> +
> + /* If state is running or paused, it is not needed */
> +
> + if (strcmp(runstate, "running") == 0 ||
> + strcmp(runstate, "paused") == 0) {
> + return false;
> + }
> +
> + /* for any other state it is needed */
> + return true;
> +}
> +
> static int global_state_post_load(void *opaque, int version_id)
> {
> GlobalState *s = opaque;
> @@ -152,7 +180,6 @@ static void global_state_pre_save(void *opaque)
>
> trace_migrate_global_state_pre_save((char *)s->runstate);
> s->size = strlen((char *)s->runstate) + 1;
> - printf("saved state: %s\n", s->runstate);
> }
>
> static const VMStateDescription vmstate_globalstate = {
> @@ -161,6 +188,7 @@ static const VMStateDescription vmstate_globalstate = {
> .minimum_version_id = 1,
> .post_load = global_state_post_load,
> .pre_save = global_state_pre_save,
> + .needed = global_state_needed,
> .fields = (VMStateField[]) {
> VMSTATE_UINT32(size, GlobalState),
> VMSTATE_BUFFER(runstate, GlobalState),
> --
> 2.4.3
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 08/12] migration: ensure we start in NONE state
2015-07-01 8:51 ` [Qemu-devel] [PATCH 08/12] migration: ensure we start in NONE state Juan Quintela
@ 2015-07-01 9:29 ` Dr. David Alan Gilbert
2015-07-01 9:51 ` Yang Hongyang
1 sibling, 0 replies; 24+ messages in thread
From: Dr. David Alan Gilbert @ 2015-07-01 9:29 UTC (permalink / raw)
To: Juan Quintela; +Cc: amit.shah, qemu-devel
* Juan Quintela (quintela@redhat.com) wrote:
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---
> migration/migration.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/migration/migration.c b/migration/migration.c
> index cfcc227..c5b778b 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -693,7 +693,6 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
> error_setg(errp, QERR_MIGRATION_ACTIVE);
> return;
> }
> -
> if (runstate_check(RUN_STATE_INMIGRATE)) {
> error_setg(errp, "Guest is waiting for an incoming migration");
> return;
> @@ -708,6 +707,12 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
> return;
> }
>
> + /* We are starting a new migration, so we want to start in a clean
> + state. This change is only needed if previous migration
> + failed/was cancelled. We don't use migrate_set_state() because
> + we are setting the initial state, not changing it. */
> + s->state = MIGRATION_STATUS_NONE;
> +
Yes, I think that should work; we've already checked which state we're
in, so we can't already be running a migration at this point, and this
would be run from the main thread.
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> s = migrate_init(¶ms);
>
> if (strstart(uri, "tcp:", &p)) {
> --
> 2.4.3
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 03/12] migration: create new section to store global state
2015-07-01 9:13 ` Dr. David Alan Gilbert
@ 2015-07-01 9:34 ` Juan Quintela
0 siblings, 0 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 9:34 UTC (permalink / raw)
To: Dr. David Alan Gilbert; +Cc: amit.shah, qemu-devel
"Dr. David Alan Gilbert" <dgilbert@redhat.com> wrote:
> * Juan Quintela (quintela@redhat.com) wrote:
>> This includes a new section that for now just stores the current qemu state.
>>
>> Right now, there are only one way to control what is the state of the
>> target after migration.
>>
>> - If you run the target qemu with -S, it would start stopped.
>> - If you run the target qemu without -S, it would run just after migration finishes.
>>
>> The problem here is what happens if we start the target without -S and
>> there happens one error during migration that puts current state as
>> -EIO. Migration would ends (notice that the error happend doing block
>> IO, network IO, i.e. nothing related with migration), and when
>> migration finish, we would just "continue" running on destination,
>> probably hanging the guest/corruption data, whatever.
>>
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>> ---
>> include/migration/migration.h | 1 +
>> migration/migration.c | 105 +++++++++++++++++++++++++++++++++++++++---
>> trace-events | 3 ++
>> vl.c | 1 +
>> 4 files changed, 103 insertions(+), 7 deletions(-)
>>
>> diff --git a/include/migration/migration.h b/include/migration/migration.h
>> index 9387c8c..1280193 100644
>> --- a/include/migration/migration.h
>> +++ b/include/migration/migration.h
>> @@ -197,4 +197,5 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
>>
>> void ram_mig_init(void);
>> void savevm_skip_section_footers(void);
>> +void register_global_state(void);
>> #endif
>> diff --git a/migration/migration.c b/migration/migration.c
>> index c6ac08a..b4b6d69 100644
>> --- a/migration/migration.c
>> +++ b/migration/migration.c
>> @@ -26,6 +26,7 @@
>> #include "qemu/thread.h"
>> #include "qmp-commands.h"
>> #include "trace.h"
>> +#include "qapi/util.h"
>>
>> #define MAX_THROTTLE (32 << 20) /* Migration speed throttling */
>>
>> @@ -97,6 +98,83 @@ void migration_incoming_state_destroy(void)
>> mis_current = NULL;
>> }
>>
>> +
>> +typedef struct {
>> + uint32_t size;
>> + uint8_t runstate[100];
>> +} GlobalState;
>> +
>> +static GlobalState global_state;
>> +
>> +static int global_state_store(void)
>> +{
>> + if (!runstate_store((char *)global_state.runstate,
>> + sizeof(global_state.runstate))) {
>> + trace_migrate_state_too_big();
>
> Hmm ok, but that should have stayed as the error_report - the only
> problem with that in the previous version was a \n
> (error_report for errors, trace_ for debug)
>
>> + return -EINVAL;
>> + }
>> + return 0;
>> +}
>> +
>> +static char *global_state_get_runstate(void)
>> +{
>> + return (char *)global_state.runstate;
>> +}
>> +
>> +static int global_state_post_load(void *opaque, int version_id)
>> +{
>> + GlobalState *s = opaque;
>> + int ret = 0;
>> + char *runstate = (char *)s->runstate;
>> +
>> + trace_migrate_global_state_post_load(runstate);
>> +
>> + if (strcmp(runstate, "running") != 0) {
>> + Error *local_err = NULL;
>> + int r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE_MAX,
>> + -1, &local_err);
>> +
>> + if (r == -1) {
>> + if (local_err) {
>> + error_report_err(local_err);
>> + }
>> + return -EINVAL;
>> + }
>> + ret = vm_stop_force_state(r);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static void 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;
>> + printf("saved state: %s\n", s->runstate);
>
> Stray printf
grrr, the removal got somehow on the following patch.
Thanks.
>
>
> Other than that,
>
> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
>
>> +}
>> +
>> +static const VMStateDescription vmstate_globalstate = {
>> + .name = "globalstate",
>> + .version_id = 1,
>> + .minimum_version_id = 1,
>> + .post_load = global_state_post_load,
>> + .pre_save = global_state_pre_save,
>> + .fields = (VMStateField[]) {
>> + VMSTATE_UINT32(size, GlobalState),
>> + VMSTATE_BUFFER(runstate, GlobalState),
>> + VMSTATE_END_OF_LIST()
>> + },
>> +};
>> +
>> +void register_global_state(void)
>> +{
>> + /* We would use it independently that we receive it */
>> + strcpy((char *)&global_state.runstate, "");
>> + vmstate_register(NULL, 0, &vmstate_globalstate, &global_state);
>> +}
>> +
>> /*
>> * Called on -incoming with a defer: uri.
>> * The migration can be started later after any parameters have been
>> @@ -164,10 +242,20 @@ static void process_incoming_migration_co(void *opaque)
>> exit(EXIT_FAILURE);
>> }
>>
>> - if (autostart) {
>> + /* runstate == "" means that we haven't received it through the
>> + * wire, so we obey autostart. runstate == runing means that we
>> + * need to run it, we need to make sure that we do it after
>> + * everything else has finished. Every other state change is done
>> + * at the post_load function */
>> +
>> + if (strcmp(global_state_get_runstate(), "running") == 0) {
>> vm_start();
>> - } else {
>> - runstate_set(RUN_STATE_PAUSED);
>> + } else if (strcmp(global_state_get_runstate(), "") == 0) {
>> + if (autostart) {
>> + vm_start();
>> + } else {
>> + runstate_set(RUN_STATE_PAUSED);
>> + }
>> }
>> migrate_decompress_threads_join();
>> }
>> @@ -793,10 +881,13 @@ static void *migration_thread(void *opaque)
>> qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
>> old_vm_running = runstate_is_running();
>>
>> - ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
>> - if (ret >= 0) {
>> - qemu_file_set_rate_limit(s->file, INT64_MAX);
>> - qemu_savevm_state_complete(s->file);
>> + ret = global_state_store();
>> + if (!ret) {
>> + ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
>> + if (ret >= 0) {
>> + qemu_file_set_rate_limit(s->file, INT64_MAX);
>> + qemu_savevm_state_complete(s->file);
>> + }
>> }
>> qemu_mutex_unlock_iothread();
>>
>> diff --git a/trace-events b/trace-events
>> index 52b7efa..5d5cae2 100644
>> --- a/trace-events
>> +++ b/trace-events
>> @@ -1403,6 +1403,9 @@ migrate_fd_error(void) ""
>> migrate_fd_cancel(void) ""
>> migrate_pending(uint64_t size, uint64_t max) "pending size %" PRIu64 " max %" PRIu64
>> migrate_transferred(uint64_t tranferred, uint64_t time_spent, double bandwidth, uint64_t size) "transferred %" PRIu64 " time_spent %" PRIu64 " bandwidth %g max_size %" PRId64
>> +migrate_state_too_big(void) ""
>> +migrate_global_state_post_load(const char *state) "loaded state: %s"
>> +migrate_global_state_pre_save(const char *state) "saved state: %s"
>>
>> # migration/rdma.c
>> qemu_dma_accept_incoming_migration(void) ""
>> diff --git a/vl.c b/vl.c
>> index d4d9ca8..ce39f60 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -4624,6 +4624,7 @@ int main(int argc, char **argv, char **envp)
>> return 0;
>> }
>>
>> + register_global_state();
>> if (incoming) {
>> Error *local_err = NULL;
>> qemu_start_incoming_migration(incoming, &local_err);
>> --
>> 2.4.3
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 09/12] migration: Use always helper to set state
2015-07-01 8:51 ` [Qemu-devel] [PATCH 09/12] migration: Use always helper to set state Juan Quintela
@ 2015-07-01 9:37 ` Dr. David Alan Gilbert
2015-07-01 10:04 ` Yang Hongyang
1 sibling, 0 replies; 24+ messages in thread
From: Dr. David Alan Gilbert @ 2015-07-01 9:37 UTC (permalink / raw)
To: Juan Quintela; +Cc: amit.shah, qemu-devel
* Juan Quintela (quintela@redhat.com) wrote:
> There were three places that were not using the migrate_set_state()
> helper, just fix that.
>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> ---
> migration/migration.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/migration/migration.c b/migration/migration.c
> index c5b778b..a8d2da5 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -548,7 +548,7 @@ void migrate_fd_error(MigrationState *s)
> {
> trace_migrate_fd_error();
> assert(s->file == NULL);
> - s->state = MIGRATION_STATUS_FAILED;
> + migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED);
> trace_migrate_set_state(MIGRATION_STATUS_FAILED);
> notifier_list_notify(&migration_state_notifiers, s);
> }
> @@ -633,7 +633,7 @@ static MigrationState *migrate_init(const MigrationParams *params)
> s->parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS] =
> decompress_thread_count;
> s->bandwidth_limit = bandwidth_limit;
> - s->state = MIGRATION_STATUS_SETUP;
> + migrate_set_state(s, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP);
> trace_migrate_set_state(MIGRATION_STATUS_SETUP);
>
> s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
> @@ -732,7 +732,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
> } else {
> error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri",
> "a valid migration protocol");
> - s->state = MIGRATION_STATUS_FAILED;
> + migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED);
> return;
> }
>
> --
> 2.4.3
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 04/12] global_state: Make section optional
2015-07-01 8:51 ` [Qemu-devel] [PATCH 04/12] global_state: Make section optional Juan Quintela
2015-07-01 9:16 ` Dr. David Alan Gilbert
@ 2015-07-01 9:38 ` Yang Hongyang
2015-07-01 10:33 ` Juan Quintela
1 sibling, 1 reply; 24+ messages in thread
From: Yang Hongyang @ 2015-07-01 9:38 UTC (permalink / raw)
To: Juan Quintela, qemu-devel; +Cc: amit.shah, dgilbert
On 07/01/2015 04:51 PM, Juan Quintela wrote:
> This section would be sent:
>
> a- for all new machine types
> b- for old achine types if section state is different form {running,paused}
s/achine/machine/
> that were the only giving us troubles.
>
> So, in new qemus: it is alwasy there. In old qemus: they are only
> there if it an error has happened, basically stoping on target.
>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---
> hw/i386/pc_piix.c | 1 +
> hw/i386/pc_q35.c | 1 +
> include/migration/migration.h | 1 +
> migration/migration.c | 30 +++++++++++++++++++++++++++++-
> 4 files changed, 32 insertions(+), 1 deletion(-)
>
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index e142f75..735fb22 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -307,6 +307,7 @@ static void pc_init1(MachineState *machine)
> static void pc_compat_2_3(MachineState *machine)
> {
> savevm_skip_section_footers();
> + global_state_set_optional();
> }
>
> static void pc_compat_2_2(MachineState *machine)
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index 082cd93..26104ca 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -291,6 +291,7 @@ static void pc_q35_init(MachineState *machine)
> static void pc_compat_2_3(MachineState *machine)
> {
> savevm_skip_section_footers();
> + global_state_set_optional();
> }
>
> static void pc_compat_2_2(MachineState *machine)
> diff --git a/include/migration/migration.h b/include/migration/migration.h
> index 1280193..bb53d93 100644
> --- a/include/migration/migration.h
> +++ b/include/migration/migration.h
> @@ -198,4 +198,5 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
> void ram_mig_init(void);
> void savevm_skip_section_footers(void);
> void register_global_state(void);
> +void global_state_set_optional(void);
> #endif
> diff --git a/migration/migration.c b/migration/migration.c
> index b4b6d69..0fd5962 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -100,6 +100,7 @@ void migration_incoming_state_destroy(void)
>
>
> typedef struct {
> + bool optional;
> uint32_t size;
> uint8_t runstate[100];
> } GlobalState;
> @@ -121,6 +122,33 @@ static char *global_state_get_runstate(void)
> return (char *)global_state.runstate;
> }
>
> +void global_state_set_optional(void)
> +{
> + global_state.optional = true;
> +}
> +
> +static bool global_state_needed(void *opaque)
> +{
> + GlobalState *s = opaque;
> + char *runstate = (char *)s->runstate;
> +
> + /* If it is not optional, it is mandatory */
> +
> + if (s->optional == false) {
> + return true;
> + }
> +
> + /* If state is running or paused, it is not needed */
> +
> + if (strcmp(runstate, "running") == 0 ||
> + strcmp(runstate, "paused") == 0) {
> + return false;
> + }
> +
> + /* for any other state it is needed */
> + return true;
> +}
> +
> static int global_state_post_load(void *opaque, int version_id)
> {
> GlobalState *s = opaque;
> @@ -152,7 +180,6 @@ static void global_state_pre_save(void *opaque)
>
> trace_migrate_global_state_pre_save((char *)s->runstate);
> s->size = strlen((char *)s->runstate) + 1;
> - printf("saved state: %s\n", s->runstate);
> }
>
> static const VMStateDescription vmstate_globalstate = {
> @@ -161,6 +188,7 @@ static const VMStateDescription vmstate_globalstate = {
> .minimum_version_id = 1,
> .post_load = global_state_post_load,
> .pre_save = global_state_pre_save,
> + .needed = global_state_needed,
> .fields = (VMStateField[]) {
> VMSTATE_UINT32(size, GlobalState),
> VMSTATE_BUFFER(runstate, GlobalState),
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 06/12] migration: Add configuration section
2015-07-01 8:51 ` [Qemu-devel] [PATCH 06/12] migration: Add configuration section Juan Quintela
@ 2015-07-01 9:47 ` Yang Hongyang
2015-07-01 10:01 ` Juan Quintela
0 siblings, 1 reply; 24+ messages in thread
From: Yang Hongyang @ 2015-07-01 9:47 UTC (permalink / raw)
To: Juan Quintela, qemu-devel; +Cc: amit.shah, dgilbert
On 07/01/2015 04:51 PM, Juan Quintela wrote:
> It needs to be the first one and it is not optional, that is the reason
> why it is opencoded. For new machine types, it is required than machine
s/than/that/
BTW, only check machine type is enough? should we send/check all the
configurations?
> type name is the same in both sides.
>
> It is just done right now for pc's.
>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> ---
> hw/i386/pc_piix.c | 1 +
> hw/i386/pc_q35.c | 1 +
> include/migration/migration.h | 2 ++
> migration/savevm.c | 61 +++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 65 insertions(+)
>
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index 735fb22..5009836 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -308,6 +308,7 @@ static void pc_compat_2_3(MachineState *machine)
> {
> savevm_skip_section_footers();
> global_state_set_optional();
> + savevm_skip_configuration();
> }
>
> static void pc_compat_2_2(MachineState *machine)
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index 26104ca..d00766e 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -292,6 +292,7 @@ static void pc_compat_2_3(MachineState *machine)
> {
> savevm_skip_section_footers();
> global_state_set_optional();
> + savevm_skip_configuration();
> }
>
> static void pc_compat_2_2(MachineState *machine)
> diff --git a/include/migration/migration.h b/include/migration/migration.h
> index bb53d93..cfc0608 100644
> --- a/include/migration/migration.h
> +++ b/include/migration/migration.h
> @@ -34,6 +34,7 @@
> #define QEMU_VM_SECTION_FULL 0x04
> #define QEMU_VM_SUBSECTION 0x05
> #define QEMU_VM_VMDESCRIPTION 0x06
> +#define QEMU_VM_CONFIGURATION 0x07
> #define QEMU_VM_SECTION_FOOTER 0x7e
>
> struct MigrationParams {
> @@ -199,4 +200,5 @@ void ram_mig_init(void);
> void savevm_skip_section_footers(void);
> void register_global_state(void);
> void global_state_set_optional(void);
> +void savevm_skip_configuration(void);
> #endif
> diff --git a/migration/savevm.c b/migration/savevm.c
> index 8a15021..db8e943 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -246,11 +246,55 @@ typedef struct SaveStateEntry {
> typedef struct SaveState {
> QTAILQ_HEAD(, SaveStateEntry) handlers;
> int global_section_id;
> + bool skip_configuration;
> + uint32_t len;
> + const char *name;
> } SaveState;
>
> static SaveState savevm_state = {
> .handlers = QTAILQ_HEAD_INITIALIZER(savevm_state.handlers),
> .global_section_id = 0,
> + .skip_configuration = false,
> +};
> +
> +void savevm_skip_configuration(void)
> +{
> + savevm_state.skip_configuration = true;
> +}
> +
> +
> +static void configuration_pre_save(void *opaque)
> +{
> + SaveState *state = opaque;
> + const char *current_name = MACHINE_GET_CLASS(current_machine)->name;
> +
> + state->len = strlen(current_name);
> + state->name = current_name;
> +}
> +
> +static int configuration_post_load(void *opaque, int version_id)
> +{
> + SaveState *state = opaque;
> + const char *current_name = MACHINE_GET_CLASS(current_machine)->name;
> +
> + if (strncmp(state->name, current_name, state->len) != 0) {
> + error_report("Machine type received is '%s' and local is '%s'",
> + state->name, current_name);
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> +static const VMStateDescription vmstate_configuration = {
> + .name = "configuration",
> + .version_id = 1,
> + .post_load = configuration_post_load,
> + .pre_save = configuration_pre_save,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT32(len, SaveState),
> + VMSTATE_VBUFFER_ALLOC_UINT32(name, SaveState, 0, NULL, 0, len),
> + VMSTATE_END_OF_LIST()
> + },
> };
>
> static void dump_vmstate_vmsd(FILE *out_file,
> @@ -723,6 +767,11 @@ void qemu_savevm_state_begin(QEMUFile *f,
> se->ops->set_params(params, se->opaque);
> }
>
> + if (!savevm_state.skip_configuration) {
> + qemu_put_byte(f, QEMU_VM_CONFIGURATION);
> + vmstate_save_state(f, &vmstate_configuration, &savevm_state, 0);
> + }
> +
> QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
> if (!se->ops || !se->ops->save_live_setup) {
> continue;
> @@ -1037,6 +1086,18 @@ int qemu_loadvm_state(QEMUFile *f)
> return -ENOTSUP;
> }
>
> + if (!savevm_state.skip_configuration) {
> + if (qemu_get_byte(f) != QEMU_VM_CONFIGURATION) {
> + error_report("Configuration section missing");
> + return -EINVAL;
> + }
> + ret = vmstate_load_state(f, &vmstate_configuration, &savevm_state, 0);
> +
> + if (ret) {
> + return ret;
> + }
> + }
> +
> while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
> uint32_t instance_id, version_id, section_id;
> SaveStateEntry *se;
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 08/12] migration: ensure we start in NONE state
2015-07-01 8:51 ` [Qemu-devel] [PATCH 08/12] migration: ensure we start in NONE state Juan Quintela
2015-07-01 9:29 ` Dr. David Alan Gilbert
@ 2015-07-01 9:51 ` Yang Hongyang
1 sibling, 0 replies; 24+ messages in thread
From: Yang Hongyang @ 2015-07-01 9:51 UTC (permalink / raw)
To: Juan Quintela, qemu-devel; +Cc: amit.shah, dgilbert
On 07/01/2015 04:51 PM, Juan Quintela wrote:
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---
> migration/migration.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/migration/migration.c b/migration/migration.c
> index cfcc227..c5b778b 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -693,7 +693,6 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
> error_setg(errp, QERR_MIGRATION_ACTIVE);
> return;
> }
> -
suspicious blank line removal?
> if (runstate_check(RUN_STATE_INMIGRATE)) {
> error_setg(errp, "Guest is waiting for an incoming migration");
> return;
> @@ -708,6 +707,12 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
> return;
> }
>
> + /* We are starting a new migration, so we want to start in a clean
> + state. This change is only needed if previous migration
> + failed/was cancelled. We don't use migrate_set_state() because
> + we are setting the initial state, not changing it. */
> + s->state = MIGRATION_STATUS_NONE;
> +
> s = migrate_init(¶ms);
>
> if (strstart(uri, "tcp:", &p)) {
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 06/12] migration: Add configuration section
2015-07-01 9:47 ` Yang Hongyang
@ 2015-07-01 10:01 ` Juan Quintela
0 siblings, 0 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 10:01 UTC (permalink / raw)
To: Yang Hongyang; +Cc: amit.shah, qemu-devel, dgilbert
Yang Hongyang <yanghy@cn.fujitsu.com> wrote:
> On 07/01/2015 04:51 PM, Juan Quintela wrote:
>> It needs to be the first one and it is not optional, that is the reason
>> why it is opencoded. For new machine types, it is required than machine
>
> s/than/that/
>
> BTW, only check machine type is enough? should we send/check all the
> configurations?
Be my guest. You can add a subsection to that section to test whatever
you want. I don't know how to test all devices really, but now, there
is a place *where* you can do it.
Thanks, Juan.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 09/12] migration: Use always helper to set state
2015-07-01 8:51 ` [Qemu-devel] [PATCH 09/12] migration: Use always helper to set state Juan Quintela
2015-07-01 9:37 ` Dr. David Alan Gilbert
@ 2015-07-01 10:04 ` Yang Hongyang
1 sibling, 0 replies; 24+ messages in thread
From: Yang Hongyang @ 2015-07-01 10:04 UTC (permalink / raw)
To: Juan Quintela, qemu-devel; +Cc: amit.shah, dgilbert
On 07/01/2015 04:51 PM, Juan Quintela wrote:
> There were three places that were not using the migrate_set_state()
> helper, just fix that.
>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> ---
> migration/migration.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/migration/migration.c b/migration/migration.c
> index c5b778b..a8d2da5 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -548,7 +548,7 @@ void migrate_fd_error(MigrationState *s)
> {
> trace_migrate_fd_error();
> assert(s->file == NULL);
> - s->state = MIGRATION_STATUS_FAILED;
> + migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED);
> trace_migrate_set_state(MIGRATION_STATUS_FAILED);
> notifier_list_notify(&migration_state_notifiers, s);
> }
> @@ -633,7 +633,7 @@ static MigrationState *migrate_init(const MigrationParams *params)
> s->parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS] =
> decompress_thread_count;
> s->bandwidth_limit = bandwidth_limit;
> - s->state = MIGRATION_STATUS_SETUP;
> + migrate_set_state(s, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP);
> trace_migrate_set_state(MIGRATION_STATUS_SETUP);
>
> s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
> @@ -732,7 +732,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
> } else {
> error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri",
> "a valid migration protocol");
> - s->state = MIGRATION_STATUS_FAILED;
> + migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED);
> return;
> }
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH 04/12] global_state: Make section optional
2015-07-01 9:38 ` Yang Hongyang
@ 2015-07-01 10:33 ` Juan Quintela
0 siblings, 0 replies; 24+ messages in thread
From: Juan Quintela @ 2015-07-01 10:33 UTC (permalink / raw)
To: Yang Hongyang; +Cc: amit.shah, qemu-devel, dgilbert
Yang Hongyang <yanghy@cn.fujitsu.com> wrote:
> On 07/01/2015 04:51 PM, Juan Quintela wrote:
>> This section would be sent:
>>
>> a- for all new machine types
>> b- for old achine types if section state is different form {running,paused}
>
> s/achine/machine/
Thanks, done
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2015-07-01 10:33 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-01 8:51 [Qemu-devel] [PATCH v2 00/12] Migration events + optional sections Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 01/12] runstate: Add runstate store Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 02/12] runstate: migration allows more transitions now Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 03/12] migration: create new section to store global state Juan Quintela
2015-07-01 9:13 ` Dr. David Alan Gilbert
2015-07-01 9:34 ` Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 04/12] global_state: Make section optional Juan Quintela
2015-07-01 9:16 ` Dr. David Alan Gilbert
2015-07-01 9:38 ` Yang Hongyang
2015-07-01 10:33 ` Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 05/12] vmstate: Create optional sections Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 06/12] migration: Add configuration section Juan Quintela
2015-07-01 9:47 ` Yang Hongyang
2015-07-01 10:01 ` Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 07/12] migration: Use cmpxchg correctly Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 08/12] migration: ensure we start in NONE state Juan Quintela
2015-07-01 9:29 ` Dr. David Alan Gilbert
2015-07-01 9:51 ` Yang Hongyang
2015-07-01 8:51 ` [Qemu-devel] [PATCH 09/12] migration: Use always helper to set state Juan Quintela
2015-07-01 9:37 ` Dr. David Alan Gilbert
2015-07-01 10:04 ` Yang Hongyang
2015-07-01 8:51 ` [Qemu-devel] [PATCH 10/12] migration: No need to call trace_migrate_set_state() Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 11/12] migration: create migration event Juan Quintela
2015-07-01 8:51 ` [Qemu-devel] [PATCH 12/12] migration: Add migration events on target side Juan Quintela
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).