From: Marian Rotariu <marian.c.rota...@gmail.com>

On shutdown, it is desirable that the introspection tool removes
its changes from the introspected VM, so that they don't reach the
hibernation file.

CC: Markus Armbruster <arm...@redhat.com>
Signed-off-by: Marian Rotariu <marian.c.rota...@gmail.com>
Signed-off-by: Adalbert Lazăr <ala...@bitdefender.com>
---
 accel/kvm/vmi.c                | 31 +++++++++++++++++++++++++++----
 include/sysemu/vmi-intercept.h |  1 +
 monitor/qmp-cmds.c             |  4 ++++
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/accel/kvm/vmi.c b/accel/kvm/vmi.c
index bee9798e54..2c6981a4bf 100644
--- a/accel/kvm/vmi.c
+++ b/accel/kvm/vmi.c
@@ -85,10 +85,12 @@ static const char *action_string[] = {
     "resume",
     "force-reset",
     "migrate",
+    "shutdown",
 };
 
 static bool suspend_pending;
 static bool migrate_pending;
+static bool shutdown_pending;
 
 #define TYPE_VM_INTROSPECTION "introspection"
 
@@ -511,6 +513,17 @@ static void enable_socket_reconnect(VMIntrospection *i)
 
 static void maybe_disable_socket_reconnect(VMIntrospection *i)
 {
+    if (shutdown_pending) {
+        /*
+         * We've got the shutdown notification, but the guest might not stop.
+         * We already caused the introspection tool to unhook
+         * because shutdown_pending was set.
+         * Let the socket connect again just in case the guest doesn't stop.
+         */
+        shutdown_pending = false;
+        return;
+    }
+
     if (i->reconnect_time == 0) {
         info_report("VMI: disable socket reconnect");
         i->reconnect_time = qemu_chr_fe_reconnect_time(&i->sock, 0);
@@ -526,6 +539,9 @@ static void 
continue_with_the_intercepted_action(VMIntrospection *i)
     case VMI_INTERCEPT_MIGRATE:
         start_live_migration_thread(migrate_get_current());
         break;
+    case VMI_INTERCEPT_SHUTDOWN:
+        qemu_system_powerdown_request();
+        break;
     default:
         error_report("VMI: %s: unexpected action %d",
                      __func__, i->intercepted_action);
@@ -625,9 +641,10 @@ static void chr_event_open(VMIntrospection *i)
 {
     Error *local_err = NULL;
 
-    if (suspend_pending || migrate_pending) {
-        info_report("VMI: %s: too soon (suspend=%d, migrate=%d)",
-                    __func__, suspend_pending, migrate_pending);
+    if (suspend_pending || migrate_pending || shutdown_pending) {
+        info_report("VMI: %s: too soon (suspend=%d, migrate=%d, shutdown=%d)",
+                    __func__, suspend_pending, migrate_pending,
+                    shutdown_pending);
         maybe_disable_socket_reconnect(i);
         qemu_chr_fe_disconnect(&i->sock);
         return;
@@ -662,7 +679,7 @@ static void chr_event_close(VMIntrospection *i)
     cancel_unhook_timer(i);
     cancel_handshake_timer(i);
 
-    if (suspend_pending || migrate_pending) {
+    if (suspend_pending || migrate_pending || shutdown_pending) {
         maybe_disable_socket_reconnect(i);
 
         if (i->intercepted_action != VMI_INTERCEPT_NONE) {
@@ -752,6 +769,9 @@ static bool record_intercept_action(VMI_intercept_command 
action)
     case VMI_INTERCEPT_MIGRATE:
         migrate_pending = true;
         break;
+    case VMI_INTERCEPT_SHUTDOWN:
+        shutdown_pending = true;
+        break;
     default:
         return false;
     }
@@ -839,6 +859,9 @@ static void vm_introspection_reset(void *opaque)
     }
 
     update_vm_start_time(i);
+
+    /* warm reset triggered by user */
+    shutdown_pending = false;
 }
 
 static bool make_cookie_hash(const char *key_id, uint8_t *cookie_hash,
diff --git a/include/sysemu/vmi-intercept.h b/include/sysemu/vmi-intercept.h
index 4b93d17f2b..da086d7a04 100644
--- a/include/sysemu/vmi-intercept.h
+++ b/include/sysemu/vmi-intercept.h
@@ -16,6 +16,7 @@ typedef enum {
     VMI_INTERCEPT_RESUME,
     VMI_INTERCEPT_FORCE_RESET,
     VMI_INTERCEPT_MIGRATE,
+    VMI_INTERCEPT_SHUTDOWN,
 } VMI_intercept_command;
 
 bool vm_introspection_intercept(VMI_intercept_command ic, Error **errp);
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index d164635b5f..333a4a0ecc 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -107,6 +107,10 @@ void qmp_system_reset(Error **errp)
 
 void qmp_system_powerdown(Error **errp)
 {
+    if (vm_introspection_intercept(VMI_INTERCEPT_SHUTDOWN, errp)) {
+        return;
+    }
+
     qemu_system_powerdown_request();
 }
 

Reply via email to