For SVM, we forbid it shutdown directly when in COLO mode, FOR PVM's shutdown, we should do some work to ensure the consistent action between PVM and SVM.
Signed-off-by: zhanghailiang <zhang.zhanghaili...@huawei.com> Signed-off-by: Lai Jiangshan <la...@cn.fujitsu.com> Signed-off-by: Li Zhijian <lizhij...@cn.fujitsu.com> --- include/sysemu/sysemu.h | 3 +++ migration/colo.c | 31 ++++++++++++++++++++++++++++++- vl.c | 26 ++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 8a52934..8b37bd2 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -51,6 +51,8 @@ typedef enum WakeupReason { QEMU_WAKEUP_REASON_OTHER, } WakeupReason; +extern int colo_shutdown_requested; + void qemu_system_reset_request(void); void qemu_system_suspend_request(void); void qemu_register_suspend_notifier(Notifier *notifier); @@ -58,6 +60,7 @@ void qemu_system_wakeup_request(WakeupReason reason); void qemu_system_wakeup_enable(WakeupReason reason, bool enabled); void qemu_register_wakeup_notifier(Notifier *notifier); void qemu_system_shutdown_request(void); +void qemu_system_shutdown_request_core(void); void qemu_system_powerdown_request(void); void qemu_register_powerdown_notifier(Notifier *notifier); void qemu_system_debug_request(void); diff --git a/migration/colo.c b/migration/colo.c index 8740fc2..111062f 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -67,6 +67,8 @@ enum { COLO_CHECKPOINT_SEND, COLO_CHECKPOINT_RECEIVED, COLO_CHECKPOINT_LOADED, + + COLO_GUEST_SHUTDOWN }; static QEMUBH *colo_bh; @@ -218,7 +220,7 @@ static int colo_ctl_get(QEMUFile *f, uint64_t require) static int colo_do_checkpoint_transaction(MigrationState *s, QEMUFile *control) { - int ret; + int colo_shutdown, ret; size_t size; QEMUFile *trans = NULL; @@ -245,6 +247,7 @@ static int colo_do_checkpoint_transaction(MigrationState *s, QEMUFile *control) } /* suspend and save vm state to colo buffer */ qemu_mutex_lock_iothread(); + colo_shutdown = colo_shutdown_requested; vm_stop_force_state(RUN_STATE_COLO); qemu_mutex_unlock_iothread(); trace_colo_vm_state_change("run", "stop"); @@ -301,6 +304,16 @@ static int colo_do_checkpoint_transaction(MigrationState *s, QEMUFile *control) } trace_colo_receive_message("COLO_CHECKPOINT_LOADED"); + if (colo_shutdown) { + colo_ctl_put(s->file, COLO_GUEST_SHUTDOWN); + qemu_fflush(s->file); + colo_shutdown_requested = 0; + qemu_system_shutdown_request_core(); + while (1) { + ; + } + } + ret = 0; /* resume master */ qemu_mutex_lock_iothread(); @@ -365,6 +378,10 @@ static void *colo_thread(void *opaque) error_report("failover request"); goto out; } + + if (colo_shutdown_requested) { + goto do_checkpoint; + } /* wait for a colo checkpoint */ proxy_checkpoint_req = colo_proxy_compare(); if (proxy_checkpoint_req < 0) { @@ -478,6 +495,18 @@ static int colo_wait_handle_cmd(QEMUFile *f, int *checkpoint_request) case COLO_CHECKPOINT_NEW: *checkpoint_request = 1; return 0; + case COLO_GUEST_SHUTDOWN: + qemu_mutex_lock_iothread(); + vm_stop_force_state(RUN_STATE_COLO); + qemu_system_shutdown_request_core(); + qemu_mutex_unlock_iothread(); + trace_colo_receive_message("COLO_GUEST_SHUTDOWN"); + /* the main thread will exit and termiante the whole + * process, do we need some cleanup? + */ + for (;;) { + ; + } default: return -1; } diff --git a/vl.c b/vl.c index 822bd08..26e3ae5 100644 --- a/vl.c +++ b/vl.c @@ -1533,6 +1533,8 @@ static NotifierList wakeup_notifiers = NOTIFIER_LIST_INITIALIZER(wakeup_notifiers); static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE); +int colo_shutdown_requested; + int qemu_shutdown_requested_get(void) { return shutdown_requested; @@ -1649,6 +1651,10 @@ void qemu_system_reset(bool report) void qemu_system_reset_request(void) { if (no_reboot) { + qemu_system_shutdown_request(); + if (!shutdown_requested) {/* colo handle it ? */ + return; + } shutdown_requested = 1; } else { reset_requested = 1; @@ -1717,13 +1723,29 @@ void qemu_system_killed(int signal, pid_t pid) qemu_system_shutdown_request(); } -void qemu_system_shutdown_request(void) +void qemu_system_shutdown_request_core(void) { - trace_qemu_system_shutdown_request(); shutdown_requested = 1; qemu_notify_event(); } +void qemu_system_shutdown_request(void) +{ + trace_qemu_system_shutdown_request(); + /* + * if in colo mode, we need do some significant work before respond to the + * shutdown request. + */ + if (loadvm_in_colo_state()) { + return ; /* primary's responsibility */ + } + if (migrate_in_colo_state()) { + colo_shutdown_requested = 1; + return; + } + qemu_system_shutdown_request_core(); +} + static void qemu_system_powerdown(void) { qapi_event_send_powerdown(&error_abort); -- 1.7.12.4