]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cgtop: tweak root cgroup detection a bit
authorLennart Poettering <lennart@poettering.net>
Fri, 9 Feb 2018 16:25:30 +0000 (17:25 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 9 Feb 2018 16:31:55 +0000 (17:31 +0100)
Inside a cgroup-namespaced container we shouldn't assume that "/" is
really the root cgroup, because it generally is not.

src/cgtop/cgtop.c

index 4e406e4ad252b5e7efd6365be7814a7265b42021..27e713fd931cf16b8009294c8db7c489795c1745 100644 (file)
@@ -46,6 +46,7 @@
 #include "terminal-util.h"
 #include "unit-name.h"
 #include "util.h"
+#include "virt.h"
 
 typedef struct Group {
         char *path;
@@ -126,6 +127,26 @@ static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, uint64
 }
 
 static bool is_root_cgroup(const char *path) {
+
+        /* Returns true if the specified path belongs to the root cgroup. The root cgroup is special on cgroupsv2 as it
+         * carries only very few attributes in order not to export multiple truth about system state as most
+         * information is available elsewhere in /proc anyway. We need to be able to deal with that, and need to get
+         * our data from different sources in that case.
+         *
+         * There's one extra complication in all of this, though ðŸ˜£: if the path to the cgroup indicates we are in the
+         * root cgroup this might actually not be the case, because cgroup namespacing might be in effect
+         * (CLONE_NEWCGROUP). Since there's no nice way to distuingish a real cgroup root from a fake namespaced one we
+         * do an explicit container check here, under the assumption that CLONE_NEWCGROUP is generally used when
+         * container managers are used too.
+         *
+         * Note that checking for a container environment is kinda ugly, since in theory people could use cgtop from
+         * inside a container where cgroup namespacing is turned off to watch the host system. However, that's mostly a
+         * theoretic usecase, and if people actually try all they'll lose is accounting for the top-level cgroup. Which
+         * isn't too bad. */
+
+        if (detect_container() > 0)
+                return false;
+
         return isempty(path) || path_equal(path, "/");
 }
 
@@ -176,7 +197,8 @@ static int process(
                 }
         }
 
-        if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES)) {
+        if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) &&
+            IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES)) {
                 _cleanup_fclose_ FILE *f = NULL;
                 pid_t pid;