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(); }