diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index da03ff4c61..5200b39a3f 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -4767,7 +4767,7 @@ virQEMUCapsInitQMPCommandRun(virQEMUCapsInitQMPCommandPtr cmd, cmd->vm->pid = cmd->pid; if (!(cmd->mon = qemuMonitorOpen(cmd->vm, &cmd->config, true, - &callbacks, NULL))) + 0, &callbacks, NULL))) goto ignore; virObjectLock(cmd->mon); diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index d71f84c800..066d3444bb 100644 --- a/src/qemu/qemu_monitor.c +++ b/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, pid_t cpid) 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 vm, } +#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; diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 847e9458a5..3c37a6ffe3 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -246,6 +246,7 @@ char *qemuMonitorUnescapeArg(const char *in); 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); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index b9c1847bba..7397f59c7a 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1658,6 +1658,7 @@ qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int asyncJob, qemuDomainObjPrivatePtr priv = vm->privateData; int ret = -1; qemuMonitorPtr mon = NULL; + unsigned long long timeout = 0; if (qemuSecuritySetDaemonSocketLabel(driver->securityManager, vm->def) < 0) { VIR_ERROR(_("Failed to set security context for monitor for %s"), @@ -1665,6 +1666,12 @@ qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int asyncJob, 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); @@ -1675,6 +1682,7 @@ qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int asyncJob, mon = qemuMonitorOpen(vm, priv->monConfig, priv->monJSON, + timeout, &monitorCallbacks, driver); diff --git a/tests/qemumonitortestutils.c b/tests/qemumonitortestutils.c index cfd0a38cbb..89857a6620 100644 --- a/tests/qemumonitortestutils.c +++ b/tests/qemumonitortestutils.c @@ -1175,6 +1175,7 @@ qemuMonitorTestNew(bool json, if (!(test->mon = qemuMonitorOpen(test->vm, &src, json, + 0, &qemuMonitorTestCallbacks, driver))) goto error;