From: Jim Fehlig <[email protected]>

When shutting down a VM, libvirt sends the associated QEMU process
SIGTERM, waits 10 seconds for it to disappear, optionally sends SIGKILL,
then waits up to another 30 seconds for the process to exit before
reporting and returning an error. Commit be2ca04447 added 2 seconds per
assigned host device to the total time libvirt waits for a QEMU process
to terminate. Other scenarios than the one described in be2ca04447 could
delay the clean exit of QEMU, e.g. reclaiming memory of VMs with large
memory allocations backed by 4k pages on the host.

Instead of trying to cover all such scenarios based on VM configuration,
introduce a 'process_exit_wait' setting in qemu.conf to control how much
additional time (in seconds) libvirt will wait for a QEMU process to
terminate before reporting an error.

Signed-off-by: Jim Fehlig <[email protected]>
---
 src/qemu/libvirtd_qemu.aug         |  1 +
 src/qemu/qemu.conf.in              | 12 ++++++++++++
 src/qemu/qemu_conf.c               |  3 +++
 src/qemu/qemu_conf.h               |  1 +
 src/qemu/qemu_process.c            | 13 ++++++++++---
 src/qemu/test_libvirtd_qemu.aug.in |  1 +
 6 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index 311992e441..dc3d6d61df 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -132,6 +132,7 @@ module Libvirtd_qemu =
                  | bool_entry "dump_guest_core"
                  | str_entry "stdio_handler"
                  | int_entry "max_threads_per_process"
+                 | int_entry "process_exit_wait"
                  | str_entry "sched_core"
 
    let device_entry = bool_entry "mac_filter"
diff --git a/src/qemu/qemu.conf.in b/src/qemu/qemu.conf.in
index 97b0141cf6..2f24059053 100644
--- a/src/qemu/qemu.conf.in
+++ b/src/qemu/qemu.conf.in
@@ -844,6 +844,18 @@
 #max_threads_per_process = 0
 
 
+# When shutting down a VM, libvirt will wait up to 40 seconds for
+# the associated QEMU process to exit before reporting an error.
+# For some VM configurations, QEMU might require more time to
+# cleanup and exit, e.g. VMs with very large memory allocations.
+#
+# If process_exit_wait is set to a positive interger, libvirt
+# will use the value as additional time to wait for the QEMU
+# process to exit before reporting it cannot be terminated.
+#
+#process_exit_wait = 0
+
+
 # If max_core is set to a non-zero integer, then QEMU will be
 # permitted to create core dumps when it crashes, provided its
 # RAM size is smaller than the limit set.
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index e30b146634..adcba137cc 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -934,6 +934,9 @@ virQEMUDriverConfigLoadProcessEntry(virQEMUDriverConfig 
*cfg,
         cfg->schedCore = val;
     }
 
+    if (virConfGetValueUInt(conf, "process_exit_wait", &cfg->processExitWait) 
< 0)
+        return -1;
+
     return 0;
 }
 
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 1d29f35c5d..bc78982123 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -211,6 +211,7 @@ struct _virQEMUDriverConfig {
     unsigned int maxProcesses;
     unsigned int maxFiles;
     unsigned int maxThreadsPerProc;
+    unsigned int processExitWait;
     unsigned long long maxCore;
     bool dumpGuestCore;
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index b2506edce0..5042ffe339 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -9218,6 +9218,9 @@ qemuProcessInShutdownStartMonitor(virDomainObj *vm)
 int
 qemuProcessKill(virDomainObj *vm, unsigned int flags)
 {
+    qemuDomainObjPrivate *priv = vm->privateData;
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver);
+    unsigned int delay = cfg->processExitWait;
     int ret = -1;
 
     VIR_DEBUG("vm=%p name=%s pid=%lld flags=0x%x",
@@ -9238,11 +9241,15 @@ qemuProcessKill(virDomainObj *vm, unsigned int flags)
         return 0;
     }
 
-    /* Request an extra delay of two seconds per current nhostdevs
-     * to be safe against stalls by the kernel freeing up the resources */
+    /* If the administrator has not requested an explicit shutdown wait period,
+     * add an extra delay of two seconds per current nhostdevs to be safe 
against
+     * stalls by the kernel freeing up the resources */
+    if (delay == 0)
+        delay = vm->def->nhostdevs * 2;
+
     ret = virProcessKillPainfullyDelay(vm->pid,
                                        !!(flags & VIR_QEMU_PROCESS_KILL_FORCE),
-                                       vm->def->nhostdevs * 2,
+                                       delay,
                                        false);
 
     if (ret < 0 && (flags & VIR_QEMU_PROCESS_KILL_MONITOR_ON_ERROR)) {
diff --git a/src/qemu/test_libvirtd_qemu.aug.in 
b/src/qemu/test_libvirtd_qemu.aug.in
index c4cf9cf634..fb6cb1a1d4 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -97,6 +97,7 @@ module Test_libvirtd_qemu =
 { "max_processes" = "0" }
 { "max_files" = "0" }
 { "max_threads_per_process" = "0" }
+{ "process_exit_wait" = "0" }
 { "max_core" = "unlimited" }
 { "dump_guest_core" = "1" }
 { "mac_filter" = "1" }
-- 
2.51.0

Reply via email to