diff options
author | Lennart Poettering <lennart@poettering.net> | 2018-11-19 10:57:48 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-19 10:57:48 +0100 |
commit | 2b38a8ea80cdc64222bbd49ae374792f941aaf42 (patch) | |
tree | 5c37875abba4f9645d06e68183c26f85935a4818 /src/basic | |
parent | test: kill all processes launched by test-execute before exiting (diff) | |
parent | cgroup v2: DefaultCPUAccounting=yes if CPU controller isn't required (diff) | |
download | systemd-2b38a8ea80cdc64222bbd49ae374792f941aaf42.tar.xz systemd-2b38a8ea80cdc64222bbd49ae374792f941aaf42.zip |
Merge pull request #10507 from cdown/cpu_acct
cgroup v2: Don't require CPU controller for CPU accounting in 4.15+
Diffstat (limited to 'src/basic')
-rw-r--r-- | src/basic/cgroup-util.c | 52 | ||||
-rw-r--r-- | src/basic/cgroup-util.h | 3 |
2 files changed, 55 insertions, 0 deletions
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 0450850832..613801f2c5 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -12,6 +12,7 @@ #include <sys/stat.h> #include <sys/statfs.h> #include <sys/types.h> +#include <sys/utsname.h> #include <sys/xattr.h> #include <unistd.h> @@ -2822,3 +2823,54 @@ static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = { }; DEFINE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController); + +CGroupMask get_cpu_accounting_mask(void) { + static CGroupMask needed_mask = (CGroupMask) -1; + + /* On kernel ≥4.15 with unified hierarchy, cpu.stat's usage_usec is + * provided externally from the CPU controller, which means we don't + * need to enable the CPU controller just to get metrics. This is good, + * because enabling the CPU controller comes at a minor performance + * hit, especially when it's propagated deep into large hierarchies. + * There's also no separate CPU accounting controller available within + * a unified hierarchy. + * + * This combination of factors results in the desired cgroup mask to + * enable for CPU accounting varying as follows: + * + * ╔═════════════════════╤═════════════════════╗ + * ║ Linux ≥4.15 │ Linux <4.15 ║ + * ╔═══════════════╬═════════════════════╪═════════════════════╣ + * ║ Unified ║ nothing │ CGROUP_MASK_CPU ║ + * ╟───────────────╫─────────────────────┼─────────────────────╢ + * ║ Hybrid/Legacy ║ CGROUP_MASK_CPUACCT │ CGROUP_MASK_CPUACCT ║ + * ╚═══════════════╩═════════════════════╧═════════════════════╝ + * + * We check kernel version here instead of manually checking whether + * cpu.stat is present for every cgroup, as that check in itself would + * already be fairly expensive. + * + * Kernels where this patch has been backported will therefore have the + * CPU controller enabled unnecessarily. This is more expensive than + * necessary, but harmless. ☺️ + */ + + if (needed_mask == (CGroupMask) -1) { + if (cg_all_unified()) { + struct utsname u; + assert_se(uname(&u) >= 0); + + if (str_verscmp(u.release, "4.15") < 0) + needed_mask = CGROUP_MASK_CPU; + else + needed_mask = 0; + } else + needed_mask = CGROUP_MASK_CPUACCT; + } + + return needed_mask; +} + +bool cpu_accounting_is_cheap(void) { + return get_cpu_accounting_mask() == 0; +} diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 463a8dc84a..7919864df9 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -69,6 +69,9 @@ static inline CGroupMask CGROUP_MASK_EXTEND_JOINED(CGroupMask mask) { return mask; } +CGroupMask get_cpu_accounting_mask(void); +bool cpu_accounting_is_cheap(void); + /* Special values for all weight knobs on unified hierarchy */ #define CGROUP_WEIGHT_INVALID ((uint64_t) -1) #define CGROUP_WEIGHT_MIN UINT64_C(1) |