]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: turn on memory/cpu/tasks accounting by default for the root slice
authorLennart Poettering <lennart@poettering.net>
Fri, 9 Feb 2018 18:07:01 +0000 (19:07 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 9 Feb 2018 18:07:39 +0000 (19:07 +0100)
The kernel exposes the necessary data in /proc anyway, let's expose it
hence by default.

With this in place "systemctl status -- -.slice" will show accounting
data out-of-the-box now.

src/core/cgroup.c
src/core/cgroup.h
src/core/slice.c

index 924285de82706e08d1040a6d6a6912521e7ece84..0527996c28548f35702a585fbc6fe12bc55e79f3 100644 (file)
 #include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "virt.h"
 
 #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
 
+bool manager_owns_root_cgroup(Manager *m) {
+        assert(m);
+
+        /* Returns true if we are managing the root cgroup. Note that it isn't sufficient to just check whether the
+         * group root path equals "/" since that will also be the case if CLONE_NEWCGROUP is in the mix. Since there's
+         * appears to be no nice way to detect whether we are in a CLONE_NEWCGROUP namespace we instead just check if
+         * we run in any kind of container virtualization. */
+
+        if (detect_container() > 0)
+                return false;
+
+        return isempty(m->cgroup_root) || path_equal(m->cgroup_root, "/");
+}
+
 bool unit_has_root_cgroup(Unit *u) {
         assert(u);
 
-        /* Returns whether this unit manages the root cgroup. Note that this is different from being named "-.slice",
-         * as inside of containers the root slice won't be identical to the root cgroup. */
+        /* Returns whether this unit manages the root cgroup. This will return true if this unit is the root slice and
+         * the manager manages the root cgroup. */
 
-        if (!u->cgroup_path)
+        if (!manager_owns_root_cgroup(u->manager))
                 return false;
 
-        return isempty(u->cgroup_path) || path_equal(u->cgroup_path, "/");
+        return unit_has_name(u, SPECIAL_ROOT_SLICE);
 }
 
 static void cgroup_compat_warn(void) {
@@ -58,7 +73,9 @@ static void cgroup_compat_warn(void) {
         if (cgroup_compat_warned)
                 return;
 
-        log_warning("cgroup compatibility translation between legacy and unified hierarchy settings activated. See cgroup-compat debug messages for details.");
+        log_warning("cgroup compatibility translation between legacy and unified hierarchy settings activated. "
+                    "See cgroup-compat debug messages for details.");
+
         cgroup_compat_warned = true;
 }
 
index 1f504414126ef23d5df9871e76b92692cbb994c4..bc8a6951c978789e40295ebce79e72312608a03a 100644 (file)
@@ -208,6 +208,7 @@ int unit_reset_ip_accounting(Unit *u);
         cc ? cc->name : false;                          \
         })
 
+bool manager_owns_root_cgroup(Manager *m);
 bool unit_has_root_cgroup(Unit *u);
 
 int manager_notify_cgroup_empty(Manager *m, const char *group);
index ef2177279a1539b5386c4d7252cbe31857563090..9cb828cae129298a0a883d0e60f62fe8dc7c6405 100644 (file)
@@ -313,19 +313,18 @@ _pure_ static const char *slice_sub_state_to_string(Unit *u) {
         return slice_state_to_string(SLICE(u)->state);
 }
 
-static void slice_enumerate_perpetual(Manager *m, const char *name) {
+static int slice_make_perpetual(Manager *m, const char *name, Unit **ret) {
         Unit *u;
         int r;
 
         assert(m);
+        assert(name);
 
         u = manager_get_unit(m, name);
         if (!u) {
                 r = unit_new_for_name(m, sizeof(Slice), name, &u);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to allocate the special %s unit: %m", name);
-                        return;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Failed to allocate the special %s unit: %m", name);
         }
 
         u->perpetual = true;
@@ -333,15 +332,34 @@ static void slice_enumerate_perpetual(Manager *m, const char *name) {
 
         unit_add_to_load_queue(u);
         unit_add_to_dbus_queue(u);
+
+        if (ret)
+                *ret = u;
+
+        return 0;
 }
 
 static void slice_enumerate(Manager *m) {
+        Unit *u;
+        int r;
+
         assert(m);
 
-        slice_enumerate_perpetual(m, SPECIAL_ROOT_SLICE);
+        r = slice_make_perpetual(m, SPECIAL_ROOT_SLICE, &u);
+        if (r >= 0 && manager_owns_root_cgroup(m)) {
+                Slice *s = SLICE(u);
+
+                /* If we are managing the root cgroup then this means our root slice covers the whole system, which
+                 * means the kernel will track CPU/tasks/memory for us anyway, and it is all available in /proc. Let's
+                 * hence turn accounting on here, so that our APIs to query this data are available. */
+
+                s->cgroup_context.cpu_accounting = true;
+                s->cgroup_context.tasks_accounting = true;
+                s->cgroup_context.memory_accounting = true;
+        }
 
         if (MANAGER_IS_SYSTEM(m))
-                slice_enumerate_perpetual(m, SPECIAL_SYSTEM_SLICE);
+                (void) slice_make_perpetual(m, SPECIAL_SYSTEM_SLICE, NULL);
 }
 
 const UnitVTable slice_vtable = {