]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/job.c
Merge pull request #10087 from keszybz/xnox/fix-test-functions
[thirdparty/systemd.git] / src / core / job.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4
5 #include "sd-id128.h"
6 #include "sd-messages.h"
7
8 #include "alloc-util.h"
9 #include "async.h"
10 #include "dbus-job.h"
11 #include "dbus.h"
12 #include "escape.h"
13 #include "job.h"
14 #include "log.h"
15 #include "macro.h"
16 #include "parse-util.h"
17 #include "set.h"
18 #include "special.h"
19 #include "stdio-util.h"
20 #include "string-table.h"
21 #include "string-util.h"
22 #include "strv.h"
23 #include "terminal-util.h"
24 #include "unit.h"
25 #include "virt.h"
26
27 Job* job_new_raw(Unit *unit) {
28 Job *j;
29
30 /* used for deserialization */
31
32 assert(unit);
33
34 j = new0(Job, 1);
35 if (!j)
36 return NULL;
37
38 j->manager = unit->manager;
39 j->unit = unit;
40 j->type = _JOB_TYPE_INVALID;
41 j->reloaded = false;
42
43 return j;
44 }
45
46 Job* job_new(Unit *unit, JobType type) {
47 Job *j;
48
49 assert(type < _JOB_TYPE_MAX);
50
51 j = job_new_raw(unit);
52 if (!j)
53 return NULL;
54
55 j->id = j->manager->current_job_id++;
56 j->type = type;
57
58 /* We don't link it here, that's what job_dependency() is for */
59
60 return j;
61 }
62
63 void job_unlink(Job *j) {
64 assert(j);
65 assert(!j->installed);
66 assert(!j->transaction_prev);
67 assert(!j->transaction_next);
68 assert(!j->subject_list);
69 assert(!j->object_list);
70
71 if (j->in_run_queue) {
72 LIST_REMOVE(run_queue, j->manager->run_queue, j);
73 j->in_run_queue = false;
74 }
75
76 if (j->in_dbus_queue) {
77 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
78 j->in_dbus_queue = false;
79 }
80
81 if (j->in_gc_queue) {
82 LIST_REMOVE(gc_queue, j->manager->gc_job_queue, j);
83 j->in_gc_queue = false;
84 }
85
86 j->timer_event_source = sd_event_source_unref(j->timer_event_source);
87 }
88
89 void job_free(Job *j) {
90 assert(j);
91 assert(!j->installed);
92 assert(!j->transaction_prev);
93 assert(!j->transaction_next);
94 assert(!j->subject_list);
95 assert(!j->object_list);
96
97 job_unlink(j);
98
99 sd_bus_track_unref(j->bus_track);
100 strv_free(j->deserialized_clients);
101
102 free(j);
103 }
104
105 static void job_set_state(Job *j, JobState state) {
106 assert(j);
107 assert(state >= 0);
108 assert(state < _JOB_STATE_MAX);
109
110 if (j->state == state)
111 return;
112
113 j->state = state;
114
115 if (!j->installed)
116 return;
117
118 if (j->state == JOB_RUNNING)
119 j->unit->manager->n_running_jobs++;
120 else {
121 assert(j->state == JOB_WAITING);
122 assert(j->unit->manager->n_running_jobs > 0);
123
124 j->unit->manager->n_running_jobs--;
125
126 if (j->unit->manager->n_running_jobs <= 0)
127 j->unit->manager->jobs_in_progress_event_source = sd_event_source_unref(j->unit->manager->jobs_in_progress_event_source);
128 }
129 }
130
131 void job_uninstall(Job *j) {
132 Job **pj;
133
134 assert(j->installed);
135
136 job_set_state(j, JOB_WAITING);
137
138 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
139 assert(*pj == j);
140
141 /* Detach from next 'bigger' objects */
142
143 /* daemon-reload should be transparent to job observers */
144 if (!MANAGER_IS_RELOADING(j->manager))
145 bus_job_send_removed_signal(j);
146
147 *pj = NULL;
148
149 unit_add_to_gc_queue(j->unit);
150
151 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
152 j->installed = false;
153 }
154
155 static bool job_type_allows_late_merge(JobType t) {
156 /* Tells whether it is OK to merge a job of type 't' with an already
157 * running job.
158 * Reloads cannot be merged this way. Think of the sequence:
159 * 1. Reload of a daemon is in progress; the daemon has already loaded
160 * its config file, but hasn't completed the reload operation yet.
161 * 2. Edit foo's config file.
162 * 3. Trigger another reload to have the daemon use the new config.
163 * Should the second reload job be merged into the first one, the daemon
164 * would not know about the new config.
165 * JOB_RESTART jobs on the other hand can be merged, because they get
166 * patched into JOB_START after stopping the unit. So if we see a
167 * JOB_RESTART running, it means the unit hasn't stopped yet and at
168 * this time the merge is still allowed. */
169 return t != JOB_RELOAD;
170 }
171
172 static void job_merge_into_installed(Job *j, Job *other) {
173 assert(j->installed);
174 assert(j->unit == other->unit);
175
176 if (j->type != JOB_NOP)
177 assert_se(job_type_merge_and_collapse(&j->type, other->type, j->unit) == 0);
178 else
179 assert(other->type == JOB_NOP);
180
181 j->irreversible = j->irreversible || other->irreversible;
182 j->ignore_order = j->ignore_order || other->ignore_order;
183 }
184
185 Job* job_install(Job *j) {
186 Job **pj;
187 Job *uj;
188
189 assert(!j->installed);
190 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
191 assert(j->state == JOB_WAITING);
192
193 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
194 uj = *pj;
195
196 if (uj) {
197 if (job_type_is_conflicting(uj->type, j->type))
198 job_finish_and_invalidate(uj, JOB_CANCELED, false, false);
199 else {
200 /* not conflicting, i.e. mergeable */
201
202 if (uj->state == JOB_WAITING ||
203 (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
204 job_merge_into_installed(uj, j);
205 log_unit_debug(uj->unit,
206 "Merged into installed job %s/%s as %u",
207 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
208 return uj;
209 } else {
210 /* already running and not safe to merge into */
211 /* Patch uj to become a merged job and re-run it. */
212 /* XXX It should be safer to queue j to run after uj finishes, but it is
213 * not currently possible to have more than one installed job per unit. */
214 job_merge_into_installed(uj, j);
215 log_unit_debug(uj->unit,
216 "Merged into running job, re-running: %s/%s as %u",
217 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
218
219 job_set_state(uj, JOB_WAITING);
220 return uj;
221 }
222 }
223 }
224
225 /* Install the job */
226 *pj = j;
227 j->installed = true;
228
229 j->manager->n_installed_jobs++;
230 log_unit_debug(j->unit,
231 "Installed new job %s/%s as %u",
232 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
233
234 job_add_to_gc_queue(j);
235
236 return j;
237 }
238
239 int job_install_deserialized(Job *j) {
240 Job **pj;
241
242 assert(!j->installed);
243
244 if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
245 log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
246 return -EINVAL;
247 }
248
249 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
250 if (*pj) {
251 log_unit_debug(j->unit, "Unit already has a job installed. Not installing deserialized job.");
252 return -EEXIST;
253 }
254
255 *pj = j;
256 j->installed = true;
257 j->reloaded = true;
258
259 if (j->state == JOB_RUNNING)
260 j->unit->manager->n_running_jobs++;
261
262 log_unit_debug(j->unit,
263 "Reinstalled deserialized job %s/%s as %u",
264 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
265 return 0;
266 }
267
268 JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
269 JobDependency *l;
270
271 assert(object);
272
273 /* Adds a new job link, which encodes that the 'subject' job
274 * needs the 'object' job in some way. If 'subject' is NULL
275 * this means the 'anchor' job (i.e. the one the user
276 * explicitly asked for) is the requester. */
277
278 l = new0(JobDependency, 1);
279 if (!l)
280 return NULL;
281
282 l->subject = subject;
283 l->object = object;
284 l->matters = matters;
285 l->conflicts = conflicts;
286
287 if (subject)
288 LIST_PREPEND(subject, subject->subject_list, l);
289
290 LIST_PREPEND(object, object->object_list, l);
291
292 return l;
293 }
294
295 void job_dependency_free(JobDependency *l) {
296 assert(l);
297
298 if (l->subject)
299 LIST_REMOVE(subject, l->subject->subject_list, l);
300
301 LIST_REMOVE(object, l->object->object_list, l);
302
303 free(l);
304 }
305
306 void job_dump(Job *j, FILE*f, const char *prefix) {
307 assert(j);
308 assert(f);
309
310 prefix = strempty(prefix);
311
312 fprintf(f,
313 "%s-> Job %u:\n"
314 "%s\tAction: %s -> %s\n"
315 "%s\tState: %s\n"
316 "%s\tIrreversible: %s\n"
317 "%s\tMay GC: %s\n",
318 prefix, j->id,
319 prefix, j->unit->id, job_type_to_string(j->type),
320 prefix, job_state_to_string(j->state),
321 prefix, yes_no(j->irreversible),
322 prefix, yes_no(job_may_gc(j)));
323 }
324
325 /*
326 * Merging is commutative, so imagine the matrix as symmetric. We store only
327 * its lower triangle to avoid duplication. We don't store the main diagonal,
328 * because A merged with A is simply A.
329 *
330 * If the resulting type is collapsed immediately afterwards (to get rid of
331 * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
332 * the following properties hold:
333 *
334 * Merging is associative! A merged with B, and then merged with C is the same
335 * as A merged with the result of B merged with C.
336 *
337 * Mergeability is transitive! If A can be merged with B and B with C then
338 * A also with C.
339 *
340 * Also, if A merged with B cannot be merged with C, then either A or B cannot
341 * be merged with C either.
342 */
343 static const JobType job_merging_table[] = {
344 /* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
345 /*********************************************************************************/
346 /*JOB_START */
347 /*JOB_VERIFY_ACTIVE */ JOB_START,
348 /*JOB_STOP */ -1, -1,
349 /*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
350 /*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
351 };
352
353 JobType job_type_lookup_merge(JobType a, JobType b) {
354 assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
355 assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
356 assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
357
358 if (a == b)
359 return a;
360
361 if (a < b) {
362 JobType tmp = a;
363 a = b;
364 b = tmp;
365 }
366
367 return job_merging_table[(a - 1) * a / 2 + b];
368 }
369
370 bool job_type_is_redundant(JobType a, UnitActiveState b) {
371 switch (a) {
372
373 case JOB_START:
374 return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
375
376 case JOB_STOP:
377 return IN_SET(b, UNIT_INACTIVE, UNIT_FAILED);
378
379 case JOB_VERIFY_ACTIVE:
380 return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
381
382 case JOB_RELOAD:
383 return
384 b == UNIT_RELOADING;
385
386 case JOB_RESTART:
387 return
388 b == UNIT_ACTIVATING;
389
390 case JOB_NOP:
391 return true;
392
393 default:
394 assert_not_reached("Invalid job type");
395 }
396 }
397
398 JobType job_type_collapse(JobType t, Unit *u) {
399 UnitActiveState s;
400
401 switch (t) {
402
403 case JOB_TRY_RESTART:
404 s = unit_active_state(u);
405 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
406 return JOB_NOP;
407
408 return JOB_RESTART;
409
410 case JOB_TRY_RELOAD:
411 s = unit_active_state(u);
412 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
413 return JOB_NOP;
414
415 return JOB_RELOAD;
416
417 case JOB_RELOAD_OR_START:
418 s = unit_active_state(u);
419 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
420 return JOB_START;
421
422 return JOB_RELOAD;
423
424 default:
425 return t;
426 }
427 }
428
429 int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
430 JobType t;
431
432 t = job_type_lookup_merge(*a, b);
433 if (t < 0)
434 return -EEXIST;
435
436 *a = job_type_collapse(t, u);
437 return 0;
438 }
439
440 static bool job_is_runnable(Job *j) {
441 Iterator i;
442 Unit *other;
443 void *v;
444
445 assert(j);
446 assert(j->installed);
447
448 /* Checks whether there is any job running for the units this
449 * job needs to be running after (in the case of a 'positive'
450 * job type) or before (in the case of a 'negative' job
451 * type. */
452
453 /* Note that unit types have a say in what is runnable,
454 * too. For example, if they return -EAGAIN from
455 * unit_start() they can indicate they are not
456 * runnable yet. */
457
458 /* First check if there is an override */
459 if (j->ignore_order)
460 return true;
461
462 if (j->type == JOB_NOP)
463 return true;
464
465 if (IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE, JOB_RELOAD)) {
466 /* Immediate result is that the job is or might be
467 * started. In this case let's wait for the
468 * dependencies, regardless whether they are
469 * starting or stopping something. */
470
471 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i)
472 if (other->job)
473 return false;
474 }
475
476 /* Also, if something else is being stopped and we should
477 * change state after it, then let's wait. */
478
479 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i)
480 if (other->job &&
481 IN_SET(other->job->type, JOB_STOP, JOB_RESTART))
482 return false;
483
484 /* This means that for a service a and a service b where b
485 * shall be started after a:
486 *
487 * start a + start b → 1st step start a, 2nd step start b
488 * start a + stop b → 1st step stop b, 2nd step start a
489 * stop a + start b → 1st step stop a, 2nd step start b
490 * stop a + stop b → 1st step stop b, 2nd step stop a
491 *
492 * This has the side effect that restarts are properly
493 * synchronized too. */
494
495 return true;
496 }
497
498 static void job_change_type(Job *j, JobType newtype) {
499 assert(j);
500
501 log_unit_debug(j->unit,
502 "Converting job %s/%s -> %s/%s",
503 j->unit->id, job_type_to_string(j->type),
504 j->unit->id, job_type_to_string(newtype));
505
506 j->type = newtype;
507 }
508
509 static int job_perform_on_unit(Job **j) {
510 uint32_t id;
511 Manager *m;
512 JobType t;
513 Unit *u;
514 int r;
515
516 /* While we execute this operation the job might go away (for
517 * example: because it finishes immediately or is replaced by
518 * a new, conflicting job.) To make sure we don't access a
519 * freed job later on we store the id here, so that we can
520 * verify the job is still valid. */
521
522 assert(j);
523 assert(*j);
524
525 m = (*j)->manager;
526 u = (*j)->unit;
527 t = (*j)->type;
528 id = (*j)->id;
529
530 switch (t) {
531 case JOB_START:
532 r = unit_start(u);
533 break;
534
535 case JOB_RESTART:
536 t = JOB_STOP;
537 _fallthrough_;
538 case JOB_STOP:
539 r = unit_stop(u);
540 break;
541
542 case JOB_RELOAD:
543 r = unit_reload(u);
544 break;
545
546 default:
547 assert_not_reached("Invalid job type");
548 }
549
550 /* Log if the job still exists and the start/stop/reload function
551 * actually did something. */
552 *j = manager_get_job(m, id);
553 if (*j && r > 0)
554 unit_status_emit_starting_stopping_reloading(u, t);
555
556 return r;
557 }
558
559 int job_run_and_invalidate(Job *j) {
560 int r;
561
562 assert(j);
563 assert(j->installed);
564 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
565 assert(j->in_run_queue);
566
567 LIST_REMOVE(run_queue, j->manager->run_queue, j);
568 j->in_run_queue = false;
569
570 if (j->state != JOB_WAITING)
571 return 0;
572
573 if (!job_is_runnable(j))
574 return -EAGAIN;
575
576 job_start_timer(j, true);
577 job_set_state(j, JOB_RUNNING);
578 job_add_to_dbus_queue(j);
579
580 switch (j->type) {
581
582 case JOB_VERIFY_ACTIVE: {
583 UnitActiveState t = unit_active_state(j->unit);
584 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
585 r = -EALREADY;
586 else if (t == UNIT_ACTIVATING)
587 r = -EAGAIN;
588 else
589 r = -EBADR;
590 break;
591 }
592
593 case JOB_START:
594 case JOB_STOP:
595 case JOB_RESTART:
596 r = job_perform_on_unit(&j);
597
598 /* If the unit type does not support starting/stopping,
599 * then simply wait. */
600 if (r == -EBADR)
601 r = 0;
602 break;
603
604 case JOB_RELOAD:
605 r = job_perform_on_unit(&j);
606 break;
607
608 case JOB_NOP:
609 r = -EALREADY;
610 break;
611
612 default:
613 assert_not_reached("Unknown job type");
614 }
615
616 if (j) {
617 if (r == -EALREADY)
618 r = job_finish_and_invalidate(j, JOB_DONE, true, true);
619 else if (r == -EBADR)
620 r = job_finish_and_invalidate(j, JOB_SKIPPED, true, false);
621 else if (r == -ENOEXEC)
622 r = job_finish_and_invalidate(j, JOB_INVALID, true, false);
623 else if (r == -EPROTO)
624 r = job_finish_and_invalidate(j, JOB_ASSERT, true, false);
625 else if (r == -EOPNOTSUPP)
626 r = job_finish_and_invalidate(j, JOB_UNSUPPORTED, true, false);
627 else if (r == -ENOLINK)
628 r = job_finish_and_invalidate(j, JOB_DEPENDENCY, true, false);
629 else if (r == -ESTALE)
630 r = job_finish_and_invalidate(j, JOB_ONCE, true, false);
631 else if (r == -EAGAIN)
632 job_set_state(j, JOB_WAITING);
633 else if (r < 0)
634 r = job_finish_and_invalidate(j, JOB_FAILED, true, false);
635 }
636
637 return r;
638 }
639
640 _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
641
642 static const char *const generic_finished_start_job[_JOB_RESULT_MAX] = {
643 [JOB_DONE] = "Started %s.",
644 [JOB_TIMEOUT] = "Timed out starting %s.",
645 [JOB_FAILED] = "Failed to start %s.",
646 [JOB_DEPENDENCY] = "Dependency failed for %s.",
647 [JOB_ASSERT] = "Assertion failed for %s.",
648 [JOB_UNSUPPORTED] = "Starting of %s not supported.",
649 [JOB_COLLECTED] = "Unnecessary job for %s was removed.",
650 [JOB_ONCE] = "Unit %s has been started before and cannot be started again."
651 };
652 static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = {
653 [JOB_DONE] = "Stopped %s.",
654 [JOB_FAILED] = "Stopped (with error) %s.",
655 [JOB_TIMEOUT] = "Timed out stopping %s.",
656 };
657 static const char *const generic_finished_reload_job[_JOB_RESULT_MAX] = {
658 [JOB_DONE] = "Reloaded %s.",
659 [JOB_FAILED] = "Reload failed for %s.",
660 [JOB_TIMEOUT] = "Timed out reloading %s.",
661 };
662 /* When verify-active detects the unit is inactive, report it.
663 * Most likely a DEPEND warning from a requisiting unit will
664 * occur next and it's nice to see what was requisited. */
665 static const char *const generic_finished_verify_active_job[_JOB_RESULT_MAX] = {
666 [JOB_SKIPPED] = "%s is not active.",
667 };
668
669 const UnitStatusMessageFormats *format_table;
670 const char *format;
671
672 assert(u);
673 assert(t >= 0);
674 assert(t < _JOB_TYPE_MAX);
675
676 if (IN_SET(t, JOB_START, JOB_STOP, JOB_RESTART)) {
677 format_table = &UNIT_VTABLE(u)->status_message_formats;
678 if (format_table) {
679 format = t == JOB_START ? format_table->finished_start_job[result] :
680 format_table->finished_stop_job[result];
681 if (format)
682 return format;
683 }
684 }
685
686 /* Return generic strings */
687 if (t == JOB_START)
688 return generic_finished_start_job[result];
689 else if (IN_SET(t, JOB_STOP, JOB_RESTART))
690 return generic_finished_stop_job[result];
691 else if (t == JOB_RELOAD)
692 return generic_finished_reload_job[result];
693 else if (t == JOB_VERIFY_ACTIVE)
694 return generic_finished_verify_active_job[result];
695
696 return NULL;
697 }
698
699 static const struct {
700 const char *color, *word;
701 } job_print_status_messages [_JOB_RESULT_MAX] = {
702 [JOB_DONE] = { ANSI_OK_COLOR, " OK " },
703 [JOB_TIMEOUT] = { ANSI_HIGHLIGHT_RED, " TIME " },
704 [JOB_FAILED] = { ANSI_HIGHLIGHT_RED, "FAILED" },
705 [JOB_DEPENDENCY] = { ANSI_HIGHLIGHT_YELLOW, "DEPEND" },
706 [JOB_SKIPPED] = { ANSI_HIGHLIGHT, " INFO " },
707 [JOB_ASSERT] = { ANSI_HIGHLIGHT_YELLOW, "ASSERT" },
708 [JOB_UNSUPPORTED] = { ANSI_HIGHLIGHT_YELLOW, "UNSUPP" },
709 /* JOB_COLLECTED */
710 [JOB_ONCE] = { ANSI_HIGHLIGHT_RED, " ONCE " },
711 };
712
713 static void job_print_status_message(Unit *u, JobType t, JobResult result) {
714 const char *format;
715 const char *status;
716
717 assert(u);
718 assert(t >= 0);
719 assert(t < _JOB_TYPE_MAX);
720
721 /* Reload status messages have traditionally not been printed to console. */
722 if (t == JOB_RELOAD)
723 return;
724
725 if (!job_print_status_messages[result].word)
726 return;
727
728 format = job_get_status_message_format(u, t, result);
729 if (!format)
730 return;
731
732 if (log_get_show_color())
733 status = strjoina(job_print_status_messages[result].color,
734 job_print_status_messages[result].word,
735 ANSI_NORMAL);
736 else
737 status = job_print_status_messages[result].word;
738
739 if (result != JOB_DONE)
740 manager_flip_auto_status(u->manager, true);
741
742 DISABLE_WARNING_FORMAT_NONLITERAL;
743 unit_status_printf(u, status, format);
744 REENABLE_WARNING;
745
746 if (t == JOB_START && result == JOB_FAILED) {
747 _cleanup_free_ char *quoted;
748
749 quoted = shell_maybe_quote(u->id, ESCAPE_BACKSLASH);
750 manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted));
751 }
752 }
753
754 static void job_log_status_message(Unit *u, JobType t, JobResult result) {
755 const char *format, *mid;
756 char buf[LINE_MAX];
757 static const int job_result_log_level[_JOB_RESULT_MAX] = {
758 [JOB_DONE] = LOG_INFO,
759 [JOB_CANCELED] = LOG_INFO,
760 [JOB_TIMEOUT] = LOG_ERR,
761 [JOB_FAILED] = LOG_ERR,
762 [JOB_DEPENDENCY] = LOG_WARNING,
763 [JOB_SKIPPED] = LOG_NOTICE,
764 [JOB_INVALID] = LOG_INFO,
765 [JOB_ASSERT] = LOG_WARNING,
766 [JOB_UNSUPPORTED] = LOG_WARNING,
767 [JOB_COLLECTED] = LOG_INFO,
768 [JOB_ONCE] = LOG_ERR,
769 };
770
771 assert(u);
772 assert(t >= 0);
773 assert(t < _JOB_TYPE_MAX);
774
775 /* Skip printing if output goes to the console, and job_print_status_message()
776 will actually print something to the console. */
777 if (log_on_console() && job_print_status_messages[result].word)
778 return;
779
780 format = job_get_status_message_format(u, t, result);
781 if (!format)
782 return;
783
784 /* The description might be longer than the buffer, but that's OK,
785 * we'll just truncate it here. Note that we use snprintf() rather than
786 * xsprintf() on purpose here: we are fine with truncation and don't
787 * consider that an error. */
788 DISABLE_WARNING_FORMAT_NONLITERAL;
789 (void) snprintf(buf, sizeof(buf), format, unit_description(u));
790 REENABLE_WARNING;
791
792 switch (t) {
793
794 case JOB_START:
795 if (result == JOB_DONE)
796 mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTED_STR;
797 else
798 mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_FAILED_STR;
799 break;
800
801 case JOB_RELOAD:
802 mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_RELOADED_STR;
803 break;
804
805 case JOB_STOP:
806 case JOB_RESTART:
807 mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_STOPPED_STR;
808 break;
809
810 default:
811 log_struct(job_result_log_level[result],
812 LOG_MESSAGE("%s", buf),
813 "JOB_TYPE=%s", job_type_to_string(t),
814 "JOB_RESULT=%s", job_result_to_string(result),
815 LOG_UNIT_ID(u),
816 LOG_UNIT_INVOCATION_ID(u));
817 return;
818 }
819
820 log_struct(job_result_log_level[result],
821 LOG_MESSAGE("%s", buf),
822 "JOB_TYPE=%s", job_type_to_string(t),
823 "JOB_RESULT=%s", job_result_to_string(result),
824 LOG_UNIT_ID(u),
825 LOG_UNIT_INVOCATION_ID(u),
826 mid);
827 }
828
829 static void job_emit_status_message(Unit *u, JobType t, JobResult result) {
830 assert(u);
831
832 /* No message if the job did not actually do anything due to failed condition. */
833 if (t == JOB_START && result == JOB_DONE && !u->condition_result)
834 return;
835
836 job_log_status_message(u, t, result);
837 job_print_status_message(u, t, result);
838 }
839
840 static void job_fail_dependencies(Unit *u, UnitDependency d) {
841 Unit *other;
842 Iterator i;
843 void *v;
844
845 assert(u);
846
847 HASHMAP_FOREACH_KEY(v, other, u->dependencies[d], i) {
848 Job *j = other->job;
849
850 if (!j)
851 continue;
852 if (!IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE))
853 continue;
854
855 job_finish_and_invalidate(j, JOB_DEPENDENCY, true, false);
856 }
857 }
858
859 static int job_save_pending_finished_job(Job *j) {
860 int r;
861
862 assert(j);
863
864 r = set_ensure_allocated(&j->manager->pending_finished_jobs, NULL);
865 if (r < 0)
866 return r;
867
868 job_unlink(j);
869 return set_put(j->manager->pending_finished_jobs, j);
870 }
871
872 int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already) {
873 Unit *u;
874 Unit *other;
875 JobType t;
876 Iterator i;
877 void *v;
878
879 assert(j);
880 assert(j->installed);
881 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
882
883 u = j->unit;
884 t = j->type;
885
886 j->result = result;
887
888 log_unit_debug(u, "Job %s/%s finished, result=%s", u->id, job_type_to_string(t), job_result_to_string(result));
889
890 /* If this job did nothing to respective unit we don't log the status message */
891 if (!already)
892 job_emit_status_message(u, t, result);
893
894 /* Patch restart jobs so that they become normal start jobs */
895 if (result == JOB_DONE && t == JOB_RESTART) {
896
897 job_change_type(j, JOB_START);
898 job_set_state(j, JOB_WAITING);
899
900 job_add_to_dbus_queue(j);
901 job_add_to_run_queue(j);
902 job_add_to_gc_queue(j);
903
904 goto finish;
905 }
906
907 if (IN_SET(result, JOB_FAILED, JOB_INVALID))
908 j->manager->n_failed_jobs++;
909
910 job_uninstall(j);
911 /* Keep jobs started before the reload to send singal later, free all others */
912 if (!MANAGER_IS_RELOADING(j->manager) ||
913 !j->reloaded ||
914 job_save_pending_finished_job(j) < 0)
915 job_free(j);
916
917 /* Fail depending jobs on failure */
918 if (result != JOB_DONE && recursive) {
919 if (IN_SET(t, JOB_START, JOB_VERIFY_ACTIVE)) {
920 job_fail_dependencies(u, UNIT_REQUIRED_BY);
921 job_fail_dependencies(u, UNIT_REQUISITE_OF);
922 job_fail_dependencies(u, UNIT_BOUND_BY);
923 } else if (t == JOB_STOP)
924 job_fail_dependencies(u, UNIT_CONFLICTED_BY);
925 }
926
927 /* Trigger OnFailure dependencies that are not generated by
928 * the unit itself. We don't treat JOB_CANCELED as failure in
929 * this context. And JOB_FAILURE is already handled by the
930 * unit itself. */
931 if (IN_SET(result, JOB_TIMEOUT, JOB_DEPENDENCY)) {
932 log_struct(LOG_NOTICE,
933 "JOB_TYPE=%s", job_type_to_string(t),
934 "JOB_RESULT=%s", job_result_to_string(result),
935 LOG_UNIT_ID(u),
936 LOG_UNIT_MESSAGE(u, "Job %s/%s failed with result '%s'.",
937 u->id,
938 job_type_to_string(t),
939 job_result_to_string(result)));
940
941 unit_start_on_failure(u);
942 }
943
944 unit_trigger_notify(u);
945
946 finish:
947 /* Try to start the next jobs that can be started */
948 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_AFTER], i)
949 if (other->job) {
950 job_add_to_run_queue(other->job);
951 job_add_to_gc_queue(other->job);
952 }
953 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BEFORE], i)
954 if (other->job) {
955 job_add_to_run_queue(other->job);
956 job_add_to_gc_queue(other->job);
957 }
958
959 manager_check_finished(u->manager);
960
961 return 0;
962 }
963
964 static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *userdata) {
965 Job *j = userdata;
966 Unit *u;
967
968 assert(j);
969 assert(s == j->timer_event_source);
970
971 log_unit_warning(j->unit, "Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
972
973 u = j->unit;
974 job_finish_and_invalidate(j, JOB_TIMEOUT, true, false);
975
976 emergency_action(u->manager, u->job_timeout_action, u->job_timeout_reboot_arg, "job timed out");
977
978 return 0;
979 }
980
981 int job_start_timer(Job *j, bool job_running) {
982 int r;
983 usec_t timeout_time, old_timeout_time;
984
985 if (job_running) {
986 j->begin_running_usec = now(CLOCK_MONOTONIC);
987
988 if (j->unit->job_running_timeout == USEC_INFINITY)
989 return 0;
990
991 timeout_time = usec_add(j->begin_running_usec, j->unit->job_running_timeout);
992
993 if (j->timer_event_source) {
994 /* Update only if JobRunningTimeoutSec= results in earlier timeout */
995 r = sd_event_source_get_time(j->timer_event_source, &old_timeout_time);
996 if (r < 0)
997 return r;
998
999 if (old_timeout_time <= timeout_time)
1000 return 0;
1001
1002 return sd_event_source_set_time(j->timer_event_source, timeout_time);
1003 }
1004 } else {
1005 if (j->timer_event_source)
1006 return 0;
1007
1008 j->begin_usec = now(CLOCK_MONOTONIC);
1009
1010 if (j->unit->job_timeout == USEC_INFINITY)
1011 return 0;
1012
1013 timeout_time = usec_add(j->begin_usec, j->unit->job_timeout);
1014 }
1015
1016 r = sd_event_add_time(
1017 j->manager->event,
1018 &j->timer_event_source,
1019 CLOCK_MONOTONIC,
1020 timeout_time, 0,
1021 job_dispatch_timer, j);
1022 if (r < 0)
1023 return r;
1024
1025 (void) sd_event_source_set_description(j->timer_event_source, "job-start");
1026
1027 return 0;
1028 }
1029
1030 void job_add_to_run_queue(Job *j) {
1031 assert(j);
1032 assert(j->installed);
1033
1034 if (j->in_run_queue)
1035 return;
1036
1037 if (!j->manager->run_queue)
1038 sd_event_source_set_enabled(j->manager->run_queue_event_source, SD_EVENT_ONESHOT);
1039
1040 LIST_PREPEND(run_queue, j->manager->run_queue, j);
1041 j->in_run_queue = true;
1042 }
1043
1044 void job_add_to_dbus_queue(Job *j) {
1045 assert(j);
1046 assert(j->installed);
1047
1048 if (j->in_dbus_queue)
1049 return;
1050
1051 /* We don't check if anybody is subscribed here, since this
1052 * job might just have been created and not yet assigned to a
1053 * connection/client. */
1054
1055 LIST_PREPEND(dbus_queue, j->manager->dbus_job_queue, j);
1056 j->in_dbus_queue = true;
1057 }
1058
1059 char *job_dbus_path(Job *j) {
1060 char *p;
1061
1062 assert(j);
1063
1064 if (asprintf(&p, "/org/freedesktop/systemd1/job/%"PRIu32, j->id) < 0)
1065 return NULL;
1066
1067 return p;
1068 }
1069
1070 int job_serialize(Job *j, FILE *f) {
1071 assert(j);
1072 assert(f);
1073
1074 fprintf(f, "job-id=%u\n", j->id);
1075 fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
1076 fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
1077 fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible));
1078 fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
1079 fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
1080
1081 if (j->begin_usec > 0)
1082 fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec);
1083 if (j->begin_running_usec > 0)
1084 fprintf(f, "job-begin-running="USEC_FMT"\n", j->begin_running_usec);
1085
1086 bus_track_serialize(j->bus_track, f, "subscribed");
1087
1088 /* End marker */
1089 fputc('\n', f);
1090 return 0;
1091 }
1092
1093 int job_deserialize(Job *j, FILE *f) {
1094 assert(j);
1095 assert(f);
1096
1097 for (;;) {
1098 char line[LINE_MAX], *l, *v;
1099 size_t k;
1100
1101 if (!fgets(line, sizeof(line), f)) {
1102 if (feof(f))
1103 return 0;
1104 return -errno;
1105 }
1106
1107 char_array_0(line);
1108 l = strstrip(line);
1109
1110 /* End marker */
1111 if (l[0] == 0)
1112 return 0;
1113
1114 k = strcspn(l, "=");
1115
1116 if (l[k] == '=') {
1117 l[k] = 0;
1118 v = l+k+1;
1119 } else
1120 v = l+k;
1121
1122 if (streq(l, "job-id")) {
1123
1124 if (safe_atou32(v, &j->id) < 0)
1125 log_debug("Failed to parse job id value %s", v);
1126
1127 } else if (streq(l, "job-type")) {
1128 JobType t;
1129
1130 t = job_type_from_string(v);
1131 if (t < 0)
1132 log_debug("Failed to parse job type %s", v);
1133 else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
1134 log_debug("Cannot deserialize job of type %s", v);
1135 else
1136 j->type = t;
1137
1138 } else if (streq(l, "job-state")) {
1139 JobState s;
1140
1141 s = job_state_from_string(v);
1142 if (s < 0)
1143 log_debug("Failed to parse job state %s", v);
1144 else
1145 job_set_state(j, s);
1146
1147 } else if (streq(l, "job-irreversible")) {
1148 int b;
1149
1150 b = parse_boolean(v);
1151 if (b < 0)
1152 log_debug("Failed to parse job irreversible flag %s", v);
1153 else
1154 j->irreversible = j->irreversible || b;
1155
1156 } else if (streq(l, "job-sent-dbus-new-signal")) {
1157 int b;
1158
1159 b = parse_boolean(v);
1160 if (b < 0)
1161 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
1162 else
1163 j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
1164
1165 } else if (streq(l, "job-ignore-order")) {
1166 int b;
1167
1168 b = parse_boolean(v);
1169 if (b < 0)
1170 log_debug("Failed to parse job ignore_order flag %s", v);
1171 else
1172 j->ignore_order = j->ignore_order || b;
1173
1174 } else if (streq(l, "job-begin")) {
1175 unsigned long long ull;
1176
1177 if (sscanf(v, "%llu", &ull) != 1)
1178 log_debug("Failed to parse job-begin value %s", v);
1179 else
1180 j->begin_usec = ull;
1181
1182 } else if (streq(l, "job-begin-running")) {
1183 unsigned long long ull;
1184
1185 if (sscanf(v, "%llu", &ull) != 1)
1186 log_debug("Failed to parse job-begin-running value %s", v);
1187 else
1188 j->begin_running_usec = ull;
1189
1190 } else if (streq(l, "subscribed")) {
1191
1192 if (strv_extend(&j->deserialized_clients, v) < 0)
1193 log_oom();
1194 }
1195 }
1196 }
1197
1198 int job_coldplug(Job *j) {
1199 int r;
1200 usec_t timeout_time = USEC_INFINITY;
1201
1202 assert(j);
1203
1204 /* After deserialization is complete and the bus connection
1205 * set up again, let's start watching our subscribers again */
1206 (void) bus_job_coldplug_bus_track(j);
1207
1208 if (j->state == JOB_WAITING)
1209 job_add_to_run_queue(j);
1210
1211 /* Maybe due to new dependencies we don't actually need this job anymore? */
1212 job_add_to_gc_queue(j);
1213
1214 /* Create timer only when job began or began running and the respective timeout is finite.
1215 * Follow logic of job_start_timer() if both timeouts are finite */
1216 if (j->begin_usec == 0)
1217 return 0;
1218
1219 if (j->unit->job_timeout != USEC_INFINITY)
1220 timeout_time = usec_add(j->begin_usec, j->unit->job_timeout);
1221
1222 if (j->begin_running_usec > 0 && j->unit->job_running_timeout != USEC_INFINITY)
1223 timeout_time = MIN(timeout_time, usec_add(j->begin_running_usec, j->unit->job_running_timeout));
1224
1225 if (timeout_time == USEC_INFINITY)
1226 return 0;
1227
1228 j->timer_event_source = sd_event_source_unref(j->timer_event_source);
1229
1230 r = sd_event_add_time(
1231 j->manager->event,
1232 &j->timer_event_source,
1233 CLOCK_MONOTONIC,
1234 timeout_time, 0,
1235 job_dispatch_timer, j);
1236 if (r < 0)
1237 log_debug_errno(r, "Failed to restart timeout for job: %m");
1238
1239 (void) sd_event_source_set_description(j->timer_event_source, "job-timeout");
1240
1241 return r;
1242 }
1243
1244 void job_shutdown_magic(Job *j) {
1245 assert(j);
1246
1247 /* The shutdown target gets some special treatment here: we
1248 * tell the kernel to begin with flushing its disk caches, to
1249 * optimize shutdown time a bit. Ideally we wouldn't hardcode
1250 * this magic into PID 1. However all other processes aren't
1251 * options either since they'd exit much sooner than PID 1 and
1252 * asynchronous sync() would cause their exit to be
1253 * delayed. */
1254
1255 if (j->type != JOB_START)
1256 return;
1257
1258 if (!MANAGER_IS_SYSTEM(j->unit->manager))
1259 return;
1260
1261 if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
1262 return;
1263
1264 /* In case messages on console has been disabled on boot */
1265 j->unit->manager->no_console_output = false;
1266
1267 if (detect_container() > 0)
1268 return;
1269
1270 (void) asynchronous_sync(NULL);
1271 }
1272
1273 int job_get_timeout(Job *j, usec_t *timeout) {
1274 usec_t x = USEC_INFINITY, y = USEC_INFINITY;
1275 Unit *u = j->unit;
1276 int r;
1277
1278 assert(u);
1279
1280 if (j->timer_event_source) {
1281 r = sd_event_source_get_time(j->timer_event_source, &x);
1282 if (r < 0)
1283 return r;
1284 }
1285
1286 if (UNIT_VTABLE(u)->get_timeout) {
1287 r = UNIT_VTABLE(u)->get_timeout(u, &y);
1288 if (r < 0)
1289 return r;
1290 }
1291
1292 if (x == USEC_INFINITY && y == USEC_INFINITY)
1293 return 0;
1294
1295 *timeout = MIN(x, y);
1296 return 1;
1297 }
1298
1299 bool job_may_gc(Job *j) {
1300 Unit *other;
1301 Iterator i;
1302 void *v;
1303
1304 assert(j);
1305
1306 /* Checks whether this job should be GC'ed away. We only do this for jobs of units that have no effect on their
1307 * own and just track external state. For now the only unit type that qualifies for this are .device units.
1308 * Returns true if the job can be collected. */
1309
1310 if (!UNIT_VTABLE(j->unit)->gc_jobs)
1311 return false;
1312
1313 if (sd_bus_track_count(j->bus_track) > 0)
1314 return false;
1315
1316 /* FIXME: So this is a bit ugly: for now we don't properly track references made via private bus connections
1317 * (because it's nasty, as sd_bus_track doesn't apply to it). We simply remember that the job was once
1318 * referenced by one, and reset this whenever we notice that no private bus connections are around. This means
1319 * the GC is a bit too conservative when it comes to jobs created by private bus connections. */
1320 if (j->ref_by_private_bus) {
1321 if (set_isempty(j->unit->manager->private_buses))
1322 j->ref_by_private_bus = false;
1323 else
1324 return false;
1325 }
1326
1327 if (j->type == JOB_NOP)
1328 return false;
1329
1330 /* If a job is ordered after ours, and is to be started, then it needs to wait for us, regardless if we stop or
1331 * start, hence let's not GC in that case. */
1332 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
1333 if (!other->job)
1334 continue;
1335
1336 if (other->job->ignore_order)
1337 continue;
1338
1339 if (IN_SET(other->job->type, JOB_START, JOB_VERIFY_ACTIVE, JOB_RELOAD))
1340 return false;
1341 }
1342
1343 /* If we are going down, but something else is ordered After= us, then it needs to wait for us */
1344 if (IN_SET(j->type, JOB_STOP, JOB_RESTART))
1345 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
1346 if (!other->job)
1347 continue;
1348
1349 if (other->job->ignore_order)
1350 continue;
1351
1352 return false;
1353 }
1354
1355 /* The logic above is kinda the inverse of the job_is_runnable() logic. Specifically, if the job "we" is
1356 * ordered before the job "other":
1357 *
1358 * we start + other start → stay
1359 * we start + other stop → gc
1360 * we stop + other start → stay
1361 * we stop + other stop → gc
1362 *
1363 * "we" are ordered after "other":
1364 *
1365 * we start + other start → gc
1366 * we start + other stop → gc
1367 * we stop + other start → stay
1368 * we stop + other stop → stay
1369 */
1370
1371 return true;
1372 }
1373
1374 void job_add_to_gc_queue(Job *j) {
1375 assert(j);
1376
1377 if (j->in_gc_queue)
1378 return;
1379
1380 if (!job_may_gc(j))
1381 return;
1382
1383 LIST_PREPEND(gc_queue, j->unit->manager->gc_job_queue, j);
1384 j->in_gc_queue = true;
1385 }
1386
1387 static int job_compare(Job * const *a, Job * const *b) {
1388 return CMP((*a)->id, (*b)->id);
1389 }
1390
1391 static size_t sort_job_list(Job **list, size_t n) {
1392 Job *previous = NULL;
1393 size_t a, b;
1394
1395 /* Order by numeric IDs */
1396 typesafe_qsort(list, n, job_compare);
1397
1398 /* Filter out duplicates */
1399 for (a = 0, b = 0; a < n; a++) {
1400
1401 if (previous == list[a])
1402 continue;
1403
1404 previous = list[b++] = list[a];
1405 }
1406
1407 return b;
1408 }
1409
1410 int job_get_before(Job *j, Job*** ret) {
1411 _cleanup_free_ Job** list = NULL;
1412 size_t n = 0, n_allocated = 0;
1413 Unit *other = NULL;
1414 Iterator i;
1415 void *v;
1416
1417 /* Returns a list of all pending jobs that need to finish before this job may be started. */
1418
1419 assert(j);
1420 assert(ret);
1421
1422 if (j->ignore_order) {
1423 *ret = NULL;
1424 return 0;
1425 }
1426
1427 if (IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE, JOB_RELOAD)) {
1428
1429 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
1430 if (!other->job)
1431 continue;
1432
1433 if (!GREEDY_REALLOC(list, n_allocated, n+1))
1434 return -ENOMEM;
1435 list[n++] = other->job;
1436 }
1437 }
1438
1439 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
1440 if (!other->job)
1441 continue;
1442
1443 if (!IN_SET(other->job->type, JOB_STOP, JOB_RESTART))
1444 continue;
1445
1446 if (!GREEDY_REALLOC(list, n_allocated, n+1))
1447 return -ENOMEM;
1448 list[n++] = other->job;
1449 }
1450
1451 n = sort_job_list(list, n);
1452
1453 *ret = TAKE_PTR(list);
1454
1455 return (int) n;
1456 }
1457
1458 int job_get_after(Job *j, Job*** ret) {
1459 _cleanup_free_ Job** list = NULL;
1460 size_t n = 0, n_allocated = 0;
1461 Unit *other = NULL;
1462 void *v;
1463 Iterator i;
1464
1465 assert(j);
1466 assert(ret);
1467
1468 /* Returns a list of all pending jobs that are waiting for this job to finish. */
1469
1470 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
1471 if (!other->job)
1472 continue;
1473
1474 if (other->job->ignore_order)
1475 continue;
1476
1477 if (!IN_SET(other->job->type, JOB_START, JOB_VERIFY_ACTIVE, JOB_RELOAD))
1478 continue;
1479
1480 if (!GREEDY_REALLOC(list, n_allocated, n+1))
1481 return -ENOMEM;
1482 list[n++] = other->job;
1483 }
1484
1485 if (IN_SET(j->type, JOB_STOP, JOB_RESTART)) {
1486
1487 HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
1488 if (!other->job)
1489 continue;
1490
1491 if (other->job->ignore_order)
1492 continue;
1493
1494 if (!GREEDY_REALLOC(list, n_allocated, n+1))
1495 return -ENOMEM;
1496 list[n++] = other->job;
1497 }
1498 }
1499
1500 n = sort_job_list(list, n);
1501
1502 *ret = TAKE_PTR(list);
1503
1504 return (int) n;
1505 }
1506
1507 static const char* const job_state_table[_JOB_STATE_MAX] = {
1508 [JOB_WAITING] = "waiting",
1509 [JOB_RUNNING] = "running",
1510 };
1511
1512 DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
1513
1514 static const char* const job_type_table[_JOB_TYPE_MAX] = {
1515 [JOB_START] = "start",
1516 [JOB_VERIFY_ACTIVE] = "verify-active",
1517 [JOB_STOP] = "stop",
1518 [JOB_RELOAD] = "reload",
1519 [JOB_RELOAD_OR_START] = "reload-or-start",
1520 [JOB_RESTART] = "restart",
1521 [JOB_TRY_RESTART] = "try-restart",
1522 [JOB_TRY_RELOAD] = "try-reload",
1523 [JOB_NOP] = "nop",
1524 };
1525
1526 DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
1527
1528 static const char* const job_mode_table[_JOB_MODE_MAX] = {
1529 [JOB_FAIL] = "fail",
1530 [JOB_REPLACE] = "replace",
1531 [JOB_REPLACE_IRREVERSIBLY] = "replace-irreversibly",
1532 [JOB_ISOLATE] = "isolate",
1533 [JOB_FLUSH] = "flush",
1534 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
1535 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements",
1536 };
1537
1538 DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
1539
1540 static const char* const job_result_table[_JOB_RESULT_MAX] = {
1541 [JOB_DONE] = "done",
1542 [JOB_CANCELED] = "canceled",
1543 [JOB_TIMEOUT] = "timeout",
1544 [JOB_FAILED] = "failed",
1545 [JOB_DEPENDENCY] = "dependency",
1546 [JOB_SKIPPED] = "skipped",
1547 [JOB_INVALID] = "invalid",
1548 [JOB_ASSERT] = "assert",
1549 [JOB_UNSUPPORTED] = "unsupported",
1550 [JOB_COLLECTED] = "collected",
1551 [JOB_ONCE] = "once",
1552 };
1553
1554 DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);
1555
1556 const char* job_type_to_access_method(JobType t) {
1557 assert(t >= 0);
1558 assert(t < _JOB_TYPE_MAX);
1559
1560 if (IN_SET(t, JOB_START, JOB_RESTART, JOB_TRY_RESTART))
1561 return "start";
1562 else if (t == JOB_STOP)
1563 return "stop";
1564 else
1565 return "reload";
1566 }