cgroup.c revision 0cd385d31814c8c1bc0c81d11ef321036b8b0921
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2013 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_init(CGroupContext *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Initialize everything to the kernel defaults, assuming the
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * structure is preinitialized to 0 */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->startup_cpu_shares = (unsigned long) -1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->startup_blockio_weight = (unsigned long) -1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->cpu_quota_per_sec_usec = USEC_INFINITY;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(device_allow, c->device_allow, a);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(device_weights, c->blockio_device_weights, w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(device_bandwidths, c->blockio_device_bandwidths, b);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_done(CGroupContext *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_free_device_allow(c, c->device_allow);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sCPUAccounting=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sBlockIOAccounting=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sMemoryAccounting=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sCPUShares=%lu\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sStartupCPUShares=%lu\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sCPUQuotaPerSecSec=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sBlockIOWeight=%lu\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sStartupBlockIOWeight=%lu\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sDevicePolicy=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sDelegate=%s\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, cgroup_device_policy_to_string(c->device_policy),
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_allow, a, c->device_allow)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sDeviceAllow=%s %s%s%s\n",
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_weights, w, c->blockio_device_weights)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sBlockIODeviceWeight=%s %lu",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%s%s=%s %s\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering b->read ? "BlockIOReadBandwidth" : "BlockIOWriteBandwidth",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering format_bytes(buf, sizeof(buf), b->bandwidth));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int lookup_blkio_device(const char *p, dev_t *dev) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return log_warning_errno(errno, "Couldn't stat device %s: %m", p);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If this is not a device node then find the block
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * device this file is stored on */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If this is a partition, try to get the originating
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * block device */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int whitelist_device(const char *path, const char *node, const char *acc) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Couldn't stat device %s", node);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("%s is not a device.", node);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%c %u:%u %s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int whitelist_major(const char *path, const char *name, char type, const char *acc) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return log_warning_errno(errno, "Cannot open /proc/devices to resolve %s (%c): %m", name, type);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char buf[2+DECIMAL_STR_MAX(unsigned)+3+4], *p, *w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (type == 'c' && streq(line, "Character devices:")) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (type == 'b' && streq(line, "Block devices:")) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", buf);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning_errno(errno, "Failed to read /proc/devices: %m");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const char *path, ManagerState state) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Some cgroup attributes are not support on the root cgroup,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * hence silently ignore */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering is_root = isempty(path) || path_equal(path, "/");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char buf[MAX(DECIMAL_STR_MAX(unsigned long), DECIMAL_STR_MAX(usec_t)) + 1];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != (unsigned long) -1 ? c->startup_cpu_shares :
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->cpu_shares != (unsigned long) -1 ? c->cpu_shares : 1024);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("cpu", path, "cpu.shares", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.shares on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_period_us on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->cpu_quota_per_sec_usec != USEC_INFINITY) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, USEC_FMT "\n", c->cpu_quota_per_sec_usec * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_quota_us on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char buf[MAX3(DECIMAL_STR_MAX(unsigned long)+1,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(unsigned long)*1,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, "%lu\n", IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != (unsigned long) -1 ? c->startup_blockio_weight :
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->blockio_weight != (unsigned long) -1 ? c->blockio_weight : 1000);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("blkio", path, "blkio.weight", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight on %s: %s", path, strerror(-r));
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek /* FIXME: no way to reset this list */
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek sprintf(buf, "%u:%u %lu", major(dev), minor(dev), w->weight);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("blkio", path, "blkio.weight_device", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight_device on %s: %s", path, strerror(-r));
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering /* FIXME: no way to reset this list */
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *a;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek r = lookup_blkio_device(b->path, &dev);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering a = b->read ? "blkio.throttle.read_bps_device" : "blkio.throttle.write_bps_device";
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("blkio", path, a, buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set %s on %s: %s", a, path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek if ((mask & CGROUP_DEVICE) && !is_root) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->device_allow || c->device_policy != CGROUP_AUTO)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("devices", path, "devices.deny", "a");
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek r = cg_set_attribute("devices", path, "devices.allow", "a");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to reset devices.list on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (c->device_policy == CGROUP_AUTO && c->device_allow)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering static const char auto_devices[] =
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "/dev/pts/ptmx\0" "rw\0"; /* /dev/pts/ptmx may not be duplicated, but accessed */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *x, *y;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering whitelist_major(path, "kdbus", 'c', "rw");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering whitelist_major(path, "kdbus/*", 'c', "rw");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_allow, a, c->device_allow) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned k = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering whitelist_major(path, a->path + 6, 'b', acc);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering whitelist_major(path, a->path + 5, 'c', acc);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug("Ignoring device %s while writing cgroup attribute.", a->path);
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringCGroupControllerMask cgroup_context_get_mask(CGroupContext *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Figure out which controllers we need */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->startup_cpu_shares != (unsigned long) -1 ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->cpu_quota_per_sec_usec != USEC_INFINITY)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->blockio_weight != (unsigned long) -1 ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->startup_blockio_weight != (unsigned long) -1 ||
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringCGroupControllerMask unit_get_cgroup_mask(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If delegation is turned on, then turn on all cgroups,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * unless the process we fork into it is known to drop
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * privileges anyway, and shouldn't get access to the
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * controllers anyway. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!e || exec_context_maintains_privileges(e))
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringCGroupControllerMask unit_get_members_mask(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SET_FOREACH(member, u->dependencies[UNIT_BEFORE], i) {
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringCGroupControllerMask unit_get_siblings_mask(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return unit_get_members_mask(UNIT_DEREF(u->slice));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return unit_get_cgroup_mask(u) | unit_get_members_mask(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringCGroupControllerMask unit_get_target_mask(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mask = unit_get_cgroup_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/* Recurse from a unit up through its containing slices, propagating
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * mask bits upward. A unit is also member of itself. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid unit_update_cgroup_members_masks(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Calculate subtree mask */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m = unit_get_cgroup_mask(u) | unit_get_members_mask(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* See if anything changed from the previous invocation. If
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * not, we're done. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->cgroup_subtree_mask_valid && m == u->cgroup_subtree_mask)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek u->cgroup_subtree_mask_valid &&
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek ((m & ~u->cgroup_subtree_mask) != 0) &&
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek ((~m & u->cgroup_subtree_mask) == 0);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek u->cgroup_subtree_mask_valid = true;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek Unit *s = UNIT_DEREF(u->slice);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* There's more set now than before. We
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek * propagate the new mask to the parent's mask
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek * (not caring if it actually was valid or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* There's less set now than before (or we
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * don't know), we need to recalculate
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * everything, so let's invalidate the
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * parent's members mask */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* And now make sure that this change also hits our
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * grandparents */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic const char *migrate_callback(CGroupControllerMask mask, void *userdata) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (u->cgroup_realized_mask & mask) == mask)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmekstatic int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek _cleanup_free_ char *path = NULL;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek c = unit_get_cgroup_context(u);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek path = unit_default_cgroup_path(u);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = hashmap_put(u->manager->cgroup_unit, path, u);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_error(r == -EEXIST ? "cgroup %s exists already: %s" : "hashmap_put failed for %s: %s", path, strerror(-r));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* First, create our own group */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = cg_create_everywhere(u->manager->cgroup_supported, mask, u->cgroup_path);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to create cgroup %s: %m", u->cgroup_path);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* Keep track that this is now realized */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek u->cgroup_realized_mask = mask;
r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->cgroup_path, migrate_callback, u);
assert(u);
assert(u);
if (u->in_cgroup_queue) {
u->in_cgroup_queue = false;
if (u->in_cgroup_queue)
u->in_cgroup_queue = true;
Unit *i;
while ((i = m->cgroup_queue)) {
Iterator i;
Unit *m;
u = slice;
CGroupContext *c;
assert(u);
c = unit_get_cgroup_context(u);
assert(u);
if (!u->cgroup_path)
r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE));
u->cgroup_realized = false;
u->cgroup_realized_mask = 0;
assert(u);
if (!u->cgroup_path)
if (pid != 0) {
pid = 0;
return pid;
assert(m);
/* LEGACY: Already in /system.slice? If so, let's cut this
m->cgroup_root[0] = 0;
log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
if (!m->test_run) {
if (m->pin_cgroupfs_fd < 0)
assert(m);
Unit *u;
assert(m);
return NULL;
assert(m);
return NULL;
return NULL;
Unit *u;
assert(m);