cgroup.c revision d81afec1c9bf4b73e3df8996d65ecae95d19b6db
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering This file is part of systemd.
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering Copyright 2013 Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering systemd is free software; you can redistribute it and/or modify it
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering under the terms of the GNU Lesser General Public License as published by
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering (at your option) any later version.
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering systemd is distributed in the hope that it will be useful, but
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering Lesser General Public License for more details.
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering You should have received a copy of the GNU Lesser General Public License
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
a09561746f15b84da9471b5c4be74e53d19e4f3fLennart Poetteringvoid cgroup_context_init(CGroupContext *c) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Initialize everything to the kernel defaults, assuming the
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * structure is preinitialized to 0 */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek c->cpu_shares = (unsigned long) -1;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering c->startup_cpu_shares = (unsigned long) -1;
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen c->blockio_weight = (unsigned long) -1;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering c->startup_blockio_weight = (unsigned long) -1;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering c->cpu_quota_per_sec_usec = USEC_INFINITY;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_REMOVE(device_allow, c->device_allow, a);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_REMOVE(device_weights, c->blockio_device_weights, w);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_REMOVE(device_bandwidths, c->blockio_device_bandwidths, b);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_done(CGroupContext *c) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
13790add4bf648fed816361794d8277a75253410Lennart Poettering cgroup_context_free_device_allow(c, c->device_allow);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sCPUAccounting=%s\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sBlockIOAccounting=%s\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sMemoryAccounting=%s\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sCPUShares=%lu\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sStartupCPUShares=%lu\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sCPUQuotaPerSecSec=%s\n"
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek "%sBlockIOWeight=%lu\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sStartupBlockIOWeight=%lu\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sDevicePolicy=%s\n",
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, strna(format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1)),
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, cgroup_device_policy_to_string(c->device_policy));
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_FOREACH(device_allow, a, c->device_allow)
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sDeviceAllow=%s %s%s%s\n",
13790add4bf648fed816361794d8277a75253410Lennart Poettering a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_FOREACH(device_weights, w, c->blockio_device_weights)
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sBlockIODeviceWeight=%s %lu",
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%s%s=%s %s\n",
13790add4bf648fed816361794d8277a75253410Lennart Poettering b->read ? "BlockIOReadBandwidth" : "BlockIOWriteBandwidth",
13790add4bf648fed816361794d8277a75253410Lennart Poettering format_bytes(buf, sizeof(buf), b->bandwidth));
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic int lookup_blkio_device(const char *p, dev_t *dev) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_warning("Couldn't stat device %s: %m", p);
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* If this is not a device node then find the block
13790add4bf648fed816361794d8277a75253410Lennart Poettering * device this file is stored on */
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* If this is a partition, try to get the originating
13790add4bf648fed816361794d8277a75253410Lennart Poettering * block device */
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic int whitelist_device(const char *path, const char *node, const char *acc) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_warning("Couldn't stat device %s", node);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_warning("%s is not a device.", node);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering "%c %u:%u %s",
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", buf);
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r));
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poetteringstatic int whitelist_major(const char *path, const char *name, char type, const char *acc) {
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek log_warning("Cannot open /proc/devices to resolve %s (%c): %m", name, type);
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek FOREACH_LINE(line, f, goto fail) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering char buf[2+DECIMAL_STR_MAX(unsigned)+3+4], *p, *w;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (type == 'c' && streq(line, "Character devices:")) {
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek if (type == 'b' && streq(line, "Block devices:")) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", buf);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_warning("Failed to read /proc/devices: %m");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const char *path, ManagerState state) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* Some cgroup attributes are not support on the root cgroup,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering * hence silently ignore */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering is_root = isempty(path) || path_equal(path, "/");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering char buf[MAX(DECIMAL_STR_MAX(unsigned long), DECIMAL_STR_MAX(usec_t)) + 1];
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != (unsigned long) -1 ? c->startup_cpu_shares :
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->cpu_shares != (unsigned long) -1 ? c->cpu_shares : 1024);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("cpu", path, "cpu.shares", buf);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.shares on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf);
41891700e02daf0cab9e86908c76ac6f411bbd57Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_period_us on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (c->cpu_quota_per_sec_usec != USEC_INFINITY) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering sprintf(buf, USEC_FMT "\n", c->cpu_quota_per_sec_usec * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", buf);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_quota_us on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering char buf[MAX3(DECIMAL_STR_MAX(unsigned long)+1,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(unsigned long)*1,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering sprintf(buf, "%lu\n", IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != (unsigned long) -1 ? c->startup_blockio_weight :
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->blockio_weight != (unsigned long) -1 ? c->blockio_weight : 1000);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("blkio", path, "blkio.weight", buf);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* FIXME: no way to reset this list */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering sprintf(buf, "%u:%u %lu", major(dev), minor(dev), w->weight);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("blkio", path, "blkio.weight_device", buf);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight_device on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* FIXME: no way to reset this list */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering const char *a;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering a = b->read ? "blkio.throttle.read_bps_device" : "blkio.throttle.write_bps_device";
13790add4bf648fed816361794d8277a75253410Lennart Poettering sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth);
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = cg_set_attribute("blkio", path, a, buf);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set %s on %s: %s", a, path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if ((mask & CGROUP_DEVICE) && !is_root) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (c->device_allow || c->device_policy != CGROUP_AUTO)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("devices", path, "devices.deny", "a");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", "a");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to reset devices.list on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering (c->device_policy == CGROUP_AUTO && c->device_allow)) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering static const char auto_devices[] =
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "/dev/pts/ptmx\0" "rw\0"; /* /dev/pts/ptmx may not be duplicated, but accessed */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering const char *x, *y;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering whitelist_major(path, "kdbus", 'c', "rw");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering whitelist_major(path, "kdbus/*", 'c', "rw");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_FOREACH(device_allow, a, c->device_allow) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering unsigned k = 0;
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering whitelist_major(path, a->path + 6, 'b', acc);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering whitelist_major(path, a->path + 5, 'c', acc);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_debug("Ignoring device %s while writing cgroup attribute.", a->path);
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal SchmidtCGroupControllerMask cgroup_context_get_mask(CGroupContext *c) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* Figure out which controllers we need */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->startup_cpu_shares != (unsigned long) -1 ||
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->cpu_quota_per_sec_usec != USEC_INFINITY)
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering c->blockio_weight != (unsigned long) -1 ||
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->startup_blockio_weight != (unsigned long) -1 ||
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (c->device_allow || c->device_policy != CGROUP_AUTO)
13790add4bf648fed816361794d8277a75253410Lennart PoetteringCGroupControllerMask unit_get_cgroup_mask(Unit *u) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart PoetteringCGroupControllerMask unit_get_members_mask(Unit *u) {
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek if (u->cgroup_members_mask_valid)
13790add4bf648fed816361794d8277a75253410Lennart Poettering SET_FOREACH(member, u->dependencies[UNIT_BEFORE], i) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart PoetteringCGroupControllerMask unit_get_siblings_mask(Unit *u) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering return unit_get_members_mask(UNIT_DEREF(u->slice));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return unit_get_cgroup_mask(u) | unit_get_members_mask(u);
f9a810bedacf1da7c505c1786a2416d592665926Lennart PoetteringCGroupControllerMask unit_get_target_mask(Unit *u) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering mask = unit_get_cgroup_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt/* Recurse from a unit up through its containing slices, propagating
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering * mask bits upward. A unit is also member of itself. */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid unit_update_cgroup_members_masks(Unit *u) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* Calculate subtree mask */
13790add4bf648fed816361794d8277a75253410Lennart Poettering m = unit_get_cgroup_mask(u) | unit_get_members_mask(u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* See if anything changed from the previous invocation. If
13790add4bf648fed816361794d8277a75253410Lennart Poettering * not, we're done. */
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (u->cgroup_subtree_mask_valid && m == u->cgroup_subtree_mask)
13790add4bf648fed816361794d8277a75253410Lennart Poettering ((m & ~u->cgroup_subtree_mask) != 0) &&
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* There's more set now than before. We
13790add4bf648fed816361794d8277a75253410Lennart Poettering * propagate the new mask to the parent's mask
13790add4bf648fed816361794d8277a75253410Lennart Poettering * (not caring if it actually was valid or
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* There's less set now than before (or we
13790add4bf648fed816361794d8277a75253410Lennart Poettering * don't know), we need to recalculate
13790add4bf648fed816361794d8277a75253410Lennart Poettering * everything, so let's invalidate the
13790add4bf648fed816361794d8277a75253410Lennart Poettering * parent's members mask */
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* And now make sure that this change also hits our
13790add4bf648fed816361794d8277a75253410Lennart Poettering * grandparents */
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic const char *migrate_callback(CGroupControllerMask mask, void *userdata) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering (u->cgroup_realized_mask & mask) == mask)
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = hashmap_put(u->manager->cgroup_unit, path, u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_error(r == -EEXIST ? "cgroup %s exists already: %s" : "hashmap_put failed for %s: %s", path, strerror(-r));
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* First, create our own group */
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = cg_create_everywhere(u->manager->cgroup_supported, mask, u->cgroup_path);
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_error("Failed to create cgroup %s: %s", u->cgroup_path, strerror(-r));
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Keep track that this is now realized */
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Then, possibly move things over */
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->cgroup_path, migrate_callback, u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_warning("Failed to migrate cgroup from to %s: %s", u->cgroup_path, strerror(-r));
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic bool unit_has_mask_realized(Unit *u, CGroupControllerMask mask) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering return u->cgroup_realized && u->cgroup_realized_mask == mask;
13790add4bf648fed816361794d8277a75253410Lennart Poettering/* Check if necessary controllers and attributes for a unit are in place.
13790add4bf648fed816361794d8277a75253410Lennart Poettering * If so, do nothing.
13790add4bf648fed816361794d8277a75253410Lennart Poettering * If not, create paths, move processes over, and set attributes.
13790add4bf648fed816361794d8277a75253410Lennart Poettering * Returns 0 on success and < 0 on failure. */
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic int unit_realize_cgroup_now(Unit *u, ManagerState state) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* First, realize parents */
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = unit_realize_cgroup_now(UNIT_DEREF(u->slice), state);
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* And then do the real work */
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Finally, apply the necessary attributes. */
13790add4bf648fed816361794d8277a75253410Lennart Poettering cgroup_context_apply(unit_get_cgroup_context(u), mask, u->cgroup_path, state);
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic void unit_add_to_cgroup_queue(Unit *u) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_PREPEND(cgroup_queue, u->manager->cgroup_queue, u);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringunsigned manager_dispatch_cgroup_queue(Manager *m) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering unsigned n = 0;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek while ((i = m->cgroup_queue)) {
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt log_warning("Failed to realize cgroups for queued unit %s: %s", i->id, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringstatic void unit_queue_siblings(Unit *u) {
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt /* This adds the siblings of the specified unit and the
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt * siblings of all parent units to the cgroup queue. (But
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering * neither the specified unit itself nor the parents.) */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering SET_FOREACH(m, slice->dependencies[UNIT_BEFORE], i) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* Skip units that have a dependency on the slice
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering * but aren't actually in it. */
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) {
return -errno;
assert(m);
Unit *u;
assert(m);
return NULL;
assert(m);
return NULL;
return NULL;
Unit *u;
assert(m);