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