cgroup.c revision 3d040cf24473f2ed13121d57ed753bad5f8ad09d
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/***
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2013 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart 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
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
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***/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <fcntl.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "path-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "special.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "cgroup-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "cgroup.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_init(CGroupContext *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Initialize everything to the kernel defaults, assuming the
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * structure is preinitialized to 0 */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->cpu_shares = 1024;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->memory_limit = c->memory_soft_limit = (uint64_t) -1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->blockio_weight = 1000;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(a);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(CGroupDeviceAllow, device_allow, c->device_allow, a);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(a->path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(a);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering LIST_REMOVE(CGroupBlockIODeviceWeight, device_weights, c->blockio_device_weights, w);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering free(w->path);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering free(w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(b);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(CGroupBlockIODeviceBandwidth, device_bandwidths, c->blockio_device_bandwidths, b);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(b->path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(b);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_done(CGroupContext *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while (c->blockio_device_weights)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while (c->blockio_device_bandwidths)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while (c->device_allow)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_free_device_allow(c, c->device_allow);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CGroupBlockIODeviceBandwidth *b;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CGroupBlockIODeviceWeight *w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CGroupDeviceAllow *a;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix = strempty(prefix);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering fprintf(f,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sCPUAccounting=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sBlockIOAccounting=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sMemoryAccounting=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sCPUShares=%lu\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sBlockIOWeight%lu\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sMemoryLimit=%" PRIu64 "\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sMemorySoftLimit=%" PRIu64 "\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sDevicePolicy=%s\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, yes_no(c->cpu_accounting),
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, yes_no(c->blockio_accounting),
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, yes_no(c->memory_accounting),
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, c->cpu_shares,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, c->blockio_weight,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, c->memory_limit,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, c->memory_soft_limit,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, cgroup_device_policy_to_string(c->device_policy));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_allow, a, c->device_allow)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering fprintf(f,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sDeviceAllow=%s %s%s%s\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering a->path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_weights, w, c->blockio_device_weights)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering fprintf(f,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sBlockIODeviceWeight=%s %lu",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->weight);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char buf[FORMAT_BYTES_MAX];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering fprintf(f,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%s%s=%s %s\n",
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering prefix,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering b->read ? "BlockIOReadBandwidth" : "BlockIOWriteBandwidth",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering b->path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering format_bytes(buf, sizeof(buf), b->bandwidth));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int lookup_blkio_device(const char *p, dev_t *dev) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct stat st;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(p);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(dev);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = stat(p, &st);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Couldn't stat device %s: %m", p);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -errno;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (S_ISBLK(st.st_mode))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *dev = st.st_rdev;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (major(st.st_dev) != 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If this is not a device node then find the block
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * device this file is stored on */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *dev = st.st_dev;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If this is a partition, try to get the originating
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * block device */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering block_get_whole_disk(*dev, dev);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENODEV;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
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 struct stat st;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(acc);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (stat(node, &st) < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Couldn't stat device %s", node);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -errno;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
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 return -ENODEV;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%c %u:%u %s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering S_ISCHR(st.st_mode) ? 'c' : 'b',
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering major(st.st_rdev), minor(st.st_rdev),
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering acc);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to set devices.allow on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const char *path) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (mask == 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (mask & CGROUP_CPU) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char buf[DECIMAL_STR_MAX(unsigned long) + 1];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, "%lu\n", c->cpu_shares);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("cpu", path, "cpu.shares", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to set cpu.shares on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (mask & CGROUP_BLKIO) {
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 CGroupBlockIODeviceWeight *w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CGroupBlockIODeviceBandwidth *b;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, "%lu\n", c->blockio_weight);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("blkio", path, "blkio.weight", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to set blkio.weight on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* FIXME: no way to reset this list */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering dev_t dev;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = lookup_blkio_device(w->path, &dev);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering 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 if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to set blkio.weight_device on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* FIXME: no way to reset this list */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *a;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering dev_t dev;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = lookup_blkio_device(b->path, &dev);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering a = b->read ? "blkio.throttle.read_bps_device" : "blkio.throttle.write_bps_device";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("blkio", path, a, buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to set %s on %s: %s", a, path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (mask & CGROUP_MEMORY) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char buf[DECIMAL_STR_MAX(uint64_t) + 1];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek if (mask & CGROUP_DEVICE) {
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek CGroupDeviceAllow *a;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->device_allow || c->device_policy != CGROUP_AUTO)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("devices", path, "devices.deny", "a");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", "a");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to reset devices.list on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->device_policy == CGROUP_CLOSED ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (c->device_policy == CGROUP_AUTO && c->device_allow)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering static const char auto_devices[] =
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "/dev/null\0" "rw\0"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "/dev/zero\0" "rw\0"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "/dev/full\0" "rw\0"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "/dev/random\0" "rw\0"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "/dev/urandom\0" "rw\0";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *x, *y;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering NULSTR_FOREACH_PAIR(x, y, auto_devices)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering whitelist_device(path, x, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_allow, a, c->device_allow) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char acc[4];
7850b3b83791ba0e2377ba40383c5abc258b839dKay Sievers unsigned k = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (a->r)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering acc[k++] = 'r';
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (a->w)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering acc[k++] = 'w';
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (a->m)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering acc[k++] = 'm';
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (k == 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering acc[k++] = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering whitelist_device(path, a->path, acc);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek }
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringCGroupControllerMask cgroup_context_get_mask(CGroupContext *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CGroupControllerMask mask = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Figure out which controllers we need */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->cpu_accounting || c->cpu_shares != 1024)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mask |= CGROUP_CPUACCT | CGROUP_CPU;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->blockio_accounting ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->blockio_weight != 1000 ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->blockio_device_weights ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->blockio_device_bandwidths)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mask |= CGROUP_BLKIO;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->memory_accounting ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->memory_limit != (uint64_t) -1 ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->memory_soft_limit != (uint64_t) -1)
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek mask |= CGROUP_MEMORY;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek if (c->device_allow || c->device_policy != CGROUP_AUTO)
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek mask |= CGROUP_DEVICE;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return mask;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmekstatic CGroupControllerMask unit_get_cgroup_mask(Unit *u) {
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek CGroupContext *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c = unit_get_cgroup_context(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!c)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering return cgroup_context_get_mask(c);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering}
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic CGroupControllerMask unit_get_members_mask(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CGroupControllerMask mask = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Unit *m;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek Iterator i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SET_FOREACH(m, u->dependencies[UNIT_BEFORE], i) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek if (UNIT_DEREF(m->slice) != u)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mask |= unit_get_cgroup_mask(m) | unit_get_members_mask(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek return mask;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic CGroupControllerMask unit_get_siblings_mask(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!UNIT_ISSET(u->slice))
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Sibling propagation is only relevant for weight-based
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * controllers, so let's mask out everything else */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return unit_get_members_mask(UNIT_DEREF(u->slice)) &
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (CGROUP_CPU|CGROUP_BLKIO|CGROUP_CPUACCT);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek}
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *path = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
943aad8ca57a6b5c49c4ea60f9e8c13bf9b20e6cZbigniew Jędrzejewski-Szmek assert(u);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek path = unit_default_cgroup_path(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!path)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = hashmap_put(u->manager->cgroup_unit, path, u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* First, create our own group */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_create_with_mask(mask, path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to create cgroup %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Then, possibly move things over */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->cgroup_path && !streq(path, u->cgroup_path)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_migrate_with_mask(mask, u->cgroup_path, path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to migrate cgroup %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* And remember the new data */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(u->cgroup_path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->cgroup_path = path;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->cgroup_realized = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->cgroup_mask = mask;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
4ec24515daa780118709e04cd78dae93f25a8428Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int unit_realize_cgroup_now(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CGroupControllerMask mask;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->in_cgroup_queue) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(Unit, cgroup_queue, u->manager->cgroup_queue, u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->in_cgroup_queue = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mask = unit_get_cgroup_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mask &= u->manager->cgroup_supported;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->cgroup_realized &&
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->cgroup_mask == mask)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* First, realize parents */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (UNIT_ISSET(u->slice))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_realize_cgroup_now(UNIT_DEREF(u->slice));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering /* And then do the real work */
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering return unit_create_cgroups(u, mask);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poetteringstatic void unit_add_to_cgroup_queue(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->in_cgroup_queue)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_PREPEND(Unit, cgroup_queue, u->manager->cgroup_queue, u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->in_cgroup_queue = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringunsigned manager_dispatch_cgroup_queue(Manager *m) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Unit *i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned n = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((i = m->cgroup_queue)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(i->in_cgroup_queue);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (unit_realize_cgroup_now(i) >= 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_apply(unit_get_cgroup_context(i), i->cgroup_mask, i->cgroup_path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return n;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void unit_queue_siblings(Unit *u) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering Unit *slice;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* This adds the siblings of the specified unit and the
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * siblings of all parent units to the cgroup queue. (But
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * neither the specified unit itself nor the parents.) */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((slice = UNIT_DEREF(u->slice))) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering Iterator i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Unit *m;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SET_FOREACH(m, slice->dependencies[UNIT_BEFORE], i) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (m == u)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (UNIT_DEREF(m->slice) != slice)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_add_to_cgroup_queue(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u = slice;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering }
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering}
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint unit_realize_cgroup(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering CGroupContext *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c = unit_get_cgroup_context(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!c)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* So, here's the deal: when realizing the cgroups for this
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * unit, we need to first create all parents, but there's more
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * actually: for the weight-based controllers we also need to
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * make sure that all our siblings (i.e. units that are in the
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * same slice as we are) have cgroup too. Otherwise things
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * would become very uneven as each of their processes would
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * get as much resources as all our group together. This call
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * will synchronously create the parent cgroups, but will
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * defer work on the siblings to the next event loop
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * iteration. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Add all sibling slices to the cgroup queue. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_queue_siblings(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* And realize this one now */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = unit_realize_cgroup_now(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* And apply the values */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r >= 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_apply(c, u->cgroup_mask, u->cgroup_path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid unit_destroy_cgroup(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!u->cgroup_path)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_trim_with_mask(u->cgroup_mask, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug("Failed to destroy cgroup %s: %s", u->cgroup_path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(u->cgroup_path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->cgroup_path = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->cgroup_realized = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->cgroup_mask = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringpid_t unit_search_main_pid(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering pid_t pid = 0, npid, mypid;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!u->cgroup_path)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return 0;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f) < 0)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return 0;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek mypid = getpid();
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek while (cg_read_pid(f, &npid) > 0) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek pid_t ppid;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (npid == pid)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek continue;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* Ignore processes that aren't our kids */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek continue;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (pid != 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Dang, there's more than one daemonized PID
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering in this group, so we don't know what process
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering is the main process. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering pid = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering break;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering pid = npid;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return pid;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint manager_setup_cgroup(Manager *m) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_free_ char *path = NULL;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *e, *a;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* 0. Be nice to Ingo Molnar #628004 */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (path_is_mount_point("/sys/fs/cgroup/systemd", false) <= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("No control group support available, not creating root group.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* 1. Determine hierarchy */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(m->cgroup_root);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->cgroup_root = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Cannot determine cgroup we are running in: %s", strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* Already in /system.slice? If so, let's cut this off again */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (m->running_as == SYSTEMD_SYSTEM) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (e)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek *e = 0;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* And make sure to store away the root value without trailing
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek * slash, even for the root dir, so that we can easily prepend
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek * it everywhere. */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (streq(m->cgroup_root, "/"))
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek m->cgroup_root[0] = 0;
2e8fb7026d3c560194cfe9f83935ce0b16263da0Lukas Nykryn
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykryn /* 2. Show data */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (r < 0) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_error("Cannot find cgroup mount point: %s", strerror(-r));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return r;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
2e8fb7026d3c560194cfe9f83935ce0b16263da0Lukas Nykryn /* 3. Install agent */
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykryn if (m->running_as == SYSTEMD_SYSTEM) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (r < 0)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_warning("Failed to install release agent, ignoring: %s", strerror(-r));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek else if (r > 0)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_debug("Installed release agent.");
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek else
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_debug("Release agent already installed.");
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
/* 4. Realize the system slice and put us in there */
if (m->running_as == SYSTEMD_SYSTEM) {
a = strappenda(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, a, 0);
} else
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 */
if (m->pin_cgroupfs_fd >= 0)
close_nointr_nofail(m->pin_cgroupfs_fd);
m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
if (r < 0) {
log_error("Failed to open pin file: %m");
return -errno;
}
/* 6. 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);
if (m->pin_cgroupfs_fd >= 0) {
close_nointr_nofail(m->pin_cgroupfs_fd);
m->pin_cgroupfs_fd = -1;
}
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);