***/
#include <errno.h>
-#include <signal.h>
-#include <unistd.h>
-#include "unit.h"
-#include "slice.h"
-#include "load-fragment.h"
-#include "log.h"
+#include "alloc-util.h"
#include "dbus-slice.h"
+#include "log.h"
+#include "slice.h"
#include "special.h"
+#include "string-util.h"
+#include "strv.h"
#include "unit-name.h"
+#include "unit.h"
static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = {
[SLICE_DEAD] = UNIT_INACTIVE,
[SLICE_ACTIVE] = UNIT_ACTIVE
};
-static void slice_init(Unit *u) {
- Slice *s = SLICE(u);
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- cgroup_context_init(&s->cgroup_context);
-}
-
-static void slice_done(Unit *u) {
- Slice *s = SLICE(u);
-
- assert(u);
-
- cgroup_context_done(&s->cgroup_context);
-}
-
static void slice_set_state(Slice *t, SliceState state) {
SliceState old_state;
assert(t);
assert(s);
+ if (!UNIT(s)->default_dependencies)
+ return 0;
+
/* Make sure slices are unloaded on shutdown */
- r = unit_add_dependency_by_name(UNIT(s), UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
+ r = unit_add_two_dependencies_by_name(
+ UNIT(s),
+ UNIT_BEFORE, UNIT_CONFLICTS,
+ SPECIAL_SHUTDOWN_TARGET, NULL, true);
if (r < 0)
return r;
}
static int slice_verify(Slice *s) {
+ _cleanup_free_ char *parent = NULL;
+ int r;
+
assert(s);
if (UNIT(s)->load_state != UNIT_LOADED)
return 0;
- if (UNIT_DEREF(UNIT(s)->slice)) {
- char *a, *dash;
+ 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;
+ }
- a = strdupa(UNIT(s)->id);
- dash = strrchr(a, '-');
- if (dash)
- strcpy(dash, ".slice");
- else
- a = (char*) SPECIAL_ROOT_SLICE;
+ r = slice_build_parent_slice(UNIT(s)->id, &parent);
+ if (r < 0)
+ return log_unit_error_errno(UNIT(s), r, "Failed to determine parent slice: %m");
- if (!unit_has_name(UNIT_DEREF(UNIT(s)->slice), a)) {
- log_error_unit(UNIT(s)->id,
- "%s located outside its parent slice. Refusing.", UNIT(s)->id);
- return -EINVAL;
- }
+ 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 0;
/* This is a new unit? Then let's add in some extras */
if (u->load_state == UNIT_LOADED) {
+ r = unit_patch_contexts(u);
+ if (r < 0)
+ return r;
+
r = slice_add_parent_slice(s);
if (r < 0)
return r;
- if (u->default_dependencies) {
- r = slice_add_default_dependencies(s);
- if (r < 0)
- return r;
- }
+ r = slice_add_default_dependencies(s);
+ if (r < 0)
+ return r;
}
return slice_verify(s);
assert(t);
assert(t->state == SLICE_DEAD);
- unit_realize_cgroup(u);
+ (void) unit_realize_cgroup(u);
+ (void) unit_reset_cpu_usage(u);
slice_set_state(t, SLICE_ACTIVE);
- return 0;
+ return 1;
}
static int slice_stop(Unit *u) {
* unit_notify() will do that for us anyway. */
slice_set_state(t, SLICE_DEAD);
- return 0;
+ return 1;
}
-static int slice_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int slice_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
return unit_kill_common(u, who, signo, -1, -1, error);
}
return slice_state_to_string(SLICE(u)->state);
}
-static const char* const slice_state_table[_SLICE_STATE_MAX] = {
- [SLICE_DEAD] = "dead",
- [SLICE_ACTIVE] = "active"
-};
+static void slice_enumerate(Manager *m) {
+ Unit *u;
+ int r;
+
+ assert(m);
-DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
+ u = manager_get_unit(m, SPECIAL_ROOT_SLICE);
+ 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 -.slice name");
+ return;
+ }
+ }
+
+ u->default_dependencies = false;
+ u->no_gc = true;
+ u->ignore_on_isolate = true;
+ u->refuse_manual_start = true;
+ u->refuse_manual_stop = true;
+ SLICE(u)->deserialized_state = SLICE_ACTIVE;
+
+ if (!u->description)
+ u->description = strdup("Root Slice");
+ if (!u->documentation)
+ (void) strv_extend(&u->documentation, "man:systemd.special(7)");
+
+ unit_add_to_load_queue(u);
+ unit_add_to_dbus_queue(u);
+}
const UnitVTable slice_vtable = {
.object_size = sizeof(Slice),
+ .cgroup_context_offset = offsetof(Slice, cgroup_context),
+
.sections =
"Unit\0"
"Slice\0"
"Install\0",
-
.private_section = "Slice",
- .cgroup_context_offset = offsetof(Slice, cgroup_context),
.no_alias = true,
.no_instances = true,
+ .can_transient = true,
- .init = slice_init,
.load = slice_load,
- .done = slice_done,
.coldplug = slice_coldplug,
.active_state = slice_active_state,
.sub_state_to_string = slice_sub_state_to_string,
- .bus_interface = "org.freedesktop.systemd1.Slice",
- .bus_message_handler = bus_slice_message_handler,
+ .bus_vtable = bus_slice_vtable,
+ .bus_set_property = bus_slice_set_property,
+ .bus_commit_properties = bus_slice_commit_properties,
+
+ .enumerate = slice_enumerate,
.status_message_formats = {
.finished_start_job = {
[JOB_DONE] = "Created slice %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
},
.finished_stop_job = {
[JOB_DONE] = "Removed slice %s.",