#include <fcntl.h>
#include <fnmatch.h>
-#include "process-util.h"
-#include "path-util.h"
-// #include "special.h"
+#include "alloc-util.h"
#include "cgroup-util.h"
#include "cgroup.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "process-util.h"
+//#include "special.h"
+#include "string-table.h"
+#include "string-util.h"
#define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
+#if 0 /// UNNEEDED by elogind
void cgroup_context_init(CGroupContext *c) {
assert(c);
/* Initialize everything to the kernel defaults, assuming the
* structure is preinitialized to 0 */
- c->cpu_shares = (unsigned long) -1;
- c->startup_cpu_shares = (unsigned long) -1;
+ c->cpu_shares = CGROUP_CPU_SHARES_INVALID;
+ c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID;
+ c->cpu_quota_per_sec_usec = USEC_INFINITY;
+
c->memory_limit = (uint64_t) -1;
- c->blockio_weight = (unsigned long) -1;
- c->startup_blockio_weight = (unsigned long) -1;
- c->cpu_quota_per_sec_usec = USEC_INFINITY;
+ c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
+ c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
+
+ c->tasks_max = (uint64_t) -1;
+
+ c->netclass_type = CGROUP_NETCLASS_TYPE_NONE;
}
void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
cgroup_context_free_device_allow(c, c->device_allow);
}
-/// UNNEEDED by elogind
-#if 0
void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
CGroupBlockIODeviceBandwidth *b;
CGroupBlockIODeviceWeight *w;
"%sCPUAccounting=%s\n"
"%sBlockIOAccounting=%s\n"
"%sMemoryAccounting=%s\n"
- "%sCPUShares=%lu\n"
- "%sStartupCPUShares=%lu\n"
+ "%sTasksAccounting=%s\n"
+ "%sCPUShares=%" PRIu64 "\n"
+ "%sStartupCPUShares=%" PRIu64 "\n"
"%sCPUQuotaPerSecSec=%s\n"
- "%sBlockIOWeight=%lu\n"
- "%sStartupBlockIOWeight=%lu\n"
+ "%sBlockIOWeight=%" PRIu64 "\n"
+ "%sStartupBlockIOWeight=%" PRIu64 "\n"
"%sMemoryLimit=%" PRIu64 "\n"
+ "%sTasksMax=%" PRIu64 "\n"
"%sDevicePolicy=%s\n"
"%sDelegate=%s\n",
prefix, yes_no(c->cpu_accounting),
prefix, yes_no(c->blockio_accounting),
prefix, yes_no(c->memory_accounting),
+ prefix, yes_no(c->tasks_accounting),
prefix, c->cpu_shares,
prefix, c->startup_cpu_shares,
prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
prefix, c->blockio_weight,
prefix, c->startup_blockio_weight,
prefix, c->memory_limit,
+ prefix, c->tasks_max,
prefix, cgroup_device_policy_to_string(c->device_policy),
prefix, yes_no(c->delegate));
LIST_FOREACH(device_weights, w, c->blockio_device_weights)
fprintf(f,
- "%sBlockIODeviceWeight=%s %lu",
+ "%sBlockIODeviceWeight=%s %" PRIu64,
prefix,
w->path,
w->weight);
r = cg_set_attribute("devices", path, "devices.allow", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set devices.allow on %s: %m", path);
return r;
r = cg_set_attribute("devices", path, "devices.allow", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set devices.allow on %s: %m", path);
}
return -errno;
}
-void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, ManagerState state) {
+void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, uint32_t netclass, ManagerState state) {
bool is_root;
int r;
* and missing cgroups, i.e. EROFS and ENOENT. */
if ((mask & CGROUP_MASK_CPU) && !is_root) {
- char buf[MAX(DECIMAL_STR_MAX(unsigned long), DECIMAL_STR_MAX(usec_t)) + 1];
+ char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1];
- sprintf(buf, "%lu\n",
- IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != (unsigned long) -1 ? c->startup_cpu_shares :
- c->cpu_shares != (unsigned long) -1 ? c->cpu_shares : 1024);
+ sprintf(buf, "%" PRIu64 "\n",
+ IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->startup_cpu_shares :
+ c->cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->cpu_shares : CGROUP_CPU_SHARES_DEFAULT);
r = cg_set_attribute("cpu", path, "cpu.shares", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set cpu.shares on %s: %m", path);
sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set cpu.cfs_period_us on %s: %m", path);
if (c->cpu_quota_per_sec_usec != USEC_INFINITY) {
} else
r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1");
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set cpu.cfs_quota_us on %s: %m", path);
}
if (mask & CGROUP_MASK_BLKIO) {
- char buf[MAX3(DECIMAL_STR_MAX(unsigned long)+1,
- DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(unsigned long)*1,
+ char buf[MAX(DECIMAL_STR_MAX(uint64_t)+1,
DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
CGroupBlockIODeviceWeight *w;
CGroupBlockIODeviceBandwidth *b;
if (!is_root) {
- sprintf(buf, "%lu\n", IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != (unsigned long) -1 ? c->startup_blockio_weight :
- c->blockio_weight != (unsigned long) -1 ? c->blockio_weight : 1000);
+ sprintf(buf, "%" PRIu64 "\n",
+ IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->startup_blockio_weight :
+ c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ? c->blockio_weight : CGROUP_BLKIO_WEIGHT_DEFAULT);
r = cg_set_attribute("blkio", path, "blkio.weight", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set blkio.weight on %s: %m", path);
/* FIXME: no way to reset this list */
if (r < 0)
continue;
- sprintf(buf, "%u:%u %lu", major(dev), minor(dev), w->weight);
+ sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), w->weight);
r = cg_set_attribute("blkio", path, "blkio.weight_device", buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set blkio.weight_device on %s: %m", path);
}
}
sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth);
r = cg_set_attribute("blkio", path, a, buf);
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set %s on %s: %m", a, path);
}
}
}
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set memory.limit_in_bytes/memory.max on %s: %m", path);
}
- if ((mask & CGROUP_MASK_DEVICE) && !is_root) {
+ if ((mask & CGROUP_MASK_DEVICES) && !is_root) {
CGroupDeviceAllow *a;
/* Changing the devices list of a populated cgroup
else
r = cg_set_attribute("devices", path, "devices.allow", "a");
if (r < 0)
- log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to reset devices.list on %s: %m", path);
if (c->device_policy == CGROUP_CLOSED ||
log_debug("Ignoring device %s while writing cgroup attribute.", a->path);
}
}
+
+ if ((mask & CGROUP_MASK_PIDS) && !is_root) {
+
+ if (c->tasks_max != (uint64_t) -1) {
+ char buf[DECIMAL_STR_MAX(uint64_t) + 2];
+
+ sprintf(buf, "%" PRIu64 "\n", c->tasks_max);
+ r = cg_set_attribute("pids", path, "pids.max", buf);
+ } else
+ r = cg_set_attribute("pids", path, "pids.max", "max");
+
+ if (r < 0)
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to set pids.max on %s: %m", path);
+ }
+
+ if (mask & CGROUP_MASK_NET_CLS) {
+ char buf[DECIMAL_STR_MAX(uint32_t)];
+
+ sprintf(buf, "%" PRIu32, netclass);
+
+ r = cg_set_attribute("net_cls", path, "net_cls.classid", buf);
+ if (r < 0)
+ log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to set net_cls.classid on %s: %m", path);
+ }
}
-#endif // 0
CGroupMask cgroup_context_get_mask(CGroupContext *c) {
CGroupMask mask = 0;
/* Figure out which controllers we need */
if (c->cpu_accounting ||
- c->cpu_shares != (unsigned long) -1 ||
- c->startup_cpu_shares != (unsigned long) -1 ||
+ c->cpu_shares != CGROUP_CPU_SHARES_INVALID ||
+ c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ||
c->cpu_quota_per_sec_usec != USEC_INFINITY)
mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
if (c->blockio_accounting ||
- c->blockio_weight != (unsigned long) -1 ||
- c->startup_blockio_weight != (unsigned long) -1 ||
+ c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
+ c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
c->blockio_device_weights ||
c->blockio_device_bandwidths)
mask |= CGROUP_MASK_BLKIO;
if (c->device_allow ||
c->device_policy != CGROUP_AUTO)
- mask |= CGROUP_MASK_DEVICE;
+ mask |= CGROUP_MASK_DEVICES;
+
+ if (c->tasks_accounting ||
+ c->tasks_max != (uint64_t) -1)
+ mask |= CGROUP_MASK_PIDS;
+
+ if (c->netclass_type != CGROUP_NETCLASS_TYPE_NONE)
+ mask |= CGROUP_MASK_NET_CLS;
return mask;
}
-/// UNNEEDED by elogind
-#if 0
CGroupMask unit_get_own_mask(Unit *u) {
CGroupContext *c;
if (r < 0)
return log_oom();
- r = cg_get_path(ELOGIND_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.populated", &populated);
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.populated", &populated);
if (r < 0)
return log_oom();
return u->cgroup_realized && u->cgroup_realized_mask == target_mask;
}
+static int unit_find_free_netclass_cgroup(Unit *u, uint32_t *ret) {
+
+ uint32_t start, i;
+ Manager *m;
+
+ assert(u);
+
+ m = u->manager;
+
+ i = start = m->cgroup_netclass_registry_last;
+
+ do {
+ i++;
+
+ if (!hashmap_get(m->cgroup_netclass_registry, UINT_TO_PTR(i))) {
+ m->cgroup_netclass_registry_last = i;
+ *ret = i;
+ return 0;
+ }
+
+ if (i == UINT32_MAX)
+ i = CGROUP_NETCLASS_FIXED_MAX;
+
+ } while (i != start);
+
+ return -ENOBUFS;
+}
+
+int unit_add_to_netclass_cgroup(Unit *u) {
+
+ CGroupContext *cc;
+ Unit *first;
+ void *key;
+ int r;
+
+ assert(u);
+
+ cc = unit_get_cgroup_context(u);
+ if (!cc)
+ return 0;
+
+ switch (cc->netclass_type) {
+ case CGROUP_NETCLASS_TYPE_NONE:
+ return 0;
+
+ case CGROUP_NETCLASS_TYPE_FIXED:
+ u->cgroup_netclass_id = cc->netclass_id;
+ break;
+
+ case CGROUP_NETCLASS_TYPE_AUTO:
+ /* Allocate a new ID in case it was requested and not done yet */
+ if (u->cgroup_netclass_id == 0) {
+ r = unit_find_free_netclass_cgroup(u, &u->cgroup_netclass_id);
+ if (r < 0)
+ return r;
+
+ log_debug("Dynamically assigned netclass cgroup id %" PRIu32 " to %s", u->cgroup_netclass_id, u->id);
+ }
+
+ break;
+ }
+
+ r = hashmap_ensure_allocated(&u->manager->cgroup_netclass_registry, &trivial_hash_ops);
+ if (r < 0)
+ return r;
+
+ key = UINT32_TO_PTR(u->cgroup_netclass_id);
+ first = hashmap_get(u->manager->cgroup_netclass_registry, key);
+
+ if (first) {
+ LIST_PREPEND(cgroup_netclass, first, u);
+ return hashmap_replace(u->manager->cgroup_netclass_registry, key, u);
+ }
+
+ return hashmap_put(u->manager->cgroup_netclass_registry, key, u);
+}
+
+int unit_remove_from_netclass_cgroup(Unit *u) {
+
+ Unit *head;
+ void *key;
+
+ assert(u);
+
+ key = UINT32_TO_PTR(u->cgroup_netclass_id);
+
+ LIST_FIND_HEAD(cgroup_netclass, u, head);
+ LIST_REMOVE(cgroup_netclass, head, u);
+
+ if (head)
+ return hashmap_replace(u->manager->cgroup_netclass_registry, key, head);
+
+ hashmap_remove(u->manager->cgroup_netclass_registry, key);
+
+ return 0;
+}
+
/* Check if necessary controllers and attributes for a unit are in place.
*
* If so, do nothing.
return r;
/* Finally, apply the necessary attributes. */
- cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, state);
+ cgroup_context_apply(unit_get_cgroup_context(u), target_mask, u->cgroup_path, u->cgroup_netclass_id, state);
return 0;
}
if (!u->cgroup_path)
return -ENXIO;
- r = cg_enumerate_processes(ELOGIND_CGROUP_CONTROLLER, u->cgroup_path, &f);
+ r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f);
if (r < 0)
return r;
continue;
/* Ignore processes that aren't our kids */
- if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid)
+ if (get_process_ppid(npid, &ppid) >= 0 && ppid != mypid)
continue;
if (pid != 0)
assert(u);
assert(path);
- r = cg_enumerate_processes(ELOGIND_CGROUP_CONTROLLER, path, &f);
+ r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, path, &f);
if (r < 0)
ret = r;
else {
ret = r;
}
- r = cg_enumerate_subgroups(ELOGIND_CGROUP_CONTROLLER, path, &d);
+ r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d);
if (r < 0) {
if (ret >= 0)
ret = r;
if (!u->cgroup_path)
return 0;
- r = cg_is_empty_recursive(ELOGIND_CGROUP_CONTROLLER, u->cgroup_path);
+ r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
if (r <= 0)
return r;
/* 1. Determine hierarchy */
m->cgroup_root = mfree(m->cgroup_root);
- r = cg_pid_get_path(ELOGIND_CGROUP_CONTROLLER, 0, &m->cgroup_root);
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root);
if (r < 0)
return log_error_errno(r, "Cannot determine cgroup we are running in: %m");
-/// elogind does not support systemd scopes and slices
-#if 0
+
+#if 0 /// elogind does not support systemd scopes and slices
/* Chop off the init scope, if we are already located in it */
e = endswith(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);
* it. This is to support live upgrades from older systemd
* versions where PID 1 was moved there. Also see
* cg_get_root_path(). */
- if (!e) {
+ if (!e && m->running_as == MANAGER_SYSTEM) {
e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
if (!e)
e = endswith(m->cgroup_root, "/system"); /* even more legacy */
while ((e = endswith(m->cgroup_root, "/")))
*e = 0;
log_debug_elogind("Cgroup Controller \"%s\" -> root \"%s\"",
- ELOGIND_CGROUP_CONTROLLER, m->cgroup_root);
+ SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root);
/* 2. Show data */
- r = cg_get_path(ELOGIND_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path);
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path);
if (r < 0)
return log_error_errno(r, "Cannot find cgroup mount point: %m");
if (unified > 0)
log_debug("Unified cgroup hierarchy is located at %s.", path);
else
- log_debug("Using cgroup controller " ELOGIND_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
+ log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
if (!m->test_run) {
const char *scope_path;
/* In the unified hierarchy we can can get
* cgroup empty notifications via inotify. */
-/// elogind does not support the unified hierarchy, yet.
-#if 0
+
+#if 0 /// elogind does not support the unified hierarchy, yet.
m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
safe_close(m->cgroup_inotify_fd);
#else
return log_error_errno(EOPNOTSUPP, "Unified cgroup hierarchy not supported: %m");
-#endif // elogind
+#endif // 0
} else if (m->running_as == MANAGER_SYSTEM) {
+
/* On the legacy hierarchy we only get
* notifications via cgroup agents. (Which
* isn't really reliable, since it does not
* generate events when control groups with
* children run empty. */
- r = cg_install_release_agent(ELOGIND_CGROUP_CONTROLLER, ELOGIND_CGROUP_AGENT_PATH);
+ r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, ELOGIND_CGROUP_AGENT_PATH);
if (r < 0)
log_warning_errno(r, "Failed to install release agent, ignoring: %m");
else if (r > 0)
log_debug("Release agent already installed.");
}
-/// elogind is not meant to run in systemd init scope
-#if 0
+#if 0 /// elogind is not meant to run in systemd init scope
/* 4. Make sure we are in the special "init.scope" unit in the root slice. */
scope_path = strjoina(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);
- r = cg_create_and_attach(ELOGIND_CGROUP_CONTROLLER, scope_path, 0);
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
#else
- if (streq(m->cgroup_root, "/elogind"))
+ if (streq(SYSTEMD_CGROUP_CONTROLLER, "name=elogind"))
+ // we are our own cgroup controller
+ scope_path = strjoina("");
+ else if (streq(m->cgroup_root, "/elogind"))
// root already is our cgroup
scope_path = strjoina(m->cgroup_root);
else
// we have to create our own group
scope_path = strjoina(m->cgroup_root, "/elogind");
- r = cg_create_and_attach(ELOGIND_CGROUP_CONTROLLER, scope_path, 0);
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
#endif // 0
if (r < 0)
return log_error_errno(r, "Failed to create %s control group: %m", scope_path);
/* also, move all other userspace processes remaining
* in the root cgroup into that scope. */
if (!streq(m->cgroup_root, scope_path)) {
- r = cg_migrate(ELOGIND_CGROUP_CONTROLLER, m->cgroup_root, ELOGIND_CGROUP_CONTROLLER, scope_path, false);
+ r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, false);
if (r < 0)
log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m");
}
/* We can't really delete the group, since we are in it. But
* let's trim it. */
if (delete && m->cgroup_root)
- (void) cg_trim(ELOGIND_CGROUP_CONTROLLER, m->cgroup_root, false);
+ (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false);
-/// elogind does not support the unified hierarchy, yet.
-#if 0
+#if 0 /// elogind does not support the unified hierarchy, yet.
m->cgroup_inotify_wd_unit = hashmap_free(m->cgroup_inotify_wd_unit);
m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
m->cgroup_root = mfree(m->cgroup_root);
}
-/// UNNEEDED by elogind
-#if 0
+#if 0 /// UNNEEDED by elogind
Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
char *p;
Unit *u;
if (pid <= 0)
return NULL;
- r = cg_pid_get_path(ELOGIND_CGROUP_CONTROLLER, pid, &cgroup);
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
if (r < 0)
return NULL;
return safe_atou64(v, ret);
}
+int unit_get_tasks_current(Unit *u, uint64_t *ret) {
+ _cleanup_free_ char *v = NULL;
+ int r;
+
+ assert(u);
+ assert(ret);
+
+ if (!u->cgroup_path)
+ return -ENODATA;
+
+ if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0)
+ return -ENODATA;
+
+ r = cg_get_attribute("pids", u->cgroup_path, "pids.current", &v);
+ if (r == -ENOENT)
+ return -ENODATA;
+ if (r < 0)
+ return r;
+
+ return safe_atou64(v, ret);
+}
+
static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
_cleanup_free_ char *v = NULL;
uint64_t ns;
return c->delegate;
}
-#endif // 0
+
+void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
+ assert(u);
+
+ if (!UNIT_HAS_CGROUP_CONTEXT(u))
+ return;
+
+ if (m == 0)
+ return;
+
+ if ((u->cgroup_realized_mask & m) == 0)
+ return;
+
+ u->cgroup_realized_mask &= ~m;
+ unit_add_to_cgroup_queue(u);
+}
+
+void manager_invalidate_startup_units(Manager *m) {
+ Iterator i;
+ Unit *u;
+
+ assert(m);
+
+ SET_FOREACH(u, m->startup_units, i)
+ unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_BLKIO);
+}
static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
[CGROUP_AUTO] = "auto",
};
DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
+#endif // 0