提交 7ef0471b 编写于 作者: D Daniel P. Berrangé

qemu: don't retry connect() if doing FD passing

Since libvirt called bind() and listen() on the UNIX socket, it is
guaranteed that connect() will immediately succeed, if QEMU is running
normally. It will only fail if QEMU has closed the monitor socket by
mistake or if QEMU has exited, letting the kernel close it.

With this in mind we can remove the retry loop and timeout when
connecting to the QEMU monitor if we are doing FD passing. Libvirt can
go straight to sending the QMP greeting and will simply block waiting
for a reply until QEMU is ready.
Reviewed-by: NJohn Ferlan <jferlan@redhat.com>
Signed-off-by: NDaniel P. Berrangé <berrange@redhat.com>
上级 30fb2276
...@@ -4260,7 +4260,7 @@ virQEMUCapsInitQMPCommandRun(virQEMUCapsInitQMPCommandPtr cmd, ...@@ -4260,7 +4260,7 @@ virQEMUCapsInitQMPCommandRun(virQEMUCapsInitQMPCommandPtr cmd,
cmd->vm->pid = cmd->pid; cmd->vm->pid = cmd->pid;
if (!(cmd->mon = qemuMonitorOpen(cmd->vm, &cmd->config, true, if (!(cmd->mon = qemuMonitorOpen(cmd->vm, &cmd->config, true, true,
0, &callbacks, NULL))) 0, &callbacks, NULL)))
goto ignore; goto ignore;
......
...@@ -334,6 +334,7 @@ qemuMonitorDispose(void *obj) ...@@ -334,6 +334,7 @@ qemuMonitorDispose(void *obj)
static int static int
qemuMonitorOpenUnix(const char *monitor, qemuMonitorOpenUnix(const char *monitor,
pid_t cpid, pid_t cpid,
bool retry,
unsigned long long timeout) unsigned long long timeout)
{ {
struct sockaddr_un addr; struct sockaddr_un addr;
...@@ -355,6 +356,7 @@ qemuMonitorOpenUnix(const char *monitor, ...@@ -355,6 +356,7 @@ qemuMonitorOpenUnix(const char *monitor,
goto error; goto error;
} }
if (retry) {
if (virTimeBackOffStart(&timebackoff, 1, timeout * 1000) < 0) if (virTimeBackOffStart(&timebackoff, 1, timeout * 1000) < 0)
goto error; goto error;
while (virTimeBackOffWait(&timebackoff)) { while (virTimeBackOffWait(&timebackoff)) {
...@@ -373,7 +375,6 @@ qemuMonitorOpenUnix(const char *monitor, ...@@ -373,7 +375,6 @@ qemuMonitorOpenUnix(const char *monitor,
virReportSystemError(errno, "%s", virReportSystemError(errno, "%s",
_("failed to connect to monitor socket")); _("failed to connect to monitor socket"));
goto error; goto error;
} }
if (ret != 0) { if (ret != 0) {
...@@ -381,6 +382,14 @@ qemuMonitorOpenUnix(const char *monitor, ...@@ -381,6 +382,14 @@ qemuMonitorOpenUnix(const char *monitor,
_("monitor socket did not show up")); _("monitor socket did not show up"));
goto error; goto error;
} }
} else {
ret = connect(monfd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
virReportSystemError(errno, "%s",
_("failed to connect to monitor socket"));
goto error;
}
}
return monfd; return monfd;
...@@ -893,6 +902,7 @@ qemuMonitorPtr ...@@ -893,6 +902,7 @@ qemuMonitorPtr
qemuMonitorOpen(virDomainObjPtr vm, qemuMonitorOpen(virDomainObjPtr vm,
virDomainChrSourceDefPtr config, virDomainChrSourceDefPtr config,
bool json, bool json,
bool retry,
unsigned long long timeout, unsigned long long timeout,
qemuMonitorCallbacksPtr cb, qemuMonitorCallbacksPtr cb,
void *opaque) void *opaque)
...@@ -907,7 +917,7 @@ qemuMonitorOpen(virDomainObjPtr vm, ...@@ -907,7 +917,7 @@ qemuMonitorOpen(virDomainObjPtr vm,
case VIR_DOMAIN_CHR_TYPE_UNIX: case VIR_DOMAIN_CHR_TYPE_UNIX:
hasSendFD = true; hasSendFD = true;
if ((fd = qemuMonitorOpenUnix(config->data.nix.path, if ((fd = qemuMonitorOpenUnix(config->data.nix.path,
vm->pid, timeout)) < 0) vm->pid, retry, timeout)) < 0)
return NULL; return NULL;
break; break;
......
...@@ -313,6 +313,7 @@ char *qemuMonitorUnescapeArg(const char *in); ...@@ -313,6 +313,7 @@ char *qemuMonitorUnescapeArg(const char *in);
qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm, qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm,
virDomainChrSourceDefPtr config, virDomainChrSourceDefPtr config,
bool json, bool json,
bool retry,
unsigned long long timeout, unsigned long long timeout,
qemuMonitorCallbacksPtr cb, qemuMonitorCallbacksPtr cb,
void *opaque) void *opaque)
......
...@@ -1679,7 +1679,7 @@ qemuProcessInitMonitor(virQEMUDriverPtr driver, ...@@ -1679,7 +1679,7 @@ qemuProcessInitMonitor(virQEMUDriverPtr driver,
static int static int
qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int asyncJob, qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int asyncJob,
qemuDomainLogContextPtr logCtxt) bool retry, qemuDomainLogContextPtr logCtxt)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
qemuMonitorPtr mon = NULL; qemuMonitorPtr mon = NULL;
...@@ -1710,6 +1710,7 @@ qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int asyncJob, ...@@ -1710,6 +1710,7 @@ qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int asyncJob,
mon = qemuMonitorOpen(vm, mon = qemuMonitorOpen(vm,
monConfig, monConfig,
priv->monJSON, priv->monJSON,
retry,
timeout, timeout,
&monitorCallbacks, &monitorCallbacks,
driver); driver);
...@@ -2087,17 +2088,23 @@ qemuProcessWaitForMonitor(virQEMUDriverPtr driver, ...@@ -2087,17 +2088,23 @@ qemuProcessWaitForMonitor(virQEMUDriverPtr driver,
{ {
int ret = -1; int ret = -1;
virHashTablePtr info = NULL; virHashTablePtr info = NULL;
qemuDomainObjPrivatePtr priv; qemuDomainObjPrivatePtr priv = vm->privateData;
bool retry = true;
if (priv->qemuCaps &&
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS))
retry = false;
VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name); VIR_DEBUG("Connect monitor to vm=%p name='%s' retry=%d",
if (qemuConnectMonitor(driver, vm, asyncJob, logCtxt) < 0) vm, vm->def->name, retry);
if (qemuConnectMonitor(driver, vm, asyncJob, retry, logCtxt) < 0)
goto cleanup; goto cleanup;
/* Try to get the pty path mappings again via the monitor. This is much more /* Try to get the pty path mappings again via the monitor. This is much more
* reliable if it's available. * reliable if it's available.
* Note that the monitor itself can be on a pty, so we still need to try the * Note that the monitor itself can be on a pty, so we still need to try the
* log output method. */ * log output method. */
priv = vm->privateData;
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
goto cleanup; goto cleanup;
ret = qemuMonitorGetChardevInfo(priv->mon, &info); ret = qemuMonitorGetChardevInfo(priv->mon, &info);
...@@ -7416,6 +7423,7 @@ qemuProcessReconnect(void *opaque) ...@@ -7416,6 +7423,7 @@ qemuProcessReconnect(void *opaque)
unsigned int stopFlags = 0; unsigned int stopFlags = 0;
bool jobStarted = false; bool jobStarted = false;
virCapsPtr caps = NULL; virCapsPtr caps = NULL;
bool retry = true;
VIR_FREE(data); VIR_FREE(data);
...@@ -7446,10 +7454,15 @@ qemuProcessReconnect(void *opaque) ...@@ -7446,10 +7454,15 @@ qemuProcessReconnect(void *opaque)
* allowReboot in status XML and we need to initialize it. */ * allowReboot in status XML and we need to initialize it. */
qemuProcessPrepareAllowReboot(obj); qemuProcessPrepareAllowReboot(obj);
VIR_DEBUG("Reconnect monitor to %p '%s'", obj, obj->def->name); if (priv->qemuCaps &&
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS))
retry = false;
VIR_DEBUG("Reconnect monitor to def=%p name='%s' retry=%d",
obj, obj->def->name, retry);
/* XXX check PID liveliness & EXE path */ /* XXX check PID liveliness & EXE path */
if (qemuConnectMonitor(driver, obj, QEMU_ASYNC_JOB_NONE, NULL) < 0) if (qemuConnectMonitor(driver, obj, QEMU_ASYNC_JOB_NONE, retry, NULL) < 0)
goto error; goto error;
if (qemuHostdevUpdateActiveDomainDevices(driver, obj->def) < 0) if (qemuHostdevUpdateActiveDomainDevices(driver, obj->def) < 0)
......
...@@ -1252,6 +1252,7 @@ qemuMonitorTestNew(bool json, ...@@ -1252,6 +1252,7 @@ qemuMonitorTestNew(bool json,
if (!(test->mon = qemuMonitorOpen(test->vm, if (!(test->mon = qemuMonitorOpen(test->vm,
&src, &src,
json, json,
true,
0, 0,
&qemuMonitorTestCallbacks, &qemuMonitorTestCallbacks,
driver))) driver)))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册