]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/slice.c
core: output unit status output strings to console, only if we actually are changing...
[thirdparty/systemd.git] / src / core / slice.c
CommitLineData
a016b922
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
23#include <signal.h>
24#include <unistd.h>
25
26#include "unit.h"
27#include "slice.h"
28#include "load-fragment.h"
29#include "log.h"
30#include "dbus-slice.h"
31#include "special.h"
32#include "unit-name.h"
33
34static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = {
35 [SLICE_DEAD] = UNIT_INACTIVE,
36 [SLICE_ACTIVE] = UNIT_ACTIVE
37};
38
39static void slice_set_state(Slice *t, SliceState state) {
40 SliceState old_state;
41 assert(t);
42
43 old_state = t->state;
44 t->state = state;
45
46 if (state != old_state)
47 log_debug("%s changed %s -> %s",
48 UNIT(t)->id,
49 slice_state_to_string(old_state),
50 slice_state_to_string(state));
51
52 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
53}
54
4ad49000 55static int slice_add_parent_slice(Slice *s) {
a016b922 56 char *a, *dash;
a016b922 57 Unit *parent;
4ad49000 58 int r;
a016b922
LP
59
60 assert(s);
61
4ad49000 62 if (UNIT_ISSET(UNIT(s)->slice))
a016b922
LP
63 return 0;
64
4ad49000 65 if (unit_has_name(UNIT(s), SPECIAL_ROOT_SLICE))
a016b922
LP
66 return 0;
67
4ad49000
LP
68 a = strdupa(UNIT(s)->id);
69 dash = strrchr(a, '-');
70 if (dash)
71 strcpy(dash, ".slice");
72 else
73 a = (char*) SPECIAL_ROOT_SLICE;
a016b922
LP
74
75 r = manager_load_unit(UNIT(s)->manager, a, NULL, NULL, &parent);
76 if (r < 0)
77 return r;
78
79 unit_ref_set(&UNIT(s)->slice, parent);
80 return 0;
81}
82
83static int slice_add_default_dependencies(Slice *s) {
84 int r;
85
86 assert(s);
87
88 /* Make sure slices are unloaded on shutdown */
6c12b52e
LP
89 r = unit_add_two_dependencies_by_name(
90 UNIT(s),
91 UNIT_BEFORE, UNIT_CONFLICTS,
92 SPECIAL_SHUTDOWN_TARGET, NULL, true);
a016b922
LP
93 if (r < 0)
94 return r;
95
96 return 0;
97}
98
99static int slice_verify(Slice *s) {
100 assert(s);
101
102 if (UNIT(s)->load_state != UNIT_LOADED)
103 return 0;
104
105 if (UNIT_DEREF(UNIT(s)->slice)) {
106 char *a, *dash;
107
108 a = strdupa(UNIT(s)->id);
109 dash = strrchr(a, '-');
4ad49000 110 if (dash)
a016b922 111 strcpy(dash, ".slice");
4ad49000
LP
112 else
113 a = (char*) SPECIAL_ROOT_SLICE;
a016b922 114
4ad49000 115 if (!unit_has_name(UNIT_DEREF(UNIT(s)->slice), a)) {
79008bdd 116 log_unit_error(UNIT(s)->id,
4ad49000
LP
117 "%s located outside its parent slice. Refusing.", UNIT(s)->id);
118 return -EINVAL;
a016b922
LP
119 }
120 }
121
122 return 0;
123}
124
125static int slice_load(Unit *u) {
126 Slice *s = SLICE(u);
127 int r;
128
129 assert(s);
130
4ad49000 131 r = unit_load_fragment_and_dropin_optional(u);
a016b922
LP
132 if (r < 0)
133 return r;
134
135 /* This is a new unit? Then let's add in some extras */
136 if (u->load_state == UNIT_LOADED) {
137
598459ce
LP
138 r = unit_patch_contexts(u);
139 if (r < 0)
140 return r;
141
4ad49000 142 r = slice_add_parent_slice(s);
a016b922
LP
143 if (r < 0)
144 return r;
145
146 if (u->default_dependencies) {
147 r = slice_add_default_dependencies(s);
148 if (r < 0)
149 return r;
150 }
a016b922
LP
151 }
152
153 return slice_verify(s);
154}
155
156static int slice_coldplug(Unit *u) {
157 Slice *t = SLICE(u);
158
159 assert(t);
160 assert(t->state == SLICE_DEAD);
161
162 if (t->deserialized_state != t->state)
163 slice_set_state(t, t->deserialized_state);
164
165 return 0;
166}
167
168static void slice_dump(Unit *u, FILE *f, const char *prefix) {
169 Slice *t = SLICE(u);
170
171 assert(t);
172 assert(f);
173
174 fprintf(f,
175 "%sSlice State: %s\n",
176 prefix, slice_state_to_string(t->state));
4ad49000
LP
177
178 cgroup_context_dump(&t->cgroup_context, f, prefix);
a016b922
LP
179}
180
181static int slice_start(Unit *u) {
182 Slice *t = SLICE(u);
a016b922
LP
183
184 assert(t);
185 assert(t->state == SLICE_DEAD);
186
4ad49000 187 unit_realize_cgroup(u);
a016b922
LP
188
189 slice_set_state(t, SLICE_ACTIVE);
82a2b6bb 190 return 1;
a016b922
LP
191}
192
193static int slice_stop(Unit *u) {
194 Slice *t = SLICE(u);
195
196 assert(t);
197 assert(t->state == SLICE_ACTIVE);
198
4ad49000
LP
199 /* We do not need to destroy the cgroup explicitly,
200 * unit_notify() will do that for us anyway. */
a016b922
LP
201
202 slice_set_state(t, SLICE_DEAD);
82a2b6bb 203 return 1;
a016b922
LP
204}
205
718db961 206static int slice_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
a016b922
LP
207 return unit_kill_common(u, who, signo, -1, -1, error);
208}
209
210static int slice_serialize(Unit *u, FILE *f, FDSet *fds) {
211 Slice *s = SLICE(u);
212
213 assert(s);
214 assert(f);
215 assert(fds);
216
217 unit_serialize_item(u, f, "state", slice_state_to_string(s->state));
218 return 0;
219}
220
221static int slice_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
222 Slice *s = SLICE(u);
223
224 assert(u);
225 assert(key);
226 assert(value);
227 assert(fds);
228
229 if (streq(key, "state")) {
230 SliceState state;
231
232 state = slice_state_from_string(value);
233 if (state < 0)
234 log_debug("Failed to parse state value %s", value);
235 else
236 s->deserialized_state = state;
237
238 } else
239 log_debug("Unknown serialization key '%s'", key);
240
241 return 0;
242}
243
244_pure_ static UnitActiveState slice_active_state(Unit *u) {
245 assert(u);
246
247 return state_translation_table[SLICE(u)->state];
248}
249
250_pure_ static const char *slice_sub_state_to_string(Unit *u) {
251 assert(u);
252
253 return slice_state_to_string(SLICE(u)->state);
254}
255
256static const char* const slice_state_table[_SLICE_STATE_MAX] = {
257 [SLICE_DEAD] = "dead",
258 [SLICE_ACTIVE] = "active"
259};
260
261DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
262
263const UnitVTable slice_vtable = {
264 .object_size = sizeof(Slice),
718db961
LP
265 .cgroup_context_offset = offsetof(Slice, cgroup_context),
266
a016b922
LP
267 .sections =
268 "Unit\0"
269 "Slice\0"
270 "Install\0",
4ad49000 271 .private_section = "Slice",
4ad49000 272
a016b922
LP
273 .no_alias = true,
274 .no_instances = true,
275
276 .load = slice_load,
4ad49000 277
a016b922
LP
278 .coldplug = slice_coldplug,
279
280 .dump = slice_dump,
281
282 .start = slice_start,
283 .stop = slice_stop,
284
285 .kill = slice_kill,
286
287 .serialize = slice_serialize,
288 .deserialize_item = slice_deserialize_item,
289
290 .active_state = slice_active_state,
291 .sub_state_to_string = slice_sub_state_to_string,
292
293 .bus_interface = "org.freedesktop.systemd1.Slice",
718db961 294 .bus_vtable = bus_slice_vtable,
8e2af478
LP
295 .bus_set_property = bus_slice_set_property,
296 .bus_commit_properties = bus_slice_commit_properties,
a016b922
LP
297
298 .status_message_formats = {
299 .finished_start_job = {
4ad49000 300 [JOB_DONE] = "Created slice %s.",
a016b922
LP
301 [JOB_DEPENDENCY] = "Dependency failed for %s.",
302 },
303 .finished_stop_job = {
4ad49000 304 [JOB_DONE] = "Removed slice %s.",
a016b922
LP
305 },
306 },
307};