]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/slice.c
tree-wide: drop 'This file is part of systemd' blurb
[thirdparty/systemd.git] / src / core / slice.c
index 0fef29661fa3ea54fbd5aadc697d4c7fb807cd20..88fbe5e6fd5e94870454f78a18c045af067bb9bf 100644 (file)
@@ -1,20 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
-  This file is part of systemd.
-
   Copyright 2013 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
 #include <errno.h>
@@ -54,34 +40,28 @@ static void slice_set_state(Slice *t, SliceState state) {
                           slice_state_to_string(old_state),
                           slice_state_to_string(state));
 
-        unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
+        unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
 }
 
 static int slice_add_parent_slice(Slice *s) {
-        char *a, *dash;
-        Unit *parent;
+        Unit *u = UNIT(s), *parent;
+        _cleanup_free_ char *a = NULL;
         int r;
 
         assert(s);
 
-        if (UNIT_ISSET(UNIT(s)->slice))
-                return 0;
-
-        if (unit_has_name(UNIT(s), SPECIAL_ROOT_SLICE))
+        if (UNIT_ISSET(u->slice))
                 return 0;
 
-        a = strdupa(UNIT(s)->id);
-        dash = strrchr(a, '-');
-        if (dash)
-                strcpy(dash, ".slice");
-        else
-                a = (char*) SPECIAL_ROOT_SLICE;
+        r = slice_build_parent_slice(u->id, &a);
+        if (r <= 0) /* 0 means root slice */
+                return r;
 
-        r = manager_load_unit(UNIT(s)->manager, a, NULL, NULL, &parent);
+        r = manager_load_unit(u->manager, a, NULL, NULL, &parent);
         if (r < 0)
                 return r;
 
-        unit_ref_set(&UNIT(s)->slice, parent);
+        unit_ref_set(&u->slice, u, parent);
         return 0;
 }
 
@@ -97,7 +77,7 @@ static int slice_add_default_dependencies(Slice *s) {
         r = unit_add_two_dependencies_by_name(
                         UNIT(s),
                         UNIT_BEFORE, UNIT_CONFLICTS,
-                        SPECIAL_SHUTDOWN_TARGET, NULL, true);
+                        SPECIAL_SHUTDOWN_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
         if (r < 0)
                 return r;
 
@@ -115,7 +95,7 @@ static int slice_verify(Slice *s) {
 
         if (!slice_name_is_valid(UNIT(s)->id)) {
                 log_unit_error(UNIT(s), "Slice name %s is not valid. Refusing.", UNIT(s)->id);
-                return -EINVAL;
+                return -ENOEXEC;
         }
 
         r = slice_build_parent_slice(UNIT(s)->id, &parent);
@@ -124,7 +104,7 @@ static int slice_verify(Slice *s) {
 
         if (parent ? !unit_has_name(UNIT_DEREF(UNIT(s)->slice), parent) : UNIT_ISSET(UNIT(s)->slice)) {
                 log_unit_error(UNIT(s), "Located outside of parent slice. Refusing.");
-                return -EINVAL;
+                return -ENOEXEC;
         }
 
         return 0;
@@ -136,15 +116,12 @@ static int slice_load_root_slice(Unit *u) {
         if (!unit_has_name(u, SPECIAL_ROOT_SLICE))
                 return 0;
 
-        u->no_gc = true;
+        u->perpetual = true;
 
         /* The root slice is a bit special. For example it is always running and cannot be terminated. Because of its
          * special semantics we synthesize it here, instead of relying on the unit file on disk. */
 
         u->default_dependencies = false;
-        u->ignore_on_isolate = true;
-        u->refuse_manual_start = true;
-        u->refuse_manual_stop = true;
 
         if (!u->description)
                 u->description = strdup("Root Slice");
@@ -154,6 +131,29 @@ static int slice_load_root_slice(Unit *u) {
         return 1;
 }
 
+static int slice_load_system_slice(Unit *u) {
+        assert(u);
+
+        if (!MANAGER_IS_SYSTEM(u->manager))
+                return 0;
+        if (!unit_has_name(u, SPECIAL_SYSTEM_SLICE))
+                return 0;
+
+        u->perpetual = true;
+
+        /* The system slice is a bit special. For example it is always running and cannot be terminated. Because of its
+         * special semantics we synthesize it here, instead of relying on the unit file on disk. */
+
+        u->default_dependencies = false;
+
+        if (!u->description)
+                u->description = strdup("System Slice");
+        if (!u->documentation)
+                u->documentation = strv_new("man:systemd.special(7)", NULL);
+
+        return 1;
+}
+
 static int slice_load(Unit *u) {
         Slice *s = SLICE(u);
         int r;
@@ -164,6 +164,10 @@ static int slice_load(Unit *u) {
         r = slice_load_root_slice(u);
         if (r < 0)
                 return r;
+        r = slice_load_system_slice(u);
+        if (r < 0)
+                return r;
+
         r = unit_load_fragment_and_dropin_optional(u);
         if (r < 0)
                 return r;
@@ -224,7 +228,8 @@ static int slice_start(Unit *u) {
                 return r;
 
         (void) unit_realize_cgroup(u);
-        (void) unit_reset_cpu_usage(u);
+        (void) unit_reset_cpu_accounting(u);
+        (void) unit_reset_ip_accounting(u);
 
         slice_set_state(t, SLICE_ACTIVE);
         return 1;
@@ -293,33 +298,53 @@ _pure_ static const char *slice_sub_state_to_string(Unit *u) {
         return slice_state_to_string(SLICE(u)->state);
 }
 
-static void slice_enumerate(Manager *m) {
+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, SPECIAL_ROOT_SLICE);
+        u = manager_get_unit(m, name);
         if (!u) {
-                u = unit_new(m, sizeof(Slice));
-                if (!u)  {
-                        log_oom();
-                        return;
-                }
-
-                r = unit_add_name(u, SPECIAL_ROOT_SLICE);
-                if (r < 0) {
-                        unit_free(u);
-                        log_error_errno(r, "Failed to add the "SPECIAL_ROOT_SLICE " name: %m");
-                        return;
-                }
+                r = unit_new_for_name(m, sizeof(Slice), name, &u);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to allocate the special %s unit: %m", name);
         }
 
-        u->no_gc = true;
+        u->perpetual = true;
         SLICE(u)->deserialized_state = SLICE_ACTIVE;
 
         unit_add_to_load_queue(u);
         unit_add_to_dbus_queue(u);
+
+        if (ret)
+                *ret = u;
+
+        return 0;
+}
+
+static void slice_enumerate_perpetual(Manager *m) {
+        Unit *u;
+        int r;
+
+        assert(m);
+
+        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))
+                (void) slice_make_perpetual(m, SPECIAL_SYSTEM_SLICE, NULL);
 }
 
 const UnitVTable slice_vtable = {
@@ -356,7 +381,7 @@ const UnitVTable slice_vtable = {
         .bus_set_property = bus_slice_set_property,
         .bus_commit_properties = bus_slice_commit_properties,
 
-        .enumerate = slice_enumerate,
+        .enumerate_perpetual = slice_enumerate_perpetual,
 
         .status_message_formats = {
                 .finished_start_job = {