1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
Date: Thu, 25 Sep 2014 13:32:58 +0200
Subject: 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.
Closes: #761521
---
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 2019ef5..7cbc35b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1118,6 +1118,7 @@ virCgroupSetMemorySoftLimit;
virCgroupSetMemSwapHardLimit;
virCgroupSetOwner;
virCgroupSupportsCpuBW;
+virCgroupTerminateMachine;
# util/virclosecallbacks.h
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index bd22b7f..fa894c5 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -1206,13 +1206,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 11eeb3c..712a25e 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4143,7 +4143,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];
@@ -4921,7 +4921,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);
|