cgroup.c revision d81afec1c9bf4b73e3df8996d65ecae95d19b6db
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering/***
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering This file is part of systemd.
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering Copyright 2013 Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart 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
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
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/>.
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering***/
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell#include <fcntl.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <fnmatch.h>
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering#include "path-util.h"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering#include "special.h"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering#include "cgroup-util.h"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering#include "cgroup.h"
13790add4bf648fed816361794d8277a75253410Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
a09561746f15b84da9471b5c4be74e53d19e4f3fLennart Poetteringvoid cgroup_context_init(CGroupContext *c) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering assert(c);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Initialize everything to the kernel defaults, assuming the
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * structure is preinitialized to 0 */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek c->cpu_shares = (unsigned long) -1;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering c->startup_cpu_shares = (unsigned long) -1;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->memory_limit = (uint64_t) -1;
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen c->blockio_weight = (unsigned long) -1;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering c->startup_blockio_weight = (unsigned long) -1;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering c->cpu_quota_per_sec_usec = USEC_INFINITY;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering}
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(c);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(a);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_REMOVE(device_allow, c->device_allow, a);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(a->path);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(a);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(c);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(w);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_REMOVE(device_weights, c->blockio_device_weights, w);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(w->path);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(w);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(c);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(b);
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_REMOVE(device_bandwidths, c->blockio_device_bandwidths, b);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(b->path);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering free(b);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_done(CGroupContext *c) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(c);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering while (c->blockio_device_weights)
13790add4bf648fed816361794d8277a75253410Lennart Poettering cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering while (c->blockio_device_bandwidths)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering while (c->device_allow)
13790add4bf648fed816361794d8277a75253410Lennart Poettering cgroup_context_free_device_allow(c, c->device_allow);
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering CGroupBlockIODeviceBandwidth *b;
13790add4bf648fed816361794d8277a75253410Lennart Poettering CGroupBlockIODeviceWeight *w;
13790add4bf648fed816361794d8277a75253410Lennart Poettering CGroupDeviceAllow *a;
13790add4bf648fed816361794d8277a75253410Lennart Poettering char u[FORMAT_TIMESPAN_MAX];
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(c);
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(f);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix = strempty(prefix);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f,
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 "%sMemoryLimit=%" PRIu64 "\n"
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sDevicePolicy=%s\n",
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, yes_no(c->cpu_accounting),
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, yes_no(c->blockio_accounting),
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, yes_no(c->memory_accounting),
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, c->cpu_shares,
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, c->startup_cpu_shares,
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, strna(format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1)),
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, c->blockio_weight,
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, c->startup_blockio_weight,
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, c->memory_limit,
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix, cgroup_device_policy_to_string(c->device_policy));
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_FOREACH(device_allow, a, c->device_allow)
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f,
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sDeviceAllow=%s %s%s%s\n",
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix,
13790add4bf648fed816361794d8277a75253410Lennart Poettering a->path,
13790add4bf648fed816361794d8277a75253410Lennart Poettering a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_FOREACH(device_weights, w, c->blockio_device_weights)
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f,
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%sBlockIODeviceWeight=%s %lu",
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix,
13790add4bf648fed816361794d8277a75253410Lennart Poettering w->path,
13790add4bf648fed816361794d8277a75253410Lennart Poettering w->weight);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering char buf[FORMAT_BYTES_MAX];
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering fprintf(f,
13790add4bf648fed816361794d8277a75253410Lennart Poettering "%s%s=%s %s\n",
13790add4bf648fed816361794d8277a75253410Lennart Poettering prefix,
13790add4bf648fed816361794d8277a75253410Lennart Poettering b->read ? "BlockIOReadBandwidth" : "BlockIOWriteBandwidth",
13790add4bf648fed816361794d8277a75253410Lennart Poettering b->path,
13790add4bf648fed816361794d8277a75253410Lennart Poettering format_bytes(buf, sizeof(buf), b->bandwidth));
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic int lookup_blkio_device(const char *p, dev_t *dev) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering struct stat st;
13790add4bf648fed816361794d8277a75253410Lennart Poettering int r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(p);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering assert(dev);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = stat(p, &st);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (r < 0) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_warning("Couldn't stat device %s: %m", p);
13790add4bf648fed816361794d8277a75253410Lennart Poettering return -errno;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (S_ISBLK(st.st_mode))
13790add4bf648fed816361794d8277a75253410Lennart Poettering *dev = st.st_rdev;
13790add4bf648fed816361794d8277a75253410Lennart Poettering else if (major(st.st_dev) != 0) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* If this is not a device node then find the block
13790add4bf648fed816361794d8277a75253410Lennart Poettering * device this file is stored on */
13790add4bf648fed816361794d8277a75253410Lennart Poettering *dev = st.st_dev;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* If this is a partition, try to get the originating
13790add4bf648fed816361794d8277a75253410Lennart Poettering * block device */
13790add4bf648fed816361794d8277a75253410Lennart Poettering block_get_whole_disk(*dev, dev);
13790add4bf648fed816361794d8277a75253410Lennart Poettering } else {
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
13790add4bf648fed816361794d8277a75253410Lennart Poettering return -ENODEV;
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
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 struct stat st;
13790add4bf648fed816361794d8277a75253410Lennart Poettering int r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(path);
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(acc);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (stat(node, &st) < 0) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_warning("Couldn't stat device %s", node);
13790add4bf648fed816361794d8277a75253410Lennart Poettering return -errno;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
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 return -ENODEV;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering sprintf(buf,
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering "%c %u:%u %s",
13790add4bf648fed816361794d8277a75253410Lennart Poettering S_ISCHR(st.st_mode) ? 'c' : 'b',
13790add4bf648fed816361794d8277a75253410Lennart Poettering major(st.st_rdev), minor(st.st_rdev),
13790add4bf648fed816361794d8277a75253410Lennart Poettering acc);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", buf);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (r < 0)
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r));
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return r;
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poetteringstatic int whitelist_major(const char *path, const char *name, char type, const char *acc) {
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering char line[LINE_MAX];
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering bool good = false;
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering int r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering assert(path);
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(acc);
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(type == 'b' || type == 'c');
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering f = fopen("/proc/devices", "re");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!f) {
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek log_warning("Cannot open /proc/devices to resolve %s (%c): %m", name, type);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek return -errno;
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek }
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek
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 unsigned maj;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering truncate_nl(line);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (type == 'c' && streq(line, "Character devices:")) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering good = true;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering continue;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek if (type == 'b' && streq(line, "Block devices:")) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering good = true;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering continue;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (isempty(line)) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering good = false;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering continue;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!good)
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen continue;
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen p = strstrip(line);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering w = strpbrk(p, WHITESPACE);
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek if (!w)
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek continue;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering *w = 0;
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek r = safe_atou(p, &maj);
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek if (r < 0)
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek continue;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (maj <= 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering continue;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering w++;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering w += strspn(w, WHITESPACE);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (fnmatch(name, w, 0) != 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering continue;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering sprintf(buf,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "%c %u:* %s",
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek type,
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek maj,
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering acc);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", buf);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringfail:
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_warning("Failed to read /proc/devices: %m");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return -errno;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringvoid cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const char *path, ManagerState state) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering bool is_root;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering int r;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(c);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(path);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (mask == 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
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
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if ((mask & CGROUP_CPU) && !is_root) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering char buf[MAX(DECIMAL_STR_MAX(unsigned long), DECIMAL_STR_MAX(usec_t)) + 1];
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering sprintf(buf, "%lu\n",
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 if (r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.shares on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
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);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
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
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 } else
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
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 }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (mask & CGROUP_BLKIO) {
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 CGroupBlockIODeviceWeight *w;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering CGroupBlockIODeviceBandwidth *b;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (!is_root) {
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 if (r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* FIXME: no way to reset this list */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering dev_t dev;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = lookup_blkio_device(w->path, &dev);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering continue;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
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 if (r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight_device on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
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 dev_t dev;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = lookup_blkio_device(b->path, &dev);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering continue;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering a = b->read ? "blkio.throttle.read_bps_device" : "blkio.throttle.write_bps_device";
13790add4bf648fed816361794d8277a75253410Lennart Poettering
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 if (r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set %s on %s: %s", a, path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (mask & CGROUP_MEMORY) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (c->memory_limit != (uint64_t) -1) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering char buf[DECIMAL_STR_MAX(uint64_t) + 1];
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering } else
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
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 }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if ((mask & CGROUP_DEVICE) && !is_root) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering CGroupDeviceAllow *a;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (c->device_allow || c->device_policy != CGROUP_AUTO)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("devices", path, "devices.deny", "a");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering else
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", "a");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to reset devices.list on %s: %s", path, strerror(-r));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (c->device_policy == CGROUP_CLOSED ||
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering (c->device_policy == CGROUP_AUTO && c->device_allow)) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering static const char auto_devices[] =
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "/dev/null\0" "rwm\0"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "/dev/zero\0" "rwm\0"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "/dev/full\0" "rwm\0"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "/dev/random\0" "rwm\0"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "/dev/urandom\0" "rwm\0"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "/dev/tty\0" "rwm\0"
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering "/dev/pts/ptmx\0" "rw\0"; /* /dev/pts/ptmx may not be duplicated, but accessed */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering const char *x, *y;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering NULSTR_FOREACH_PAIR(x, y, auto_devices)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering whitelist_device(path, x, y);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering whitelist_major(path, "pts", 'c', "rw");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering whitelist_major(path, "kdbus", 'c', "rw");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering whitelist_major(path, "kdbus/*", 'c', "rw");
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering LIST_FOREACH(device_allow, a, c->device_allow) {
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering char acc[4];
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering unsigned k = 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (a->r)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering acc[k++] = 'r';
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (a->w)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering acc[k++] = 'w';
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (a->m)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering acc[k++] = 'm';
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (k == 0)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering continue;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering acc[k++] = 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (startswith(a->path, "/dev/"))
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering whitelist_device(path, a->path, acc);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering else if (startswith(a->path, "block-"))
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering whitelist_major(path, a->path + 6, 'b', acc);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering else if (startswith(a->path, "char-"))
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering whitelist_major(path, a->path + 5, 'c', acc);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering else
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering log_debug("Ignoring device %s while writing cgroup attribute.", a->path);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal SchmidtCGroupControllerMask cgroup_context_get_mask(CGroupContext *c) {
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering CGroupControllerMask mask = 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* Figure out which controllers we need */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering if (c->cpu_accounting ||
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering c->cpu_shares != (unsigned long) -1 ||
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->startup_cpu_shares != (unsigned long) -1 ||
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->cpu_quota_per_sec_usec != USEC_INFINITY)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering mask |= CGROUP_CPUACCT | CGROUP_CPU;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (c->blockio_accounting ||
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering c->blockio_weight != (unsigned long) -1 ||
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->startup_blockio_weight != (unsigned long) -1 ||
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->blockio_device_weights ||
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->blockio_device_bandwidths)
91bf3b3e124575f6f647bff29766e9d992f55b32Lennart Poettering mask |= CGROUP_BLKIO;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (c->memory_accounting ||
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c->memory_limit != (uint64_t) -1)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering mask |= CGROUP_MEMORY;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (c->device_allow || c->device_policy != CGROUP_AUTO)
13790add4bf648fed816361794d8277a75253410Lennart Poettering mask |= CGROUP_DEVICE;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return mask;
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart PoetteringCGroupControllerMask unit_get_cgroup_mask(Unit *u) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering CGroupContext *c;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering c = unit_get_cgroup_context(u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!c)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return cgroup_context_get_mask(c);
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart PoetteringCGroupControllerMask unit_get_members_mask(Unit *u) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(u);
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek if (u->cgroup_members_mask_valid)
2de56f70941eaf91a4520bf33de47a87ebd8b2cbZbigniew Jędrzejewski-Szmek return u->cgroup_members_mask;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering u->cgroup_members_mask = 0;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (u->type == UNIT_SLICE) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering Unit *member;
13790add4bf648fed816361794d8277a75253410Lennart Poettering Iterator i;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering SET_FOREACH(member, u->dependencies[UNIT_BEFORE], i) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (member == u)
13790add4bf648fed816361794d8277a75253410Lennart Poettering continue;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (UNIT_DEREF(member->slice) != u)
13790add4bf648fed816361794d8277a75253410Lennart Poettering continue;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->cgroup_members_mask |=
13790add4bf648fed816361794d8277a75253410Lennart Poettering unit_get_cgroup_mask(member) |
13790add4bf648fed816361794d8277a75253410Lennart Poettering unit_get_members_mask(member);
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->cgroup_members_mask_valid = true;
13790add4bf648fed816361794d8277a75253410Lennart Poettering return u->cgroup_members_mask;
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart PoetteringCGroupControllerMask unit_get_siblings_mask(Unit *u) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering assert(u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (UNIT_ISSET(u->slice))
13790add4bf648fed816361794d8277a75253410Lennart Poettering return unit_get_members_mask(UNIT_DEREF(u->slice));
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return unit_get_cgroup_mask(u) | unit_get_members_mask(u);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart PoetteringCGroupControllerMask unit_get_target_mask(Unit *u) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering CGroupControllerMask mask;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering mask = unit_get_cgroup_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering mask &= u->manager->cgroup_supported;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return mask;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
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 CGroupControllerMask m;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering bool more;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(u);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* Calculate subtree mask */
13790add4bf648fed816361794d8277a75253410Lennart Poettering m = unit_get_cgroup_mask(u) | unit_get_members_mask(u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
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 return;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering more =
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->cgroup_subtree_mask_valid &&
13790add4bf648fed816361794d8277a75253410Lennart Poettering ((m & ~u->cgroup_subtree_mask) != 0) &&
13790add4bf648fed816361794d8277a75253410Lennart Poettering ((~m & u->cgroup_subtree_mask) == 0);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->cgroup_subtree_mask = m;
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->cgroup_subtree_mask_valid = true;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (UNIT_ISSET(u->slice)) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering Unit *s = UNIT_DEREF(u->slice);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (more)
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 * not). */
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering s->cgroup_members_mask |= m;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering else
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
13790add4bf648fed816361794d8277a75253410Lennart Poettering s->cgroup_members_mask_valid = false;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* And now make sure that this change also hits our
13790add4bf648fed816361794d8277a75253410Lennart Poettering * grandparents */
13790add4bf648fed816361794d8277a75253410Lennart Poettering unit_update_cgroup_members_masks(s);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic const char *migrate_callback(CGroupControllerMask mask, void *userdata) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering Unit *u = userdata;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(mask != 0);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering assert(u);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering while (u) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (u->cgroup_path &&
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->cgroup_realized &&
13790add4bf648fed816361794d8277a75253410Lennart Poettering (u->cgroup_realized_mask & mask) == mask)
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering return u->cgroup_path;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering u = UNIT_DEREF(u->slice);
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return NULL;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering _cleanup_free_ char *path = NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering int r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering assert(u);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering path = unit_default_cgroup_path(u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!path)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return log_oom();
13790add4bf648fed816361794d8277a75253410Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = hashmap_put(u->manager->cgroup_unit, path, u);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_error(r == -EEXIST ? "cgroup %s exists already: %s" : "hashmap_put failed for %s: %s", path, strerror(-r));
13790add4bf648fed816361794d8277a75253410Lennart Poettering return r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (r > 0) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->cgroup_path = path;
13790add4bf648fed816361794d8277a75253410Lennart Poettering path = NULL;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* First, create our own group */
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = cg_create_everywhere(u->manager->cgroup_supported, mask, u->cgroup_path);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (r < 0) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_error("Failed to create cgroup %s: %s", u->cgroup_path, strerror(-r));
13790add4bf648fed816361794d8277a75253410Lennart Poettering return r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Keep track that this is now realized */
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->cgroup_realized = true;
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->cgroup_realized_mask = mask;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
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 if (r < 0)
13790add4bf648fed816361794d8277a75253410Lennart Poettering log_warning("Failed to migrate cgroup from to %s: %s", u->cgroup_path, strerror(-r));
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic bool unit_has_mask_realized(Unit *u, CGroupControllerMask mask) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(u);
15d91bff36c61d38df8edff258d1702a017a0e66Zbigniew Jędrzejewski-Szmek
13790add4bf648fed816361794d8277a75253410Lennart Poettering return u->cgroup_realized && u->cgroup_realized_mask == mask;
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering/* Check if necessary controllers and attributes for a unit are in place.
13790add4bf648fed816361794d8277a75253410Lennart Poettering *
13790add4bf648fed816361794d8277a75253410Lennart Poettering * If so, do nothing.
13790add4bf648fed816361794d8277a75253410Lennart Poettering * If not, create paths, move processes over, and set attributes.
13790add4bf648fed816361794d8277a75253410Lennart Poettering *
13790add4bf648fed816361794d8277a75253410Lennart Poettering * Returns 0 on success and < 0 on failure. */
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic int unit_realize_cgroup_now(Unit *u, ManagerState state) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering CGroupControllerMask mask;
13790add4bf648fed816361794d8277a75253410Lennart Poettering int r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering assert(u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (u->in_cgroup_queue) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->in_cgroup_queue = false;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering mask = unit_get_target_mask(u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (unit_has_mask_realized(u, mask))
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* First, realize parents */
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (UNIT_ISSET(u->slice)) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = unit_realize_cgroup_now(UNIT_DEREF(u->slice), state);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (r < 0)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering }
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* And then do the real work */
13790add4bf648fed816361794d8277a75253410Lennart Poettering r = unit_create_cgroups(u, mask);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (r < 0)
13790add4bf648fed816361794d8277a75253410Lennart Poettering return r;
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Finally, apply the necessary attributes. */
13790add4bf648fed816361794d8277a75253410Lennart Poettering cgroup_context_apply(unit_get_cgroup_context(u), mask, u->cgroup_path, state);
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering return 0;
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poetteringstatic void unit_add_to_cgroup_queue(Unit *u) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (u->in_cgroup_queue)
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return;
7b77ed8cf36e8eca6017791626044b61ae2d68e7Lennart Poettering
13790add4bf648fed816361794d8277a75253410Lennart Poettering LIST_PREPEND(cgroup_queue, u->manager->cgroup_queue, u);
13790add4bf648fed816361794d8277a75253410Lennart Poettering u->in_cgroup_queue = true;
13790add4bf648fed816361794d8277a75253410Lennart Poettering}
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringunsigned manager_dispatch_cgroup_queue(Manager *m) {
15d91bff36c61d38df8edff258d1702a017a0e66Zbigniew Jędrzejewski-Szmek ManagerState state;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering unsigned n = 0;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering Unit *i;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering int r;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering state = manager_state(m);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek while ((i = m->cgroup_queue)) {
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek assert(i->in_cgroup_queue);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering r = unit_realize_cgroup_now(i, state);
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (r < 0)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt log_warning("Failed to realize cgroups for queued unit %s: %s", i->id, strerror(-r));
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering n++;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering }
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering return n;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt}
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poetteringstatic void unit_queue_siblings(Unit *u) {
4a61c3e51e96a747c30598d78ee3a24e7c569e9fZbigniew Jędrzejewski-Szmek Unit *slice;
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
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.) */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering while ((slice = UNIT_DEREF(u->slice))) {
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering Iterator i;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt Unit *m;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering SET_FOREACH(m, slice->dependencies[UNIT_BEFORE], i) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (m == u)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt continue;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering /* Skip units that have a dependency on the slice
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering * but aren't actually in it. */
a45b9fca6b91a767dcd9060cfcb30617dad234c7Lennart Poettering if (UNIT_DEREF(m->slice) != slice)
continue;
/* No point in doing cgroup application for units
* without active processes. */
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m)))
continue;
/* If the unit doesn't need any new controllers
* and has current ones realized, it doesn't need
* any changes. */
if (unit_has_mask_realized(m, unit_get_target_mask(m)))
continue;
unit_add_to_cgroup_queue(m);
}
u = slice;
}
}
int unit_realize_cgroup(Unit *u) {
CGroupContext *c;
assert(u);
c = unit_get_cgroup_context(u);
if (!c)
return 0;
/* So, here's the deal: when realizing the cgroups for this
* unit, we need to first create all parents, but there's more
* actually: for the weight-based controllers we also need to
* make sure that all our siblings (i.e. units that are in the
* same slice as we are) have cgroups, too. Otherwise, things
* would become very uneven as each of their processes would
* get as much resources as all our group together. This call
* will synchronously create the parent cgroups, but will
* defer work on the siblings to the next event loop
* iteration. */
/* Add all sibling slices to the cgroup queue. */
unit_queue_siblings(u);
/* And realize this one now (and apply the values) */
return unit_realize_cgroup_now(u, manager_state(u->manager));
}
void unit_destroy_cgroup(Unit *u) {
int r;
assert(u);
if (!u->cgroup_path)
return;
r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE));
if (r < 0)
log_debug("Failed to destroy cgroup %s: %s", u->cgroup_path, strerror(-r));
hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
free(u->cgroup_path);
u->cgroup_path = NULL;
u->cgroup_realized = false;
u->cgroup_realized_mask = 0;
}
pid_t unit_search_main_pid(Unit *u) {
_cleanup_fclose_ FILE *f = NULL;
pid_t pid = 0, npid, mypid;
assert(u);
if (!u->cgroup_path)
return 0;
if (cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f) < 0)
return 0;
mypid = getpid();
while (cg_read_pid(f, &npid) > 0) {
pid_t ppid;
if (npid == pid)
continue;
/* Ignore processes that aren't our kids */
if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid)
continue;
if (pid != 0) {
/* Dang, there's more than one daemonized PID
in this group, so we don't know what process
is the main process. */
pid = 0;
break;
}
pid = npid;
}
return pid;
}
int manager_setup_cgroup(Manager *m) {
_cleanup_free_ char *path = NULL;
int r;
assert(m);
/* 1. Determine hierarchy */
free(m->cgroup_root);
m->cgroup_root = NULL;
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root);
if (r < 0) {
log_error("Cannot determine cgroup we are running in: %s", strerror(-r));
return r;
}
/* LEGACY: Already in /system.slice? If so, let's cut this
* off. This is to support live upgrades from older systemd
* versions where PID 1 was moved there. */
if (m->running_as == SYSTEMD_SYSTEM) {
char *e;
e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
if (!e)
e = endswith(m->cgroup_root, "/system");
if (e)
*e = 0;
}
/* And make sure to store away the root value without trailing
* slash, even for the root dir, so that we can easily prepend
* it everywhere. */
if (streq(m->cgroup_root, "/"))
m->cgroup_root[0] = 0;
/* 2. Show data */
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path);
if (r < 0) {
log_error("Cannot find cgroup mount point: %s", strerror(-r));
return r;
}
log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
if (!m->test_run) {
/* 3. Install agent */
if (m->running_as == SYSTEMD_SYSTEM) {
r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
if (r < 0)
log_warning("Failed to install release agent, ignoring: %s", strerror(-r));
else if (r > 0)
log_debug("Installed release agent.");
else
log_debug("Release agent already installed.");
}
/* 4. Make sure we are in the root cgroup */
r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, 0);
if (r < 0) {
log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
return r;
}
/* 5. And pin it, so that it cannot be unmounted */
safe_close(m->pin_cgroupfs_fd);
m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
if (m->pin_cgroupfs_fd < 0) {
log_error("Failed to open pin file: %m");
return -errno;
}
/* 6. Always enable hierarchial support if it exists... */
cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
}
/* 7. Figure out which controllers are supported */
m->cgroup_supported = cg_mask_supported();
return 0;
}
void manager_shutdown_cgroup(Manager *m, bool delete) {
assert(m);
/* We can't really delete the group, since we are in it. But
* let's trim it. */
if (delete && m->cgroup_root)
cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false);
m->pin_cgroupfs_fd = safe_close(m->pin_cgroupfs_fd);
free(m->cgroup_root);
m->cgroup_root = NULL;
}
Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
char *p;
Unit *u;
assert(m);
assert(cgroup);
u = hashmap_get(m->cgroup_unit, cgroup);
if (u)
return u;
p = strdupa(cgroup);
for (;;) {
char *e;
e = strrchr(p, '/');
if (e == p || !e)
return NULL;
*e = 0;
u = hashmap_get(m->cgroup_unit, p);
if (u)
return u;
}
}
Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
_cleanup_free_ char *cgroup = NULL;
int r;
assert(m);
if (pid <= 1)
return NULL;
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
if (r < 0)
return NULL;
return manager_get_unit_by_cgroup(m, cgroup);
}
int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
Unit *u;
int r;
assert(m);
assert(cgroup);
u = manager_get_unit_by_cgroup(m, cgroup);
if (u) {
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
if (r > 0) {
if (UNIT_VTABLE(u)->notify_cgroup_empty)
UNIT_VTABLE(u)->notify_cgroup_empty(u);
unit_add_to_gc_queue(u);
}
}
return 0;
}
static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
[CGROUP_AUTO] = "auto",
[CGROUP_CLOSED] = "closed",
[CGROUP_STRICT] = "strict",
};
DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);