cgroup.c revision 91901329245f070b621a24577393fb8f4ce9bffc
d24f45d9257685c7b1ad34a2a675b7ff35fb9398cmaeder/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4e7da6e9164ba18433755b68bbc8bc6354f0c04Eugen Kuksa
af313f59287bea73d6e453a1bdb397c3f68c3160Jonathan von Schroeder/***
af313f59287bea73d6e453a1bdb397c3f68c3160Jonathan von Schroeder This file is part of systemd.
167d70cbaefa2fcc045ffde6fb4b826524c1c7a9Christian Maeder
167d70cbaefa2fcc045ffde6fb4b826524c1c7a9Christian Maeder Copyright 2010 Lennart Poettering
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner systemd is free software; you can redistribute it and/or modify it
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner under the terms of the GNU General Public License as published by
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner the Free Software Foundation; either version 2 of the License, or
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner (at your option) any later version.
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner systemd is distributed in the hope that it will be useful, but
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner WITHOUT ANY WARRANTY; without even the implied warranty of
4c7cb5671b356d873d67829ec8062a5083c1ee0eEugen Kuksa MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6a6306c583c71d23b47101b59d7c9348d181ba57Eugen Kuksa General Public License for more details.
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner You should have received a copy of the GNU General Public License
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner along with systemd; If not, see <http://www.gnu.org/licenses/>.
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner***/
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner#include <errno.h>
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner#include <assert.h>
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner#include <unistd.h>
73677326fdbc1d154208000f6f37d7524d8f90cfJens Elkner#include <sys/types.h>
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner#include <signal.h>
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner#include <sys/mount.h>
730ccc63c301363853cba9286760d511b456671eChristian Maeder#include <fcntl.h>
730ccc63c301363853cba9286760d511b456671eChristian Maeder
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner#include "cgroup.h"
730ccc63c301363853cba9286760d511b456671eChristian Maeder#include "cgroup-util.h"
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner#include "log.h"
7bb0a9e92bc7a6f868eaa0b9c3212c0af4f96b7fEugen Kuksa
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elknerint cgroup_bonding_realize(CGroupBonding *b) {
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner int r;
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner assert(b);
a84a8d508a0778b13a4d097a6dd34b95feae78acJens Elkner assert(b->path);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder assert(b->controller);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (b->realized)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return 0;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if ((r = cg_create(b->controller, b->path)) < 0)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder b->realized = true;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (b->only_us && b->clean_up)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder cg_trim(b->controller, b->path, false);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return 0;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder}
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroederint cgroup_bonding_realize_list(CGroupBonding *first) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder CGroupBonding *b;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder int r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder LIST_FOREACH(by_unit, b, first)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if ((r = cgroup_bonding_realize(b)) < 0)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return 0;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder}
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroedervoid cgroup_bonding_free(CGroupBonding *b) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder assert(b);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (b->unit) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder CGroupBonding *f;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder LIST_REMOVE(CGroupBonding, by_unit, b->unit->meta.cgroup_bondings, b);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder assert_se(f = hashmap_get(b->unit->meta.manager->cgroup_bondings, b->path));
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder LIST_REMOVE(CGroupBonding, by_path, f, b);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (f)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder hashmap_replace(b->unit->meta.manager->cgroup_bondings, b->path, f);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder else
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder hashmap_remove(b->unit->meta.manager->cgroup_bondings, b->path);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder }
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (b->realized && b->only_us && b->clean_up) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (cgroup_bonding_is_empty(b) > 0)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder cg_delete(b->controller, b->path);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder else
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder cg_trim(b->controller, b->path, false);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder }
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder free(b->controller);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder free(b->path);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder free(b);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder}
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroedervoid cgroup_bonding_free_list(CGroupBonding *first) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder CGroupBonding *b, *n;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder LIST_FOREACH_SAFE(by_unit, b, n, first)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder cgroup_bonding_free(b);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder}
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroedervoid cgroup_bonding_trim(CGroupBonding *b, bool delete_root) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder assert(b);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (b->realized && b->only_us && b->clean_up)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder cg_trim(b->controller, b->path, delete_root);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder}
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroedervoid cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder CGroupBonding *b;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder LIST_FOREACH(by_unit, b, first)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder cgroup_bonding_trim(b, delete_root);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder}
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroederint cgroup_bonding_install(CGroupBonding *b, pid_t pid) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder int r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder assert(b);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder assert(pid >= 0);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if ((r = cg_create_and_attach(b->controller, b->path, pid)) < 0)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder b->realized = true;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return 0;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder}
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroederint cgroup_bonding_install_list(CGroupBonding *first, pid_t pid) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder CGroupBonding *b;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder int r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder LIST_FOREACH(by_unit, b, first)
8d632882ae6a59db929b7f87816da6c4d795594eJonathan von Schroeder if ((r = cgroup_bonding_install(b, pid)) < 0)
8d632882ae6a59db929b7f87816da6c4d795594eJonathan von Schroeder return r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return 0;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder}
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroederint cgroup_bonding_kill(CGroupBonding *b, int sig, Set *s) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder int r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder assert(b);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder assert(sig >= 0);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if ((r = cgroup_bonding_realize(b)) < 0)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder assert(b->realized);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return cg_kill_recursive(b->controller, b->path, sig, true, false, s);
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder}
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroederint cgroup_bonding_kill_list(CGroupBonding *first, int sig, Set *s) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder CGroupBonding *b;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder Set *allocated_set = NULL;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder int ret = -EAGAIN, r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (!s)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder return -ENOMEM;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder LIST_FOREACH(by_unit, b, first) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if ((r = cgroup_bonding_kill(b, sig, s)) < 0) {
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (r == -EAGAIN || r == -ESRCH)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder continue;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder ret = r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder goto finish;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder }
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder if (ret < 0 || r > 0)
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder ret = r;
5d3daa829555d76ff7cf45e71adf661e0819a12bJonathan von Schroeder }
f618b9465de7fe92a62fc4f247b1e10aa4454d2dJonathan von Schroeder
f618b9465de7fe92a62fc4f247b1e10aa4454d2dJonathan von Schroederfinish:
6aad75f5233b1f80eb84f53395f7bb44e9ed7b88Jonathan von Schroeder if (allocated_set)
6aad75f5233b1f80eb84f53395f7bb44e9ed7b88Jonathan von Schroeder set_free(allocated_set);
6aad75f5233b1f80eb84f53395f7bb44e9ed7b88Jonathan von Schroeder
6aad75f5233b1f80eb84f53395f7bb44e9ed7b88Jonathan von Schroeder return ret;
8d632882ae6a59db929b7f87816da6c4d795594eJonathan von Schroeder}
8d632882ae6a59db929b7f87816da6c4d795594eJonathan von Schroeder
5d8372f2459037830704c3f48d2b566ee1f35e31cmaeder/* Returns 1 if the group is empty, 0 if it is not, -EAGAIN if we
5d8372f2459037830704c3f48d2b566ee1f35e31cmaeder * cannot know */
7bb0a9e92bc7a6f868eaa0b9c3212c0af4f96b7fEugen Kuksaint cgroup_bonding_is_empty(CGroupBonding *b) {
7bb0a9e92bc7a6f868eaa0b9c3212c0af4f96b7fEugen Kuksa int r;
7bb0a9e92bc7a6f868eaa0b9c3212c0af4f96b7fEugen Kuksa
73677326fdbc1d154208000f6f37d7524d8f90cfJens Elkner assert(b);
73677326fdbc1d154208000f6f37d7524d8f90cfJens Elkner
a389e88e0acb83d8489bdc5e55bc5522b152bbecEugen Kuksa if ((r = cg_is_empty_recursive(b->controller, b->path, true)) < 0)
return r;
/* If it is empty it is empty */
if (r > 0)
return 1;
/* It's not only us using this cgroup, so we just don't know */
return b->only_us ? 0 : -EAGAIN;
}
int cgroup_bonding_is_empty_list(CGroupBonding *first) {
CGroupBonding *b;
LIST_FOREACH(by_unit, b, first) {
int r;
if ((r = cgroup_bonding_is_empty(b)) < 0) {
/* If this returned -EAGAIN, then we don't know if the
* group is empty, so let's see if another group can
* tell us */
if (r != -EAGAIN)
return r;
} else
return r;
}
return -EAGAIN;
}
int manager_setup_cgroup(Manager *m) {
char *current = NULL, *path = NULL;
int r;
char suffix[32];
assert(m);
/* 1. Determine hierarchy */
if ((r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &current)) < 0)
goto finish;
snprintf(suffix, sizeof(suffix), "/systemd-%lu", (unsigned long) getpid());
char_array_0(suffix);
free(m->cgroup_hierarchy);
if (endswith(current, suffix)) {
/* We probably got reexecuted and can continue to use our root cgroup */
m->cgroup_hierarchy = current;
current = NULL;
} else {
/* We need a new root cgroup */
m->cgroup_hierarchy = NULL;
if (asprintf(&m->cgroup_hierarchy, "%s%s", streq(current, "/") ? "" : current, suffix) < 0) {
r = -ENOMEM;
goto finish;
}
}
/* 2. Show data */
if ((r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path)) < 0)
goto finish;
log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
/* 3. Install agent */
if ((r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH)) < 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. Realize the group */
if ((r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0)) < 0) {
log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
goto finish;
}
/* 5. And pin it, so that it cannot be unmounted */
if (m->pin_cgroupfs_fd >= 0)
close_nointr_nofail(m->pin_cgroupfs_fd);
if ((m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK)) < 0) {
r = -errno;
goto finish;
}
log_debug("Created root group.");
finish:
free(current);
free(path);
return r;
}
void manager_shutdown_cgroup(Manager *m, bool delete) {
assert(m);
if (delete && m->cgroup_hierarchy)
cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy);
if (m->pin_cgroupfs_fd >= 0) {
close_nointr_nofail(m->pin_cgroupfs_fd);
m->pin_cgroupfs_fd = -1;
}
free(m->cgroup_hierarchy);
m->cgroup_hierarchy = NULL;
}
int cgroup_notify_empty(Manager *m, const char *group) {
CGroupBonding *l, *b;
assert(m);
assert(group);
if (!(l = hashmap_get(m->cgroup_bondings, group)))
return 0;
LIST_FOREACH(by_path, b, l) {
int t;
if (!b->unit)
continue;
if ((t = cgroup_bonding_is_empty_list(b)) < 0) {
/* If we don't know, we don't know */
if (t != -EAGAIN)
log_warning("Failed to check whether cgroup is empty: %s", strerror(errno));
continue;
}
if (t > 0)
if (UNIT_VTABLE(b->unit)->cgroup_notify_empty)
UNIT_VTABLE(b->unit)->cgroup_notify_empty(b->unit);
}
return 0;
}
Unit* cgroup_unit_by_pid(Manager *m, pid_t pid) {
CGroupBonding *l, *b;
char *group = NULL;
assert(m);
if (pid <= 1)
return NULL;
if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &group) < 0)
return NULL;
l = hashmap_get(m->cgroup_bondings, group);
if (!l) {
char *slash;
while ((slash = strrchr(group, '/'))) {
if (slash == group)
break;
*slash = 0;
if ((l = hashmap_get(m->cgroup_bondings, group)))
break;
}
}
free(group);
LIST_FOREACH(by_path, b, l) {
if (!b->unit)
continue;
if (b->only_us)
return b->unit;
}
return NULL;
}
CGroupBonding *cgroup_bonding_find_list(CGroupBonding *first, const char *controller) {
CGroupBonding *b;
assert(controller);
LIST_FOREACH(by_unit, b, first)
if (streq(b->controller, controller))
return b;
return NULL;
}
char *cgroup_bonding_to_string(CGroupBonding *b) {
char *r;
assert(b);
if (asprintf(&r, "%s:%s", b->controller, b->path) < 0)
return NULL;
return r;
}
pid_t cgroup_bonding_search_main_pid(CGroupBonding *b) {
FILE *f;
pid_t pid = 0, npid;
int r;
assert(b);
if (!b->only_us)
return 0;
if ((r = cg_enumerate_processes(b->controller, b->path, &f)) < 0)
return 0;
while ((r = cg_read_pid(f, &npid)) > 0) {
if (npid == pid)
continue;
if (pid != 0) {
/* Dang, there's more than one PID in this
* group, so we don't know what process is the
* main process. */
pid = 0;
break;
}
pid = npid;
}
fclose(f);
return pid;
}
pid_t cgroup_bonding_search_main_pid_list(CGroupBonding *first) {
CGroupBonding *b;
pid_t pid;
/* Try to find a main pid from this cgroup, but checking if
* there's only one PID in the cgroup and returning it. Later
* on we might want to add additional, smarter heuristics
* here. */
LIST_FOREACH(by_unit, b, first)
if ((pid = cgroup_bonding_search_main_pid(b)) != 0)
return pid;
return 0;
}