cgroup.c revision 3d040cf24473f2ed13121d57ed753bad5f8ad09d
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2013 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_init(CGroupContext *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Initialize everything to the kernel defaults, assuming the
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * structure is preinitialized to 0 */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->memory_limit = c->memory_soft_limit = (uint64_t) -1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(CGroupDeviceAllow, device_allow, c->device_allow, a);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering LIST_REMOVE(CGroupBlockIODeviceWeight, device_weights, c->blockio_device_weights, w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(CGroupBlockIODeviceBandwidth, device_bandwidths, c->blockio_device_bandwidths, b);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_done(CGroupContext *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_free_device_allow(c, c->device_allow);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sCPUAccounting=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sBlockIOAccounting=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sMemoryAccounting=%s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sCPUShares=%lu\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sBlockIOWeight%lu\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sDevicePolicy=%s\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, cgroup_device_policy_to_string(c->device_policy));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_allow, a, c->device_allow)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sDeviceAllow=%s %s%s%s\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_weights, w, c->blockio_device_weights)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sBlockIODeviceWeight=%s %lu",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%s%s=%s %s\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering b->read ? "BlockIOReadBandwidth" : "BlockIOWriteBandwidth",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering format_bytes(buf, sizeof(buf), b->bandwidth));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int lookup_blkio_device(const char *p, dev_t *dev) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Couldn't stat device %s: %m", p);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If this is not a device node then find the block
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * device this file is stored on */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If this is a partition, try to get the originating
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * block device */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int whitelist_device(const char *path, const char *node, const char *acc) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Couldn't stat device %s", node);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("%s is not a device.", node);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%c %u:%u %s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to set devices.allow on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const char *path) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char buf[DECIMAL_STR_MAX(unsigned long) + 1];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("cpu", path, "cpu.shares", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to set cpu.shares on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char buf[MAX3(DECIMAL_STR_MAX(unsigned long)+1,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(unsigned long)*1,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, "%lu\n", c->blockio_weight);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("blkio", path, "blkio.weight", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Failed to set blkio.weight on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* FIXME: no way to reset this list */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
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 log_error("Failed to set blkio.weight_device on %s: %s", path, strerror(-r));
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 a = b->read ? "blkio.throttle.read_bps_device" : "blkio.throttle.write_bps_device";
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 log_error("Failed to set %s on %s: %s", a, path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
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 log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->device_allow || c->device_policy != CGROUP_AUTO)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("devices", path, "devices.deny", "a");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_set_attribute("devices", path, "devices.allow", "a");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to reset devices.list on %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (c->device_policy == CGROUP_AUTO && c->device_allow)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering static const char auto_devices[] =
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *x, *y;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(device_allow, a, c->device_allow) {
7850b3b83791ba0e2377ba40383c5abc258b839dKay Sievers unsigned k = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringCGroupControllerMask cgroup_context_get_mask(CGroupContext *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Figure out which controllers we need */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->cpu_accounting || c->cpu_shares != 1024)
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek if (c->device_allow || c->device_policy != CGROUP_AUTO)
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmekstatic CGroupControllerMask unit_get_cgroup_mask(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic CGroupControllerMask unit_get_members_mask(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SET_FOREACH(m, u->dependencies[UNIT_BEFORE], i) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mask |= unit_get_cgroup_mask(m) | unit_get_members_mask(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic CGroupControllerMask unit_get_siblings_mask(Unit *u) {
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);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek path = unit_default_cgroup_path(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = hashmap_put(u->manager->cgroup_unit, path, u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* First, create our own group */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to create cgroup %s: %s", path, strerror(-r));
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 log_error("Failed to migrate cgroup %s: %s", path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* And remember the new data */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int unit_realize_cgroup_now(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(Unit, cgroup_queue, u->manager->cgroup_queue, u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mask = unit_get_cgroup_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* First, realize parents */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_realize_cgroup_now(UNIT_DEREF(u->slice));
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering /* And then do the real work */
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poetteringstatic void unit_add_to_cgroup_queue(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_PREPEND(Unit, cgroup_queue, u->manager->cgroup_queue, u);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringunsigned manager_dispatch_cgroup_queue(Manager *m) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned n = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((i = m->cgroup_queue)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_apply(unit_get_cgroup_context(i), i->cgroup_mask, i->cgroup_path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void unit_queue_siblings(Unit *u) {
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 SET_FOREACH(m, slice->dependencies[UNIT_BEFORE], i) {
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 /* Add all sibling slices to the cgroup queue. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* And realize this one now */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* And apply the values */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering cgroup_context_apply(c, u->cgroup_mask, u->cgroup_path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_trim_with_mask(u->cgroup_mask, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug("Failed to destroy cgroup %s: %s", u->cgroup_path, strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f) < 0)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek while (cg_read_pid(f, &npid) > 0) {
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)
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 /* 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 /* 1. Determine hierarchy */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Cannot determine cgroup we are running in: %s", strerror(-r));
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 /* 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. */
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 log_error("Cannot find cgroup mount point: %s", strerror(-r));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
2e8fb7026d3c560194cfe9f83935ce0b16263da0Lukas Nykryn /* 3. Install agent */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_warning("Failed to install release agent, ignoring: %s", strerror(-r));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_debug("Installed release agent.");
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_debug("Release agent already installed.");
if (m->pin_cgroupfs_fd >= 0)
return -errno;
assert(m);
if (m->pin_cgroupfs_fd >= 0) {
Unit *u;
assert(m);
return NULL;
assert(m);
return NULL;
return NULL;
Unit *u;
assert(m);