51e9f38d3f
- qemu: Fix monitor timeout with large memory VMs 67dcb797-virTimeBackOffWait-sleepcap.patch 85af0b80-qemu-adaptive-montimeout.patch bsc#1013113 OBS-URL: https://build.opensuse.org/request/show/480654 OBS-URL: https://build.opensuse.org/package/show/Virtualization/libvirt?expand=0&rev=591
172 lines
6.6 KiB
Diff
172 lines
6.6 KiB
Diff
commit 85af0b803cd19a03f71bd01ab4e045552410368f
|
|
Author: Michal Privoznik <mprivozn@redhat.com>
|
|
Date: Sat Mar 11 07:23:42 2017 +0100
|
|
|
|
qemu: Adaptive timeout for connecting to monitor
|
|
|
|
There were couple of reports on the list (e.g. [1]) that guests
|
|
with huge amounts of RAM are unable to start because libvirt
|
|
kills qemu in the initialization phase. The problem is that if
|
|
guest is configured to use hugepages kernel has to zero them all
|
|
out before handing over to qemu process. For instance, 402GiB
|
|
worth of 1GiB pages took around 105 seconds (~3.8GiB/s). Since we
|
|
do not want to make the timeout for connecting to monitor
|
|
configurable, we have to teach libvirt to count with this
|
|
fact. This commit implements "1s per each 1GiB of RAM" approach
|
|
as suggested here [2].
|
|
|
|
1: https://www.redhat.com/archives/libvir-list/2017-March/msg00373.html
|
|
2: https://www.redhat.com/archives/libvir-list/2017-March/msg00405.html
|
|
|
|
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
|
Index: libvirt-3.1.0/src/qemu/qemu_capabilities.c
|
|
===================================================================
|
|
--- libvirt-3.1.0.orig/src/qemu/qemu_capabilities.c
|
|
+++ libvirt-3.1.0/src/qemu/qemu_capabilities.c
|
|
@@ -4571,7 +4571,7 @@ virQEMUCapsInitQMPCommandRun(virQEMUCaps
|
|
cmd->vm->pid = cmd->pid;
|
|
|
|
if (!(cmd->mon = qemuMonitorOpen(cmd->vm, &cmd->config, true,
|
|
- &callbacks, NULL)))
|
|
+ 0, &callbacks, NULL)))
|
|
goto ignore;
|
|
|
|
virObjectLock(cmd->mon);
|
|
Index: libvirt-3.1.0/src/qemu/qemu_monitor.c
|
|
===================================================================
|
|
--- libvirt-3.1.0.orig/src/qemu/qemu_monitor.c
|
|
+++ libvirt-3.1.0/src/qemu/qemu_monitor.c
|
|
@@ -327,11 +327,13 @@ qemuMonitorDispose(void *obj)
|
|
|
|
|
|
static int
|
|
-qemuMonitorOpenUnix(const char *monitor, pid_t cpid)
|
|
+qemuMonitorOpenUnix(const char *monitor,
|
|
+ pid_t cpid,
|
|
+ unsigned long long timeout)
|
|
{
|
|
struct sockaddr_un addr;
|
|
int monfd;
|
|
- virTimeBackOffVar timeout;
|
|
+ virTimeBackOffVar timebackoff;
|
|
int ret = -1;
|
|
|
|
if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
|
@@ -348,9 +350,9 @@ qemuMonitorOpenUnix(const char *monitor,
|
|
goto error;
|
|
}
|
|
|
|
- if (virTimeBackOffStart(&timeout, 1, 30*1000 /* ms */) < 0)
|
|
+ if (virTimeBackOffStart(&timebackoff, 1, timeout * 1000) < 0)
|
|
goto error;
|
|
- while (virTimeBackOffWait(&timeout)) {
|
|
+ while (virTimeBackOffWait(&timebackoff)) {
|
|
ret = connect(monfd, (struct sockaddr *) &addr, sizeof(addr));
|
|
|
|
if (ret == 0)
|
|
@@ -871,10 +873,30 @@ qemuMonitorOpenInternal(virDomainObjPtr
|
|
}
|
|
|
|
|
|
+#define QEMU_DEFAULT_MONITOR_WAIT 30
|
|
+
|
|
+/**
|
|
+ * qemuMonitorOpen:
|
|
+ * @vm: domain object
|
|
+ * @config: monitor configuration
|
|
+ * @json: enable JSON on the monitor
|
|
+ * @timeout: number of seconds to add to default timeout
|
|
+ * @cb: monitor event handles
|
|
+ * @opaque: opaque data for @cb
|
|
+ *
|
|
+ * Opens the monitor for running qemu. It may happen that it
|
|
+ * takes some time for qemu to create the monitor socket (e.g.
|
|
+ * because kernel is zeroing configured hugepages), therefore we
|
|
+ * wait up to default + timeout seconds for the monitor to show
|
|
+ * up after which a failure is claimed.
|
|
+ *
|
|
+ * Returns monitor object, NULL on error.
|
|
+ */
|
|
qemuMonitorPtr
|
|
qemuMonitorOpen(virDomainObjPtr vm,
|
|
virDomainChrSourceDefPtr config,
|
|
bool json,
|
|
+ unsigned long long timeout,
|
|
qemuMonitorCallbacksPtr cb,
|
|
void *opaque)
|
|
{
|
|
@@ -882,10 +904,14 @@ qemuMonitorOpen(virDomainObjPtr vm,
|
|
bool hasSendFD = false;
|
|
qemuMonitorPtr ret;
|
|
|
|
+ timeout += QEMU_DEFAULT_MONITOR_WAIT;
|
|
+
|
|
switch (config->type) {
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
|
hasSendFD = true;
|
|
- if ((fd = qemuMonitorOpenUnix(config->data.nix.path, vm ? vm->pid : 0)) < 0)
|
|
+ if ((fd = qemuMonitorOpenUnix(config->data.nix.path,
|
|
+ vm ? vm->pid : 0,
|
|
+ timeout)) < 0)
|
|
return NULL;
|
|
break;
|
|
|
|
Index: libvirt-3.1.0/src/qemu/qemu_monitor.h
|
|
===================================================================
|
|
--- libvirt-3.1.0.orig/src/qemu/qemu_monitor.h
|
|
+++ libvirt-3.1.0/src/qemu/qemu_monitor.h
|
|
@@ -246,6 +246,7 @@ char *qemuMonitorUnescapeArg(const char
|
|
qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm,
|
|
virDomainChrSourceDefPtr config,
|
|
bool json,
|
|
+ unsigned long long timeout,
|
|
qemuMonitorCallbacksPtr cb,
|
|
void *opaque)
|
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4);
|
|
Index: libvirt-3.1.0/src/qemu/qemu_process.c
|
|
===================================================================
|
|
--- libvirt-3.1.0.orig/src/qemu/qemu_process.c
|
|
+++ libvirt-3.1.0/src/qemu/qemu_process.c
|
|
@@ -1656,6 +1656,7 @@ qemuConnectMonitor(virQEMUDriverPtr driv
|
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
int ret = -1;
|
|
qemuMonitorPtr mon = NULL;
|
|
+ unsigned long long timeout = 0;
|
|
|
|
if (virSecurityManagerSetDaemonSocketLabel(driver->securityManager,
|
|
vm->def) < 0) {
|
|
@@ -1664,6 +1665,12 @@ qemuConnectMonitor(virQEMUDriverPtr driv
|
|
return -1;
|
|
}
|
|
|
|
+ /* When using hugepages, kernel zeroes them out before
|
|
+ * handing them over to qemu. This can be very time
|
|
+ * consuming. Therefore, add a second to timeout for each
|
|
+ * 1GiB of guest RAM. */
|
|
+ timeout = vm->def->mem.total_memory / (1024 * 1024);
|
|
+
|
|
/* Hold an extra reference because we can't allow 'vm' to be
|
|
* deleted until the monitor gets its own reference. */
|
|
virObjectRef(vm);
|
|
@@ -1674,6 +1681,7 @@ qemuConnectMonitor(virQEMUDriverPtr driv
|
|
mon = qemuMonitorOpen(vm,
|
|
priv->monConfig,
|
|
priv->monJSON,
|
|
+ timeout,
|
|
&monitorCallbacks,
|
|
driver);
|
|
|
|
Index: libvirt-3.1.0/tests/qemumonitortestutils.c
|
|
===================================================================
|
|
--- libvirt-3.1.0.orig/tests/qemumonitortestutils.c
|
|
+++ libvirt-3.1.0/tests/qemumonitortestutils.c
|
|
@@ -1175,6 +1175,7 @@ qemuMonitorTestNew(bool json,
|
|
if (!(test->mon = qemuMonitorOpen(test->vm,
|
|
&src,
|
|
json,
|
|
+ 0,
|
|
&qemuMonitorTestCallbacks,
|
|
driver)))
|
|
goto error;
|