From ba776c58abac13bd5a539cd128c002284a363f58 Mon Sep 17 00:00:00 2001 Message-Id: From: "Daniel P. Berrange" Date: Wed, 31 Jul 2013 19:48:20 +0100 Subject: [PATCH] Enable support for systemd-machined in cgroups creation https://bugzilla.redhat.com/show_bug.cgi?id=980929 Make the virCgroupNewMachine method try to use systemd-machined first. If that fails, then fallback to using the traditional cgroup setup code path. Signed-off-by: Daniel P. Berrange (cherry picked from commit 2fe2470181ce3722788fd7125d3f1f9be87e6278) --- src/lxc/lxc_process.c | 10 +-- src/qemu/qemu_cgroup.c | 1 + src/util/vircgroup.c | 187 ++++++++++++++++++++++++++++++++++++++++++++----- src/util/vircgroup.h | 1 + 4 files changed, 179 insertions(+), 20 deletions(-) diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 247e516..0a28305 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -1203,8 +1203,9 @@ int virLXCProcessStart(virConnectPtr conn, goto cleanup; } - if (virCgroupNewDetectMachine(vm->def->name, "lxc", - vm->pid, -1, &priv->cgroup) < 0) + if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid, + vm->def->resource->partition, + -1, &priv->cgroup) < 0) goto error; if (!priv->cgroup) { @@ -1411,8 +1412,9 @@ virLXCProcessReconnectDomain(virDomainObjPtr vm, if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm))) goto error; - if (virCgroupNewDetectMachine(vm->def->name, "lxc", - vm->pid, -1, &priv->cgroup) < 0) + if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid, + vm->def->resource->partition, + -1, &priv->cgroup) < 0) goto error; if (!priv->cgroup) { diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 9f6b251..787ddeb 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -707,6 +707,7 @@ qemuConnectCgroup(virQEMUDriverPtr driver, if (virCgroupNewDetectMachine(vm->def->name, "qemu", vm->pid, + vm->def->resource->partition, cfg->cgroupControllers, &priv->cgroup) < 0) goto cleanup; diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index a70bb98..cfb4b3f 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -50,6 +50,7 @@ #include "virhash.h" #include "virhashcode.h" #include "virstring.h" +#include "virsystemd.h" #define CGROUP_MAX_VAL 512 @@ -102,11 +103,13 @@ static bool virCgroupValidateMachineGroup(virCgroupPtr group, const char *name, const char *drivername, + const char *partition, bool stripEmulatorSuffix) { size_t i; bool valid = false; char *partname; + char *scopename; if (virAsprintf(&partname, "%s.libvirt-%s", name, drivername) < 0) @@ -115,6 +118,15 @@ virCgroupValidateMachineGroup(virCgroupPtr group, if (virCgroupPartitionEscape(&partname) < 0) goto cleanup; + if (!partition) + partition = "/machine"; + + if (!(scopename = virSystemdMakeScopeName(name, drivername, partition))) + goto cleanup; + + if (virCgroupPartitionEscape(&scopename) < 0) + goto cleanup; + for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) { char *tmp; @@ -142,9 +154,10 @@ virCgroupValidateMachineGroup(virCgroupPtr group, tmp++; if (STRNEQ(tmp, name) && - STRNEQ(tmp, partname)) { - VIR_DEBUG("Name '%s' for controller '%s' does not match '%s' or '%s'", - tmp, virCgroupControllerTypeToString(i), name, partname); + STRNEQ(tmp, partname) && + STRNEQ(tmp, scopename)) { + VIR_DEBUG("Name '%s' for controller '%s' does not match '%s', '%s' or '%s'", + tmp, virCgroupControllerTypeToString(i), name, partname, scopename); goto cleanup; } } @@ -153,6 +166,7 @@ virCgroupValidateMachineGroup(virCgroupPtr group, cleanup: VIR_FREE(partname); + VIR_FREE(scopename); return valid; } #else @@ -1649,6 +1663,7 @@ int virCgroupNewDetect(pid_t pid ATTRIBUTE_UNUSED, int virCgroupNewDetectMachine(const char *name, const char *drivername, pid_t pid, + const char *partition, int controllers, virCgroupPtr *group) { @@ -1658,7 +1673,7 @@ int virCgroupNewDetectMachine(const char *name, return -1; } - if (!virCgroupValidateMachineGroup(*group, name, drivername, true)) { + if (!virCgroupValidateMachineGroup(*group, name, drivername, partition, true)) { VIR_DEBUG("Failed to validate machine name for '%s' driver '%s'", name, drivername); virCgroupFree(group); @@ -1668,22 +1683,124 @@ int virCgroupNewDetectMachine(const char *name, return 0; } -int virCgroupNewMachine(const char *name, - const char *drivername, - bool privileged ATTRIBUTE_UNUSED, - const unsigned char *uuid ATTRIBUTE_UNUSED, - const char *rootdir ATTRIBUTE_UNUSED, - pid_t pidleader ATTRIBUTE_UNUSED, - bool isContainer ATTRIBUTE_UNUSED, - const char *partition, - int controllers, - virCgroupPtr *group) +/* + * Returns 0 on success, -1 on fatal error, -2 on systemd not available + */ +static int +virCgroupNewMachineSystemd(const char *name, + const char *drivername, + bool privileged, + const unsigned char *uuid, + const char *rootdir, + pid_t pidleader, + bool isContainer, + const char *partition, + int controllers, + virCgroupPtr *group) { - virCgroupPtr parent = NULL; int ret = -1; + int rv; + virCgroupPtr init, parent = NULL; + char *path = NULL; + char *offset; + + VIR_DEBUG("Trying to setup machine '%s' via systemd", name); + if ((rv = virSystemdCreateMachine(name, + drivername, + privileged, + uuid, + rootdir, + pidleader, + isContainer, + partition)) < 0) + return rv; + + if (controllers != -1) + controllers |= (1 << VIR_CGROUP_CONTROLLER_SYSTEMD); + + VIR_DEBUG("Detecting systemd placement"); + if (virCgroupNewDetect(pidleader, + controllers, + &init) < 0) + return -1; - *group = NULL; + path = init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement; + init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement = NULL; + virCgroupFree(&init); + + if (!path || STREQ(path, "/") || path[0] != '/') { + VIR_DEBUG("Systemd didn't setup its controller"); + ret = -2; + goto cleanup; + } + + offset = path; + + if (virCgroupNew(pidleader, + "", + NULL, + controllers, + &parent) < 0) + goto cleanup; + + + for (;;) { + virCgroupPtr tmp; + char *t = strchr(offset + 1, '/'); + if (t) + *t = '\0'; + + if (virCgroupNew(pidleader, + path, + parent, + controllers, + &tmp) < 0) + goto cleanup; + + if (virCgroupMakeGroup(parent, tmp, true, VIR_CGROUP_NONE) < 0) { + virCgroupFree(&tmp); + goto cleanup; + } + if (t) { + *t = '/'; + offset = t; + virCgroupFree(&parent); + parent = tmp; + } else { + *group = tmp; + break; + } + } + + if (virCgroupAddTask(*group, pidleader) < 0) { + virErrorPtr saved = virSaveLastError(); + virCgroupRemove(*group); + virCgroupFree(group); + if (saved) { + virSetError(saved); + virFreeError(saved); + } + } + + ret = 0; + cleanup: + virCgroupFree(&parent); + VIR_FREE(path); + return ret; +} +static int +virCgroupNewMachineManual(const char *name, + const char *drivername, + pid_t pidleader, + const char *partition, + int controllers, + virCgroupPtr *group) +{ + virCgroupPtr parent = NULL; + int ret = -1; + + VIR_DEBUG("Fallback to non-systemd setup"); if (virCgroupNewPartition(partition, STREQ(partition, "/machine"), controllers, @@ -1719,6 +1836,44 @@ cleanup: return ret; } +int virCgroupNewMachine(const char *name, + const char *drivername, + bool privileged, + const unsigned char *uuid, + const char *rootdir, + pid_t pidleader, + bool isContainer, + const char *partition, + int controllers, + virCgroupPtr *group) +{ + int rv; + + *group = NULL; + + if ((rv = virCgroupNewMachineSystemd(name, + drivername, + privileged, + uuid, + rootdir, + pidleader, + isContainer, + partition, + controllers, + group)) == 0) + return 0; + + if (rv == -1) + return -1; + + return virCgroupNewMachineManual(name, + drivername, + pidleader, + partition, + controllers, + group); +} + bool virCgroupNewIgnoreError(void) { if (virLastErrorIsSystemErrno(ENXIO) || diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h index e579f41..d7ce892 100644 --- a/src/util/vircgroup.h +++ b/src/util/vircgroup.h @@ -83,6 +83,7 @@ int virCgroupNewDetect(pid_t pid, int virCgroupNewDetectMachine(const char *name, const char *drivername, pid_t pid, + const char *partition, int controllers, virCgroupPtr *group); -- 1.8.3.2