[libvirt] [PATCH] qemu: use systemd's TerminateMachine to kill all processes
Cole Robinson
crobinso at redhat.com
Tue Sep 30 14:10:51 UTC 2014
On 09/25/2014 08:30 AM, Guido Günther wrote:
> 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.
Thanks for the patch, I've definitely seen this a handful of times on Fedora
as well.
> ---
> src/libvirt_private.syms | 1 +
> src/qemu/qemu_cgroup.c | 11 ++++++++++-
> src/qemu/qemu_cgroup.h | 2 +-
> src/qemu/qemu_process.c | 4 ++--
> src/util/vircgroup.c | 11 +++++++++++
> src/util/vircgroup.h | 5 +++++
> 6 files changed, 30 insertions(+), 4 deletions(-)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 51a692b..99ef1db 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1115,6 +1115,7 @@ virCgroupSetMemorySoftLimit;
> virCgroupSetMemSwapHardLimit;
> virCgroupSetOwner;
> virCgroupSupportsCpuBW;
> +virCgroupTerminateMachine;
>
>
> # util/virclosecallbacks.h
> diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
> index 7c6b2c1..0ab7227 100644
> --- a/src/qemu/qemu_cgroup.c
> +++ b/src/qemu/qemu_cgroup.c
> @@ -1188,13 +1188,22 @@ qemuSetupCgroupForIOThreads(virDomainObjPtr vm)
> }
>
> int
> -qemuRemoveCgroup(virDomainObjPtr vm)
> +qemuRemoveCgroup(virQEMUDriverPtr driver,
> + virDomainObjPtr vm)
> {
> qemuDomainObjPrivatePtr priv = vm->privateData;
> + virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
>
> if (priv->cgroup == NULL)
> 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);
> }
>
> diff --git a/src/qemu/qemu_cgroup.h b/src/qemu/qemu_cgroup.h
> index 8a2c723..4a4f22c 100644
> --- a/src/qemu/qemu_cgroup.h
> +++ b/src/qemu/qemu_cgroup.h
> @@ -66,7 +66,7 @@ int qemuSetupCgroupForIOThreads(virDomainObjPtr vm);
> int qemuSetupCgroupForEmulator(virQEMUDriverPtr driver,
> virDomainObjPtr vm,
> virBitmapPtr nodemask);
> -int qemuRemoveCgroup(virDomainObjPtr vm);
> +int qemuRemoveCgroup(virQEMUDriverPtr driver, virDomainObjPtr vm);
> int qemuAddToCgroup(virDomainObjPtr vm);
>
> #endif /* __QEMU_CGROUP_H__ */
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index 13614e9..e7cce1a 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -4131,7 +4131,7 @@ int qemuProcessStart(virConnectPtr conn,
> /* Ensure no historical cgroup for this VM is lying around bogus
> * settings */
> VIR_DEBUG("Ensuring no historical cgroup is lying around");
> - qemuRemoveCgroup(vm);
> + qemuRemoveCgroup(driver, vm);
>
> for (i = 0; i < vm->def->ngraphics; ++i) {
> virDomainGraphicsDefPtr graphics = vm->def->graphics[i];
> @@ -4909,7 +4909,7 @@ void qemuProcessStop(virQEMUDriverPtr driver,
> }
>
> retry:
> - if ((ret = qemuRemoveCgroup(vm)) < 0) {
> + if ((ret = qemuRemoveCgroup(driver, vm)) < 0) {
> if (ret == -EBUSY && (retries++ < 5)) {
> usleep(200*1000);
> goto retry;
> diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
> index 1dbe6f9..d69f71b 100644
> --- a/src/util/vircgroup.c
> +++ b/src/util/vircgroup.c
> @@ -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
> virCgroupNewMachineManual(const char *name,
> const char *drivername,
> diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
> index 19e82d1..7718a07 100644
> --- a/src/util/vircgroup.h
> +++ b/src/util/vircgroup.h
> @@ -106,6 +106,11 @@ int virCgroupNewMachine(const char *name,
> ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
> ATTRIBUTE_NONNULL(4);
>
> +int virCgroupTerminateMachine(const char *name,
> + const char *drivername,
> + bool privileged)
> + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
> +
> bool virCgroupNewIgnoreError(void);
>
> void virCgroupFree(virCgroupPtr *group);
>
All the above seems reasonable to me. ACK
- Cole
More information about the libvir-list
mailing list