提交 93e59975 编写于 作者: E Eric Blake

qemu: don't leave shutdown inhibited on attach failure

While debugging a failure of 'virsh qemu-attach', I noticed that
we were leaking the count of active domains on failure.  This
means that a libvirtd session that is supposed to quit after
active domains disappear will hang around forever.

* src/qemu/qemu_process.c (qemuProcessAttach): Undo count of
active domains on failure.
Signed-off-by: NEric Blake <eblake@redhat.com>
上级 2b1ef11c
...@@ -4362,6 +4362,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -4362,6 +4362,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
const char *model; const char *model;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virCapsPtr caps = NULL; virCapsPtr caps = NULL;
bool active = false;
VIR_DEBUG("Beginning VM attach process"); VIR_DEBUG("Beginning VM attach process");
...@@ -4373,7 +4374,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -4373,7 +4374,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
} }
if (!(caps = virQEMUDriverGetCapabilities(driver, false))) if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
goto cleanup; goto error;
/* Do this upfront, so any part of the startup process can add /* Do this upfront, so any part of the startup process can add
* runtime state to vm->def that won't be persisted. This let's us * runtime state to vm->def that won't be persisted. This let's us
...@@ -4381,60 +4382,59 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -4381,60 +4382,59 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
*/ */
VIR_DEBUG("Setting current domain def as transient"); VIR_DEBUG("Setting current domain def as transient");
if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0) if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0)
goto cleanup; goto error;
vm->def->id = qemuDriverAllocateID(driver); vm->def->id = qemuDriverAllocateID(driver);
if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
driver->inhibitCallback(true, driver->inhibitOpaque); driver->inhibitCallback(true, driver->inhibitOpaque);
active = true;
if (virFileMakePath(cfg->logDir) < 0) { if (virFileMakePath(cfg->logDir) < 0) {
virReportSystemError(errno, virReportSystemError(errno,
_("cannot create log directory %s"), _("cannot create log directory %s"),
cfg->logDir); cfg->logDir);
goto cleanup; goto error;
} }
VIR_FREE(priv->pidfile); VIR_FREE(priv->pidfile);
if (VIR_STRDUP(priv->pidfile, pidfile) < 0) if (VIR_STRDUP(priv->pidfile, pidfile) < 0)
goto cleanup; goto error;
VIR_DEBUG("Detect security driver config"); VIR_DEBUG("Detect security driver config");
sec_managers = virSecurityManagerGetNested(driver->securityManager); sec_managers = virSecurityManagerGetNested(driver->securityManager);
if (sec_managers == NULL) { if (sec_managers == NULL)
goto cleanup; goto error;
}
for (i = 0; sec_managers[i]; i++) { for (i = 0; sec_managers[i]; i++) {
model = virSecurityManagerGetModel(sec_managers[i]); model = virSecurityManagerGetModel(sec_managers[i]);
seclabeldef = virDomainDefGetSecurityLabelDef(vm->def, model); seclabeldef = virDomainDefGetSecurityLabelDef(vm->def, model);
if (seclabeldef == NULL) { if (seclabeldef == NULL)
goto cleanup; goto error;
}
seclabeldef->type = VIR_DOMAIN_SECLABEL_STATIC; seclabeldef->type = VIR_DOMAIN_SECLABEL_STATIC;
if (VIR_ALLOC(seclabel) < 0) if (VIR_ALLOC(seclabel) < 0)
goto cleanup; goto error;
if (virSecurityManagerGetProcessLabel(driver->securityManager, if (virSecurityManagerGetProcessLabel(driver->securityManager,
vm->def, vm->pid, seclabel) < 0) vm->def, vm->pid, seclabel) < 0)
goto cleanup; goto error;
if (VIR_STRDUP(seclabeldef->model, model) < 0) if (VIR_STRDUP(seclabeldef->model, model) < 0)
goto cleanup; goto error;
if (VIR_STRDUP(seclabeldef->label, seclabel->label) < 0) if (VIR_STRDUP(seclabeldef->label, seclabel->label) < 0)
goto cleanup; goto error;
VIR_FREE(seclabel); VIR_FREE(seclabel);
} }
VIR_DEBUG("Creating domain log file"); VIR_DEBUG("Creating domain log file");
if ((logfile = qemuDomainCreateLog(driver, vm, false)) < 0) if ((logfile = qemuDomainCreateLog(driver, vm, false)) < 0)
goto cleanup; goto error;
VIR_DEBUG("Determining emulator version"); VIR_DEBUG("Determining emulator version");
virObjectUnref(priv->qemuCaps); virObjectUnref(priv->qemuCaps);
if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache, if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
vm->def->emulator))) vm->def->emulator)))
goto cleanup; goto error;
VIR_DEBUG("Preparing monitor state"); VIR_DEBUG("Preparing monitor state");
priv->monConfig = monConfig; priv->monConfig = monConfig;
...@@ -4453,11 +4453,11 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -4453,11 +4453,11 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
VIR_DEBUG("Assigning domain PCI addresses"); VIR_DEBUG("Assigning domain PCI addresses");
if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm)) < 0) if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm)) < 0)
goto cleanup; goto error;
} }
if ((timestamp = virTimeStringNow()) == NULL) { if ((timestamp = virTimeStringNow()) == NULL) {
goto cleanup; goto error;
} else { } else {
if (safewrite(logfile, timestamp, strlen(timestamp)) < 0 || if (safewrite(logfile, timestamp, strlen(timestamp)) < 0 ||
safewrite(logfile, ATTACH_POSTFIX, strlen(ATTACH_POSTFIX)) < 0) { safewrite(logfile, ATTACH_POSTFIX, strlen(ATTACH_POSTFIX)) < 0) {
...@@ -4474,7 +4474,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -4474,7 +4474,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
VIR_DEBUG("Waiting for monitor to show up"); VIR_DEBUG("Waiting for monitor to show up");
if (qemuProcessWaitForMonitor(driver, vm, priv->qemuCaps, -1) < 0) if (qemuProcessWaitForMonitor(driver, vm, priv->qemuCaps, -1) < 0)
goto cleanup; goto error;
/* Failure to connect to agent shouldn't be fatal */ /* Failure to connect to agent shouldn't be fatal */
if (qemuConnectAgent(driver, vm) < 0) { if (qemuConnectAgent(driver, vm) < 0) {
...@@ -4486,34 +4486,34 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -4486,34 +4486,34 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
VIR_DEBUG("Detecting VCPU PIDs"); VIR_DEBUG("Detecting VCPU PIDs");
if (qemuProcessDetectVcpuPIDs(driver, vm) < 0) if (qemuProcessDetectVcpuPIDs(driver, vm) < 0)
goto cleanup; goto error;
/* If we have -device, then addresses are assigned explicitly. /* If we have -device, then addresses are assigned explicitly.
* If not, then we have to detect dynamic ones here */ * If not, then we have to detect dynamic ones here */
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
VIR_DEBUG("Determining domain device PCI addresses"); VIR_DEBUG("Determining domain device PCI addresses");
if (qemuProcessInitPCIAddresses(driver, vm) < 0) if (qemuProcessInitPCIAddresses(driver, vm) < 0)
goto cleanup; goto error;
} }
VIR_DEBUG("Getting initial memory amount"); VIR_DEBUG("Getting initial memory amount");
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
if (qemuMonitorGetBalloonInfo(priv->mon, &vm->def->mem.cur_balloon) < 0) { if (qemuMonitorGetBalloonInfo(priv->mon, &vm->def->mem.cur_balloon) < 0) {
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
goto cleanup; goto error;
} }
if (qemuMonitorGetStatus(priv->mon, &running, &reason) < 0) { if (qemuMonitorGetStatus(priv->mon, &running, &reason) < 0) {
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
goto cleanup; goto error;
} }
if (qemuMonitorGetVirtType(priv->mon, &vm->def->virtType) < 0) { if (qemuMonitorGetVirtType(priv->mon, &vm->def->virtType) < 0) {
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
goto cleanup; goto error;
} }
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
if (!virDomainObjIsActive(vm)) if (!virDomainObjIsActive(vm))
goto cleanup; goto error;
if (running) { if (running) {
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
...@@ -4530,7 +4530,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -4530,7 +4530,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
VIR_DEBUG("Writing domain status to disk"); VIR_DEBUG("Writing domain status to disk");
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
goto cleanup; goto error;
/* Run an hook to allow admins to do some magic */ /* Run an hook to allow admins to do some magic */
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
...@@ -4546,7 +4546,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -4546,7 +4546,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
* If the script raised an error abort the launch * If the script raised an error abort the launch
*/ */
if (hookret < 0) if (hookret < 0)
goto cleanup; goto error;
} }
VIR_FORCE_CLOSE(logfile); VIR_FORCE_CLOSE(logfile);
...@@ -4557,10 +4557,13 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, ...@@ -4557,10 +4557,13 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
return 0; return 0;
cleanup: error:
/* We jump here if we failed to start the VM for any reason, or /* We jump here if we failed to attach to the VM for any reason.
* if we failed to initialize the now running VM. kill it off and * Leave the domain running, but pretend we never attempted to
* pretend we never started it */ * attach to it. */
if (active && virAtomicIntDecAndTest(&driver->nactive) &&
driver->inhibitCallback)
driver->inhibitCallback(false, driver->inhibitOpaque);
VIR_FORCE_CLOSE(logfile); VIR_FORCE_CLOSE(logfile);
VIR_FREE(seclabel); VIR_FREE(seclabel);
VIR_FREE(sec_managers); VIR_FREE(sec_managers);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册