]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/target.c
Merge pull request #31648 from neighbourhoodie/review-content
[thirdparty/systemd.git] / src / core / target.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
a7334b09 2
4139c1b2 3#include "dbus-target.h"
6fcbec6f 4#include "dbus-unit.h"
07630cea 5#include "log.h"
d68c645b 6#include "serialize.h"
514f4ef5 7#include "special.h"
07630cea 8#include "string-util.h"
d68c645b 9#include "target.h"
b2bb3dbe 10#include "unit-name.h"
07630cea 11#include "unit.h"
c22cbe26 12
fa068367 13static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = {
17f6b640
YW
14 [TARGET_DEAD] = UNIT_INACTIVE,
15 [TARGET_ACTIVE] = UNIT_ACTIVE,
fa068367
LP
16};
17
fa068367
LP
18static void target_set_state(Target *t, TargetState state) {
19 TargetState old_state;
b7e4e152 20
fa068367
LP
21 assert(t);
22
6fcbec6f
LP
23 if (t->state != state)
24 bus_unit_send_pending_change_signal(UNIT(t), false);
25
fa068367
LP
26 old_state = t->state;
27 t->state = state;
28
e537352b 29 if (state != old_state)
b7e4e152
MY
30 log_unit_debug(UNIT(t), "Changed %s -> %s",
31 target_state_to_string(old_state), target_state_to_string(state));
c22cbe26 32
96b09de5 33 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], /* reload_success = */ true);
fa068367
LP
34}
35
a40eb732 36static int target_add_default_dependencies(Target *t) {
15ed3c3a
LP
37 _cleanup_free_ Unit **others = NULL;
38 int r, n_others;
bba34eed 39
98bc2000 40 assert(t);
a40eb732 41
41c237af
IP
42 if (!UNIT(t)->default_dependencies)
43 return 0;
44
15ed3c3a
LP
45 /* Imply ordering for requirement dependencies on target units. Note that when the user created a
46 * contradicting ordering manually we won't add anything in here to make sure we don't create a
47 * loop.
48 *
49 * Note that quite likely iterating through these dependencies will add new dependencies, which
50 * conflicts with the hashmap-based iteration logic. Hence, instead of iterating through the
51 * dependencies and acting on them as we go, first take an "atomic snapshot" of sorts and iterate
52 * through that. */
53
54 n_others = unit_get_dependency_array(UNIT(t), UNIT_ATOM_ADD_DEFAULT_TARGET_DEPENDENCY_QUEUE, &others);
55 if (n_others < 0)
56 return n_others;
57
8b317c34
MY
58 FOREACH_ARRAY(i, others, n_others) {
59 r = unit_add_default_target_dependency(*i, UNIT(t));
15ed3c3a
LP
60 if (r < 0)
61 return r;
eef85c4a 62 }
bba34eed 63
33e28180
LP
64 if (unit_has_name(UNIT(t), SPECIAL_SHUTDOWN_TARGET))
65 return 0;
66
b401e1fb 67 /* Make sure targets are unloaded on shutdown */
3835b9aa 68 return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
a40eb732
LP
69}
70
71static int target_load(Unit *u) {
e9fa1bf7 72 Target *t = ASSERT_PTR(TARGET(u));
a40eb732
LP
73 int r;
74
c3620770 75 r = unit_load_fragment_and_dropin(u, true);
1850161f 76 if (r < 0)
a40eb732
LP
77 return r;
78
75193d41
ZJS
79 if (u->load_state != UNIT_LOADED)
80 return 0;
a40eb732 81
75193d41
ZJS
82 /* This is a new unit? Then let's add in some extras */
83 return target_add_default_dependencies(t);
a40eb732
LP
84}
85
be847e82 86static int target_coldplug(Unit *u) {
e9fa1bf7 87 Target *t = ASSERT_PTR(TARGET(u));
a16e1123 88
a16e1123
LP
89 assert(t->state == TARGET_DEAD);
90
91 if (t->deserialized_state != t->state)
92 target_set_state(t, t->deserialized_state);
93
94 return 0;
95}
96
97static void target_dump(Unit *u, FILE *f, const char *prefix) {
e9fa1bf7 98 Target *t = ASSERT_PTR(TARGET(u));
a16e1123 99
a16e1123 100 assert(f);
e9fa1bf7 101 assert(prefix);
a16e1123
LP
102
103 fprintf(f,
104 "%sTarget State: %s\n",
105 prefix, target_state_to_string(t->state));
106}
107
fa068367 108static int target_start(Unit *u) {
e9fa1bf7 109 Target *t = ASSERT_PTR(TARGET(u));
4b58153d 110 int r;
fa068367 111
fa068367
LP
112 assert(t->state == TARGET_DEAD);
113
4b58153d
LP
114 r = unit_acquire_invocation_id(u);
115 if (r < 0)
116 return r;
117
fa068367 118 target_set_state(t, TARGET_ACTIVE);
82a2b6bb 119 return 1;
fa068367 120}
c22cbe26 121
fa068367 122static int target_stop(Unit *u) {
e9fa1bf7 123 Target *t = ASSERT_PTR(TARGET(u));
fa068367 124
fa068367
LP
125 assert(t->state == TARGET_ACTIVE);
126
127 target_set_state(t, TARGET_DEAD);
82a2b6bb 128 return 1;
c22cbe26
LP
129}
130
a16e1123 131static int target_serialize(Unit *u, FILE *f, FDSet *fds) {
e9fa1bf7 132 Target *t = ASSERT_PTR(TARGET(u));
a16e1123 133
a16e1123
LP
134 assert(f);
135 assert(fds);
136
e9fa1bf7 137 (void) serialize_item(f, "state", target_state_to_string(t->state));
a16e1123
LP
138 return 0;
139}
140
141static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
e9fa1bf7 142 Target *t = ASSERT_PTR(TARGET(u));
a16e1123 143
a16e1123
LP
144 assert(key);
145 assert(value);
146 assert(fds);
147
148 if (streq(key, "state")) {
149 TargetState state;
150
1850161f
LP
151 state = target_state_from_string(value);
152 if (state < 0)
e9fa1bf7 153 log_unit_debug(u, "Failed to parse state: %s", value);
a16e1123 154 else
e9fa1bf7 155 t->deserialized_state = state;
a16e1123
LP
156
157 } else
e9fa1bf7 158 log_unit_debug(u, "Unknown serialization key: %s", key);
a16e1123
LP
159
160 return 0;
161}
162
d1e8e8b5 163static UnitActiveState target_active_state(Unit *u) {
e9fa1bf7 164 Target *t = ASSERT_PTR(TARGET(u));
fa068367 165
e9fa1bf7 166 return state_translation_table[t->state];
c22cbe26
LP
167}
168
d1e8e8b5 169static const char *target_sub_state_to_string(Unit *u) {
e9fa1bf7 170 Target *t = ASSERT_PTR(TARGET(u));
10a94420 171
e9fa1bf7 172 return target_state_to_string(t->state);
10a94420
LP
173}
174
87f0e418 175const UnitVTable target_vtable = {
7d17cfbc 176 .object_size = sizeof(Target),
718db961 177
f975e971
LP
178 .sections =
179 "Unit\0"
180 "Target\0"
181 "Install\0",
c22cbe26 182
94d1ddbd
ZJS
183 .can_fail = true,
184
a40eb732 185 .load = target_load,
a16e1123 186 .coldplug = target_coldplug,
fa068367
LP
187
188 .dump = target_dump,
189
190 .start = target_start,
191 .stop = target_stop,
c22cbe26 192
a16e1123
LP
193 .serialize = target_serialize,
194 .deserialize_item = target_deserialize_item,
195
10a94420 196 .active_state = target_active_state,
4139c1b2
LP
197 .sub_state_to_string = target_sub_state_to_string,
198
c6918296
MS
199 .status_message_formats = {
200 .finished_start_job = {
201 [JOB_DONE] = "Reached target %s.",
c6918296
MS
202 },
203 .finished_stop_job = {
204 [JOB_DONE] = "Stopped target %s.",
205 },
206 },
b2d6bb5b
LP
207
208 .notify_supervisor = true,
c22cbe26 209};