qemu: use systemd's TerminateMachine to kill all processes

If we don't properly clean up all processes in the
machine-<vmname>.scope systemd won't remove the cgroup and subsequent vm
starts fail with

  'CreateMachine: File exists'

Additional processes can e.g. be added via

  echo $PID > /sys/fs/cgroup/systemd/machine.slice/machine-${VMNAME}.scope/tasks

but there are other cases like

  http://bugs.debian.org/761521

Invoke TerminateMachine to be on the safe side since systemd tracks the
cgroup anyway. This is a noop if all processes have terminated already.
This commit is contained in:
Guido Günther 2014-09-25 13:32:58 +02:00
parent 92427948b3
commit 4882618ed1
6 changed files with 30 additions and 4 deletions

View File

@ -1118,6 +1118,7 @@ virCgroupSetMemorySoftLimit;
virCgroupSetMemSwapHardLimit; virCgroupSetMemSwapHardLimit;
virCgroupSetOwner; virCgroupSetOwner;
virCgroupSupportsCpuBW; virCgroupSupportsCpuBW;
virCgroupTerminateMachine;
# util/virclosecallbacks.h # util/virclosecallbacks.h

View File

@ -1206,13 +1206,22 @@ qemuSetupCgroupForIOThreads(virDomainObjPtr vm)
} }
int int
qemuRemoveCgroup(virDomainObjPtr vm) qemuRemoveCgroup(virQEMUDriverPtr driver,
virDomainObjPtr vm)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
if (priv->cgroup == NULL) if (priv->cgroup == NULL)
return 0; /* Not supported, so claim success */ return 0; /* Not supported, so claim success */
if (virCgroupTerminateMachine(vm->def->name,
"qemu",
cfg->privileged) < 0) {
if (!virCgroupNewIgnoreError())
VIR_DEBUG("Failed to terminate cgroup for %s", vm->def->name);
}
return virCgroupRemove(priv->cgroup); return virCgroupRemove(priv->cgroup);
} }

View File

@ -66,7 +66,7 @@ int qemuSetupCgroupForIOThreads(virDomainObjPtr vm);
int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver, int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
virBitmapPtr nodemask); virBitmapPtr nodemask);
int qemuRemoveCgroup(virDomainObjPtr vm); int qemuRemoveCgroup(virQEMUDriverPtr driver, virDomainObjPtr vm);
int qemuAddToCgroup(virDomainObjPtr vm); int qemuAddToCgroup(virDomainObjPtr vm);
#endif /* __QEMU_CGROUP_H__ */ #endif /* __QEMU_CGROUP_H__ */

View File

@ -4143,7 +4143,7 @@ int qemuProcessStart(virConnectPtr conn,
/* Ensure no historical cgroup for this VM is lying around bogus /* Ensure no historical cgroup for this VM is lying around bogus
* settings */ * settings */
VIR_DEBUG("Ensuring no historical cgroup is lying around"); VIR_DEBUG("Ensuring no historical cgroup is lying around");
qemuRemoveCgroup(vm); qemuRemoveCgroup(driver, vm);
for (i = 0; i < vm->def->ngraphics; ++i) { for (i = 0; i < vm->def->ngraphics; ++i) {
virDomainGraphicsDefPtr graphics = vm->def->graphics[i]; virDomainGraphicsDefPtr graphics = vm->def->graphics[i];
@ -4921,7 +4921,7 @@ void qemuProcessStop(virQEMUDriverPtr driver,
} }
retry: retry:
if ((ret = qemuRemoveCgroup(vm)) < 0) { if ((ret = qemuRemoveCgroup(driver, vm)) < 0) {
if (ret == -EBUSY && (retries++ < 5)) { if (ret == -EBUSY && (retries++ < 5)) {
usleep(200*1000); usleep(200*1000);
goto retry; goto retry;

View File

@ -1680,6 +1680,17 @@ virCgroupNewMachineSystemd(const char *name,
} }
/*
* Returns 0 on success, -1 on fatal error
*/
int virCgroupTerminateMachine(const char *name,
const char *drivername,
bool privileged)
{
return virSystemdTerminateMachine(name, drivername, privileged);
}
static int static int
virCgroupNewMachineManual(const char *name, virCgroupNewMachineManual(const char *name,
const char *drivername, const char *drivername,

View File

@ -106,6 +106,11 @@ int virCgroupNewMachine(const char *name,
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
ATTRIBUTE_NONNULL(4); ATTRIBUTE_NONNULL(4);
int virCgroupTerminateMachine(const char *name,
const char *drivername,
bool privileged)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
bool virCgroupNewIgnoreError(void); bool virCgroupNewIgnoreError(void);
void virCgroupFree(virCgroupPtr *group); void virCgroupFree(virCgroupPtr *group);