@@ -37,4 +37,5 @@ COLOMode get_colo_mode(void);
void colo_do_failover(MigrationState *s);
void colo_checkpoint_notify(void *opaque);
+bool colo_handle_shutdown(void);
#endif
@@ -49,6 +49,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);
@@ -56,6 +58,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);
@@ -336,6 +336,21 @@ static int colo_do_checkpoint_transaction(MigrationState *s,
goto out;
}
+ if (colo_shutdown_requested) {
+ colo_send_message(s->to_dst_file, COLO_MESSAGE_GUEST_SHUTDOWN,
+ &local_err);
+ if (local_err) {
+ error_free(local_err);
+ /* Go on the shutdown process and throw the error message */
+ error_report("Failed to send shutdown message to SVM");
+ }
+ 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;
qemu_mutex_lock_iothread();
@@ -401,7 +416,9 @@ static void colo_process_checkpoint(MigrationState *s)
goto out;
}
- qemu_sem_wait(&s->colo_checkpoint_sem);
+ if (!colo_shutdown_requested) {
+ qemu_sem_wait(&s->colo_checkpoint_sem);
+ }
ret = colo_do_checkpoint_transaction(s, bioc, fb);
if (ret < 0) {
@@ -477,6 +494,16 @@ static void colo_wait_handle_message(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 be exit and terminate the whole
+ * process, do need some cleanup ?
+ */
+ qemu_thread_exit(0);
default:
*checkpoint_request = 0;
error_setg(errp, "Got unknown COLO message: %d", msg);
@@ -634,3 +661,20 @@ out:
return NULL;
}
+
+bool colo_handle_shutdown(void)
+{
+ /*
+ * If VM is in COLO-FT mode, we need do some significant work before
+ * respond to the shutdown request. Besides, Secondary VM will ignore
+ * the shutdown request from users.
+ */
+ if (migration_incoming_in_colo_state()) {
+ return true;
+ }
+ if (migration_in_colo_state()) {
+ colo_shutdown_requested = 1;
+ return true;
+ }
+ return false;
+}
@@ -1157,12 +1157,14 @@
#
# @vmstate-loaded: VM's state has been loaded by SVM.
#
+# @guest-shutdown: shutdown require from PVM to SVM
+#
# Since: 2.8
##
{ 'enum': 'COLOMessage',
'data': [ 'checkpoint-ready', 'checkpoint-request', 'checkpoint-reply',
'vmstate-send', 'vmstate-size', 'vmstate-received',
- 'vmstate-loaded' ] }
+ 'vmstate-loaded', 'guest-shutdown' ] }
##
# @COLOMode:
@@ -1587,6 +1587,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;
@@ -1713,7 +1715,10 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
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;
}
@@ -1786,14 +1791,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_handle_shutdown()) {
+ return;
+ }
+ qemu_system_shutdown_request_core();
+}
+
static void qemu_system_powerdown(void)
{
qapi_event_send_powerdown(&error_abort);