+ qemu_fflush(s->to_dst_file);
+ colo_shutdown_requested = 0;
+ qemu_system_shutdown_request_core();
+ /* Fix me: Just let the colo thread exit ? */
+ qemu_thread_exit(0);
+ }
+
ret = 0;
/* Resume primary guest */
qemu_mutex_lock_iothread();
@@ -390,8 +402,9 @@ static void colo_process_checkpoint(MigrationState *s)
}
current_time = qemu_clock_get_ms(QEMU_CLOCK_HOST);
- if (current_time - checkpoint_time <
- s->parameters[MIGRATION_PARAMETER_X_CHECKPOINT_DELAY]) {
+ if ((current_time - checkpoint_time <
+ s->parameters[MIGRATION_PARAMETER_X_CHECKPOINT_DELAY]) &&
+ !colo_shutdown_requested) {
int64_t delay_ms;
delay_ms = s->parameters[MIGRATION_PARAMETER_X_CHECKPOINT_DELAY] -
@@ -465,6 +478,15 @@ static void colo_wait_handle_cmd(QEMUFile *f, int
*checkpoint_request,
case COLO_MESSAGE_CHECKPOINT_REQUEST:
*checkpoint_request = 1;
break;
+ case COLO_MESSAGE_GUEST_SHUTDOWN:
+ qemu_mutex_lock_iothread();
+ vm_stop_force_state(RUN_STATE_COLO);
+ qemu_system_shutdown_request_core();
+ qemu_mutex_unlock_iothread();
+ /* the main thread will exit and terminate the whole
+ * process, do we need some cleanup?
+ */
+ qemu_thread_exit(0);
default:
*checkpoint_request = 0;
error_setg(errp, "Got unknown COLO command: %d", cmd);
@@ -636,3 +658,19 @@ out:
return NULL;
}
+
+bool colo_shutdown(void)
+{
+ /*
+ * if in colo mode, we need do some significant work before respond
+ * to the shutdown request.
+ */
+ if (migration_incoming_in_colo_state()) {
+ return true; /* primary's responsibility */
+ }
+ if (migration_in_colo_state()) {
+ colo_shutdown_requested = 1;
+ return true;
+ }
+ return false;
+}
diff --git a/qapi-schema.json b/qapi-schema.json
index 7fec696..4d8ba04 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -752,12 +752,14 @@
#
# @vmstate-loaded: VM's state has been loaded by SVM.
#
+# @guest-shutdown: shutdown require from PVM to SVM
+#
# Since: 2.6
##
{ 'enum': 'COLOMessage',
'data': [ 'checkpoint-ready', 'checkpoint-request', 'checkpoint-reply',
'vmstate-send', 'vmstate-size', 'vmstate-received',
- 'vmstate-loaded' ] }
+ 'vmstate-loaded', 'guest-shutdown' ] }
##
# @COLOMode
diff --git a/stubs/migration-colo.c b/stubs/migration-colo.c
index a6cd6e5..1996cd9 100644
--- a/stubs/migration-colo.c
+++ b/stubs/migration-colo.c
@@ -43,3 +43,8 @@ void qmp_x_colo_lost_heartbeat(Error **errp)
" with --enable-colo option in order to support"
" COLO feature");
}
+
+bool colo_shutdown(void)
+{
+ return false;
+}
diff --git a/vl.c b/vl.c
index f16fe2d..90da8d1 100644
--- a/vl.c
+++ b/vl.c
@@ -1631,6 +1631,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;
@@ -1762,7 +1764,10 @@ void qemu_system_guest_panicked(void)
void qemu_system_reset_request(void)
{
if (no_reboot) {
- shutdown_requested = 1;
+ qemu_system_shutdown_request();
+ if (!shutdown_requested) {/* colo handle it ? */
+ return;
+ }
} else {
reset_requested = 1;
}
@@ -1835,14 +1840,22 @@ void qemu_system_killed(int signal, pid_t pid)
qemu_notify_event();
}
-void qemu_system_shutdown_request(void)
+void qemu_system_shutdown_request_core(void)
{
- trace_qemu_system_shutdown_request();
replay_shutdown_request();
shutdown_requested = 1;
qemu_notify_event();
}
+void qemu_system_shutdown_request(void)
+{
+ trace_qemu_system_shutdown_request();
+ if (colo_shutdown()) {
+ return;
+ }
+ qemu_system_shutdown_request_core();
+}
+
static void qemu_system_powerdown(void)
{
qapi_event_send_powerdown(&error_abort);
--
1.8.3.1