diff options
author | Lennart Poettering <lennart@poettering.net> | 2015-09-10 12:32:16 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2015-09-10 18:41:06 +0200 |
commit | 03a7b521e3ffb7f5d153d90480ba5d4bc29d1e8f (patch) | |
tree | d18052ac68aae77bcce3813e64bf1f956cc9ad7d /src/core/cgroup.c | |
parent | 15af581253a3f25a71d4fa723bf1fdd22f842728 (diff) |
core: add support for the "pids" cgroup controller
This adds support for the new "pids" cgroup controller of 4.3 kernels.
It allows accounting the number of tasks in a cgroup and enforcing
limits on it.
This adds two new setting TasksAccounting= and TasksMax= to each unit,
as well as a gloabl option DefaultTasksAccounting=.
This also updated "cgtop" to optionally make use of the new
kernel-provided accounting.
systemctl has been updated to show the number of tasks for each service
if it is available.
This patch also adds correct support for undoing memory limits for units
using a MemoryLimit=infinity syntax. We do the same for TasksMax= now
and hence keep things in sync here.
Diffstat (limited to 'src/core/cgroup.c')
-rw-r--r-- | src/core/cgroup.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c index baa7cc5488..48000d4e6e 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -22,10 +22,11 @@ #include <fcntl.h> #include <fnmatch.h> -#include "process-util.h" +#include "cgroup-util.h" #include "path-util.h" +#include "process-util.h" #include "special.h" -#include "cgroup-util.h" + #include "cgroup.h" #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC) @@ -41,6 +42,7 @@ void cgroup_context_init(CGroupContext *c) { c->memory_limit = (uint64_t) -1; c->blockio_weight = (unsigned long) -1; c->startup_blockio_weight = (unsigned long) -1; + c->tasks_max = (uint64_t) -1; c->cpu_quota_per_sec_usec = USEC_INFINITY; } @@ -106,6 +108,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { "%sBlockIOWeight=%lu\n" "%sStartupBlockIOWeight=%lu\n" "%sMemoryLimit=%" PRIu64 "\n" + "%sTasksMax=%" PRIu64 "\n" "%sDevicePolicy=%s\n" "%sDelegate=%s\n", prefix, yes_no(c->cpu_accounting), @@ -117,6 +120,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { 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)); @@ -466,6 +470,21 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M 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) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to set pids.max on %s: %m", path); + } } CGroupMask cgroup_context_get_mask(CGroupContext *c) { @@ -494,6 +513,10 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) { c->device_policy != CGROUP_AUTO) mask |= CGROUP_MASK_DEVICES; + if (c->tasks_accounting || + c->tasks_max != (uint64_t) -1) + mask |= CGROUP_MASK_PIDS; + return mask; } @@ -1459,6 +1482,28 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) { 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; |