]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/manager.c
manager: reuse sockaddr_union instead of redefining our own version of it
[thirdparty/systemd.git] / src / core / manager.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <assert.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <signal.h>
26 #include <sys/wait.h>
27 #include <unistd.h>
28 #include <sys/poll.h>
29 #include <sys/reboot.h>
30 #include <sys/ioctl.h>
31 #include <linux/kd.h>
32 #include <termios.h>
33 #include <fcntl.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <dirent.h>
37 #include <sys/timerfd.h>
38
39 #ifdef HAVE_AUDIT
40 #include <libaudit.h>
41 #endif
42
43 #include "sd-daemon.h"
44 #include "sd-id128.h"
45 #include "sd-messages.h"
46
47 #include "manager.h"
48 #include "transaction.h"
49 #include "hashmap.h"
50 #include "macro.h"
51 #include "strv.h"
52 #include "log.h"
53 #include "util.h"
54 #include "mkdir.h"
55 #include "ratelimit.h"
56 #include "locale-setup.h"
57 #include "mount-setup.h"
58 #include "unit-name.h"
59 #include "missing.h"
60 #include "path-lookup.h"
61 #include "special.h"
62 #include "exit-status.h"
63 #include "virt.h"
64 #include "watchdog.h"
65 #include "cgroup-util.h"
66 #include "path-util.h"
67 #include "audit-fd.h"
68 #include "boot-timestamps.h"
69 #include "env-util.h"
70 #include "bus-errors.h"
71 #include "bus-error.h"
72 #include "bus-util.h"
73 #include "dbus.h"
74 #include "dbus-unit.h"
75 #include "dbus-job.h"
76 #include "dbus-manager.h"
77 #include "bus-kernel.h"
78
79 /* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
80 #define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
81
82 /* Initial delay and the interval for printing status messages about running jobs */
83 #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
84 #define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3)
85 #define JOBS_IN_PROGRESS_PERIOD_DIVISOR 3
86
87 #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
88
89 static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
90 static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
91 static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
92 static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
93 static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata);
94 static int manager_dispatch_run_queue(sd_event_source *source, void *userdata);
95
96 static int manager_watch_jobs_in_progress(Manager *m) {
97 usec_t next;
98
99 assert(m);
100
101 if (m->jobs_in_progress_event_source)
102 return 0;
103
104 next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC;
105 return sd_event_add_time(
106 m->event,
107 &m->jobs_in_progress_event_source,
108 CLOCK_MONOTONIC,
109 next, 0,
110 manager_dispatch_jobs_in_progress, m);
111 }
112
113 #define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1))
114
115 static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) {
116 char *p = buffer;
117
118 assert(buflen >= CYLON_BUFFER_EXTRA + width + 1);
119 assert(pos <= width+1); /* 0 or width+1 mean that the center light is behind the corner */
120
121 if (pos > 1) {
122 if (pos > 2)
123 p = mempset(p, ' ', pos-2);
124 p = stpcpy(p, ANSI_RED_ON);
125 *p++ = '*';
126 }
127
128 if (pos > 0 && pos <= width) {
129 p = stpcpy(p, ANSI_HIGHLIGHT_RED_ON);
130 *p++ = '*';
131 }
132
133 p = stpcpy(p, ANSI_HIGHLIGHT_OFF);
134
135 if (pos < width) {
136 p = stpcpy(p, ANSI_RED_ON);
137 *p++ = '*';
138 if (pos < width-1)
139 p = mempset(p, ' ', width-1-pos);
140 strcpy(p, ANSI_HIGHLIGHT_OFF);
141 }
142 }
143
144 void manager_flip_auto_status(Manager *m, bool enable) {
145 assert(m);
146
147 if (enable) {
148 if (m->show_status == SHOW_STATUS_AUTO)
149 manager_set_show_status(m, SHOW_STATUS_TEMPORARY);
150 } else {
151 if (m->show_status == SHOW_STATUS_TEMPORARY)
152 manager_set_show_status(m, SHOW_STATUS_AUTO);
153 }
154 }
155
156 static void manager_print_jobs_in_progress(Manager *m) {
157 _cleanup_free_ char *job_of_n = NULL;
158 Iterator i;
159 Job *j;
160 unsigned counter = 0, print_nr;
161 char cylon[6 + CYLON_BUFFER_EXTRA + 1];
162 unsigned cylon_pos;
163 char time[FORMAT_TIMESPAN_MAX], limit[FORMAT_TIMESPAN_MAX] = "no limit";
164 uint64_t x;
165
166 assert(m);
167
168 manager_flip_auto_status(m, true);
169
170 print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs;
171
172 HASHMAP_FOREACH(j, m->jobs, i)
173 if (j->state == JOB_RUNNING && counter++ == print_nr)
174 break;
175
176 /* m->n_running_jobs must be consistent with the contents of m->jobs,
177 * so the above loop must have succeeded in finding j. */
178 assert(counter == print_nr + 1);
179 assert(j);
180
181 cylon_pos = m->jobs_in_progress_iteration % 14;
182 if (cylon_pos >= 8)
183 cylon_pos = 14 - cylon_pos;
184 draw_cylon(cylon, sizeof(cylon), 6, cylon_pos);
185
186 m->jobs_in_progress_iteration++;
187
188 if (m->n_running_jobs > 1)
189 if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0)
190 job_of_n = NULL;
191
192 format_timespan(time, sizeof(time), now(CLOCK_MONOTONIC) - j->begin_usec, 1*USEC_PER_SEC);
193 if (job_get_timeout(j, &x) > 0)
194 format_timespan(limit, sizeof(limit), x - j->begin_usec, 1*USEC_PER_SEC);
195
196 manager_status_printf(m, true, cylon,
197 "%sA %s job is running for %s (%s / %s)",
198 strempty(job_of_n),
199 job_type_to_string(j->type),
200 unit_description(j->unit),
201 time, limit);
202
203 }
204
205 static int manager_watch_idle_pipe(Manager *m) {
206 int r;
207
208 assert(m);
209
210 if (m->idle_pipe_event_source)
211 return 0;
212
213 if (m->idle_pipe[2] < 0)
214 return 0;
215
216 r = sd_event_add_io(m->event, &m->idle_pipe_event_source, m->idle_pipe[2], EPOLLIN, manager_dispatch_idle_pipe_fd, m);
217 if (r < 0) {
218 log_error("Failed to watch idle pipe: %s", strerror(-r));
219 return r;
220 }
221
222 return 0;
223 }
224
225 static void manager_close_idle_pipe(Manager *m) {
226 assert(m);
227
228 safe_close_pair(m->idle_pipe);
229 safe_close_pair(m->idle_pipe + 2);
230 }
231
232 static int manager_setup_time_change(Manager *m) {
233 int r;
234
235 /* We only care for the cancellation event, hence we set the
236 * timeout to the latest possible value. */
237 struct itimerspec its = {
238 .it_value.tv_sec = TIME_T_MAX,
239 };
240
241 assert(m);
242 assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
243
244 if (m->test_run)
245 return 0;
246
247 /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
248 * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
249
250 m->time_change_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
251 if (m->time_change_fd < 0) {
252 log_error("Failed to create timerfd: %m");
253 return -errno;
254 }
255
256 if (timerfd_settime(m->time_change_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
257 log_debug("Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
258 m->time_change_fd = safe_close(m->time_change_fd);
259 return 0;
260 }
261
262 r = sd_event_add_io(m->event, &m->time_change_event_source, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m);
263 if (r < 0) {
264 log_error("Failed to create time change event source: %s", strerror(-r));
265 return r;
266 }
267
268 log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
269
270 return 0;
271 }
272
273 static int enable_special_signals(Manager *m) {
274 _cleanup_close_ int fd = -1;
275
276 assert(m);
277
278 /* Enable that we get SIGINT on control-alt-del. In containers
279 * this will fail with EPERM (older) or EINVAL (newer), so
280 * ignore that. */
281 if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM && errno != EINVAL)
282 log_warning("Failed to enable ctrl-alt-del handling: %m");
283
284 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
285 if (fd < 0) {
286 /* Support systems without virtual console */
287 if (fd != -ENOENT)
288 log_warning("Failed to open /dev/tty0: %m");
289 } else {
290 /* Enable that we get SIGWINCH on kbrequest */
291 if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0)
292 log_warning("Failed to enable kbrequest handling: %m");
293 }
294
295 return 0;
296 }
297
298 static int manager_setup_signals(Manager *m) {
299 struct sigaction sa = {
300 .sa_handler = SIG_DFL,
301 .sa_flags = SA_NOCLDSTOP|SA_RESTART,
302 };
303 sigset_t mask;
304 int r;
305
306 assert(m);
307
308 if (m->test_run)
309 return 0;
310
311 /* We are not interested in SIGSTOP and friends. */
312 assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
313
314 assert_se(sigemptyset(&mask) == 0);
315
316 sigset_add_many(&mask,
317 SIGCHLD, /* Child died */
318 SIGTERM, /* Reexecute daemon */
319 SIGHUP, /* Reload configuration */
320 SIGUSR1, /* systemd/upstart: reconnect to D-Bus */
321 SIGUSR2, /* systemd: dump status */
322 SIGINT, /* Kernel sends us this on control-alt-del */
323 SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */
324 SIGPWR, /* Some kernel drivers and upsd send us this on power failure */
325 SIGRTMIN+0, /* systemd: start default.target */
326 SIGRTMIN+1, /* systemd: isolate rescue.target */
327 SIGRTMIN+2, /* systemd: isolate emergency.target */
328 SIGRTMIN+3, /* systemd: start halt.target */
329 SIGRTMIN+4, /* systemd: start poweroff.target */
330 SIGRTMIN+5, /* systemd: start reboot.target */
331 SIGRTMIN+6, /* systemd: start kexec.target */
332 SIGRTMIN+13, /* systemd: Immediate halt */
333 SIGRTMIN+14, /* systemd: Immediate poweroff */
334 SIGRTMIN+15, /* systemd: Immediate reboot */
335 SIGRTMIN+16, /* systemd: Immediate kexec */
336 SIGRTMIN+20, /* systemd: enable status messages */
337 SIGRTMIN+21, /* systemd: disable status messages */
338 SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */
339 SIGRTMIN+23, /* systemd: set log level to LOG_INFO */
340 SIGRTMIN+24, /* systemd: Immediate exit (--user only) */
341 SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
342 SIGRTMIN+27, /* systemd: set log target to console */
343 SIGRTMIN+28, /* systemd: set log target to kmsg */
344 SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg (obsolete)*/
345 -1);
346 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
347
348 m->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
349 if (m->signal_fd < 0)
350 return -errno;
351
352 r = sd_event_add_io(m->event, &m->signal_event_source, m->signal_fd, EPOLLIN, manager_dispatch_signal_fd, m);
353 if (r < 0)
354 return r;
355
356 /* Process signals a bit earlier than the rest of things, but
357 * later that notify_fd processing, so that the notify
358 * processing can still figure out to which process/service a
359 * message belongs, before we reap the process. */
360 r = sd_event_source_set_priority(m->signal_event_source, -5);
361 if (r < 0)
362 return r;
363
364 if (m->running_as == SYSTEMD_SYSTEM)
365 return enable_special_signals(m);
366
367 return 0;
368 }
369
370 static void manager_clean_environment(Manager *m) {
371 assert(m);
372
373 /* Let's remove some environment variables that we
374 * need ourselves to communicate with our clients */
375 strv_env_unset_many(
376 m->environment,
377 "NOTIFY_SOCKET",
378 "MAINPID",
379 "MANAGERPID",
380 "LISTEN_PID",
381 "LISTEN_FDS",
382 "WATCHDOG_PID",
383 "WATCHDOG_USEC",
384 NULL);
385 }
386
387 static int manager_default_environment(Manager *m) {
388 assert(m);
389
390 if (m->running_as == SYSTEMD_SYSTEM) {
391 /* The system manager always starts with a clean
392 * environment for its children. It does not import
393 * the kernel or the parents exported variables.
394 *
395 * The initial passed environ is untouched to keep
396 * /proc/self/environ valid; it is used for tagging
397 * the init process inside containers. */
398 m->environment = strv_new("PATH=" DEFAULT_PATH,
399 NULL);
400
401 /* Import locale variables LC_*= from configuration */
402 locale_setup(&m->environment);
403 } else {
404 /* The user manager passes its own environment
405 * along to its children. */
406 m->environment = strv_copy(environ);
407 }
408
409 if (!m->environment)
410 return -ENOMEM;
411
412 manager_clean_environment(m);
413 strv_sort(m->environment);
414
415 return 0;
416 }
417
418 int manager_new(SystemdRunningAs running_as, bool test_run, Manager **_m) {
419 Manager *m;
420 int r;
421
422 assert(_m);
423 assert(running_as >= 0);
424 assert(running_as < _SYSTEMD_RUNNING_AS_MAX);
425
426 m = new0(Manager, 1);
427 if (!m)
428 return -ENOMEM;
429
430 #ifdef ENABLE_EFI
431 if (running_as == SYSTEMD_SYSTEM && detect_container(NULL) <= 0)
432 boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp);
433 #endif
434
435 m->running_as = running_as;
436 m->exit_code = _MANAGER_EXIT_CODE_INVALID;
437 m->default_timer_accuracy_usec = USEC_PER_MINUTE;
438
439 m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
440
441 m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = -1;
442 m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
443
444 m->test_run = test_run;
445
446 r = manager_default_environment(m);
447 if (r < 0)
448 goto fail;
449
450 r = hashmap_ensure_allocated(&m->units, string_hash_func, string_compare_func);
451 if (r < 0)
452 goto fail;
453
454 r = hashmap_ensure_allocated(&m->jobs, trivial_hash_func, trivial_compare_func);
455 if (r < 0)
456 goto fail;
457
458 r = hashmap_ensure_allocated(&m->cgroup_unit, string_hash_func, string_compare_func);
459 if (r < 0)
460 goto fail;
461
462 r = hashmap_ensure_allocated(&m->watch_bus, string_hash_func, string_compare_func);
463 if (r < 0)
464 goto fail;
465
466 r = set_ensure_allocated(&m->startup_units, trivial_hash_func, trivial_compare_func);
467 if (r < 0)
468 goto fail;
469
470 r = set_ensure_allocated(&m->failed_units, trivial_hash_func, trivial_compare_func);
471 if (r < 0)
472 goto fail;
473
474 r = sd_event_default(&m->event);
475 if (r < 0)
476 goto fail;
477
478 r = sd_event_add_defer(m->event, &m->run_queue_event_source, manager_dispatch_run_queue, m);
479 if (r < 0)
480 goto fail;
481
482 r = sd_event_source_set_priority(m->run_queue_event_source, SD_EVENT_PRIORITY_IDLE);
483 if (r < 0)
484 goto fail;
485
486 r = sd_event_source_set_enabled(m->run_queue_event_source, SD_EVENT_OFF);
487 if (r < 0)
488 goto fail;
489
490 r = manager_setup_signals(m);
491 if (r < 0)
492 goto fail;
493
494 r = manager_setup_cgroup(m);
495 if (r < 0)
496 goto fail;
497
498 r = manager_setup_time_change(m);
499 if (r < 0)
500 goto fail;
501
502 m->udev = udev_new();
503 if (!m->udev) {
504 r = -ENOMEM;
505 goto fail;
506 }
507
508 /* Note that we set up neither kdbus, nor the notify fd
509 * here. We do that after deserialization, since they might
510 * have gotten serialized across the reexec. */
511
512 m->taint_usr = dir_is_empty("/usr") > 0;
513
514 *_m = m;
515 return 0;
516
517 fail:
518 manager_free(m);
519 return r;
520 }
521
522 static int manager_setup_notify(Manager *m) {
523 int r;
524
525 if (m->test_run)
526 return 0;
527
528 if (m->notify_fd < 0) {
529 _cleanup_close_ int fd = -1;
530 union sockaddr_union sa = {
531 .sa.sa_family = AF_UNIX,
532 };
533 static const int one = 1;
534
535 /* First free all secondary fields */
536 free(m->notify_socket);
537 m->notify_socket = NULL;
538 m->notify_event_source = sd_event_source_unref(m->notify_event_source);
539
540 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
541 if (fd < 0) {
542 log_error("Failed to allocate notification socket: %m");
543 return -errno;
544 }
545
546 if (m->running_as == SYSTEMD_SYSTEM)
547 m->notify_socket = strdup("/run/systemd/notify");
548 else {
549 const char *e;
550
551 e = getenv("XDG_RUNTIME_DIR");
552 if (!e) {
553 log_error("XDG_RUNTIME_DIR is not set: %m");
554 return -EINVAL;
555 }
556
557 m->notify_socket = strappend(e, "/systemd/notify");
558 }
559 if (!m->notify_socket)
560 return log_oom();
561
562 strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)-1);
563 r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
564 if (r < 0) {
565 log_error("bind(@%s) failed: %m", sa.un.sun_path+1);
566 return -errno;
567 }
568
569 r = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
570 if (r < 0) {
571 log_error("SO_PASSCRED failed: %m");
572 return -errno;
573 }
574
575 m->notify_fd = fd;
576 fd = -1;
577
578 log_debug("Using notification socket %s", m->notify_socket);
579 }
580
581 if (!m->notify_event_source) {
582 r = sd_event_add_io(m->event, &m->notify_event_source, m->notify_fd, EPOLLIN, manager_dispatch_notify_fd, m);
583 if (r < 0) {
584 log_error("Failed to allocate notify event source: %s", strerror(-r));
585 return -errno;
586 }
587
588 /* Process signals a bit earlier than SIGCHLD, so that we can
589 * still identify to which service an exit message belongs */
590 r = sd_event_source_set_priority(m->notify_event_source, -7);
591 if (r < 0) {
592 log_error("Failed to set priority of notify event source: %s", strerror(-r));
593 return r;
594 }
595 }
596
597 return 0;
598 }
599
600 static int manager_setup_kdbus(Manager *m) {
601 #ifdef ENABLE_KDBUS
602 _cleanup_free_ char *p = NULL;
603
604 assert(m);
605
606 if (m->test_run || m->kdbus_fd >= 0)
607 return 0;
608
609 m->kdbus_fd = bus_kernel_create_bus(m->running_as == SYSTEMD_SYSTEM ? "system" : "user", m->running_as == SYSTEMD_SYSTEM, &p);
610 if (m->kdbus_fd < 0) {
611 log_debug("Failed to set up kdbus: %s", strerror(-m->kdbus_fd));
612 return m->kdbus_fd;
613 }
614
615 log_debug("Successfully set up kdbus on %s", p);
616
617 /* Create the namespace directory here, so that the contents
618 * of that directory is not visible to non-root users. This is
619 * necessary to ensure that users cannot get access to busses
620 * of virtualized users when no UID namespacing is used. */
621 if (m->running_as == SYSTEMD_SYSTEM)
622 mkdir_p_label("/dev/kdbus/domain", 0700);
623 #endif
624
625 return 0;
626 }
627
628 static int manager_connect_bus(Manager *m, bool reexecuting) {
629 bool try_bus_connect;
630
631 assert(m);
632
633 if (m->test_run)
634 return 0;
635
636 try_bus_connect =
637 m->kdbus_fd >= 0 ||
638 reexecuting ||
639 (m->running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS"));
640
641 /* Try to connect to the busses, if possible. */
642 return bus_init(m, try_bus_connect);
643 }
644
645 static unsigned manager_dispatch_cleanup_queue(Manager *m) {
646 Unit *u;
647 unsigned n = 0;
648
649 assert(m);
650
651 while ((u = m->cleanup_queue)) {
652 assert(u->in_cleanup_queue);
653
654 unit_free(u);
655 n++;
656 }
657
658 return n;
659 }
660
661 enum {
662 GC_OFFSET_IN_PATH, /* This one is on the path we were traveling */
663 GC_OFFSET_UNSURE, /* No clue */
664 GC_OFFSET_GOOD, /* We still need this unit */
665 GC_OFFSET_BAD, /* We don't need this unit anymore */
666 _GC_OFFSET_MAX
667 };
668
669 static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
670 Iterator i;
671 Unit *other;
672 bool is_bad;
673
674 assert(u);
675
676 if (u->gc_marker == gc_marker + GC_OFFSET_GOOD ||
677 u->gc_marker == gc_marker + GC_OFFSET_BAD ||
678 u->gc_marker == gc_marker + GC_OFFSET_IN_PATH)
679 return;
680
681 if (u->in_cleanup_queue)
682 goto bad;
683
684 if (unit_check_gc(u))
685 goto good;
686
687 u->gc_marker = gc_marker + GC_OFFSET_IN_PATH;
688
689 is_bad = true;
690
691 SET_FOREACH(other, u->dependencies[UNIT_REFERENCED_BY], i) {
692 unit_gc_sweep(other, gc_marker);
693
694 if (other->gc_marker == gc_marker + GC_OFFSET_GOOD)
695 goto good;
696
697 if (other->gc_marker != gc_marker + GC_OFFSET_BAD)
698 is_bad = false;
699 }
700
701 if (is_bad)
702 goto bad;
703
704 /* We were unable to find anything out about this entry, so
705 * let's investigate it later */
706 u->gc_marker = gc_marker + GC_OFFSET_UNSURE;
707 unit_add_to_gc_queue(u);
708 return;
709
710 bad:
711 /* We definitely know that this one is not useful anymore, so
712 * let's mark it for deletion */
713 u->gc_marker = gc_marker + GC_OFFSET_BAD;
714 unit_add_to_cleanup_queue(u);
715 return;
716
717 good:
718 u->gc_marker = gc_marker + GC_OFFSET_GOOD;
719 }
720
721 static unsigned manager_dispatch_gc_queue(Manager *m) {
722 Unit *u;
723 unsigned n = 0;
724 unsigned gc_marker;
725
726 assert(m);
727
728 /* log_debug("Running GC..."); */
729
730 m->gc_marker += _GC_OFFSET_MAX;
731 if (m->gc_marker + _GC_OFFSET_MAX <= _GC_OFFSET_MAX)
732 m->gc_marker = 1;
733
734 gc_marker = m->gc_marker;
735
736 while ((u = m->gc_queue)) {
737 assert(u->in_gc_queue);
738
739 unit_gc_sweep(u, gc_marker);
740
741 LIST_REMOVE(gc_queue, m->gc_queue, u);
742 u->in_gc_queue = false;
743
744 n++;
745
746 if (u->gc_marker == gc_marker + GC_OFFSET_BAD ||
747 u->gc_marker == gc_marker + GC_OFFSET_UNSURE) {
748 log_debug_unit(u->id, "Collecting %s", u->id);
749 u->gc_marker = gc_marker + GC_OFFSET_BAD;
750 unit_add_to_cleanup_queue(u);
751 }
752 }
753
754 m->n_in_gc_queue = 0;
755
756 return n;
757 }
758
759 static void manager_clear_jobs_and_units(Manager *m) {
760 Unit *u;
761
762 assert(m);
763
764 while ((u = hashmap_first(m->units)))
765 unit_free(u);
766
767 manager_dispatch_cleanup_queue(m);
768
769 assert(!m->load_queue);
770 assert(!m->run_queue);
771 assert(!m->dbus_unit_queue);
772 assert(!m->dbus_job_queue);
773 assert(!m->cleanup_queue);
774 assert(!m->gc_queue);
775
776 assert(hashmap_isempty(m->jobs));
777 assert(hashmap_isempty(m->units));
778
779 m->n_on_console = 0;
780 m->n_running_jobs = 0;
781 }
782
783 void manager_free(Manager *m) {
784 UnitType c;
785 int i;
786
787 assert(m);
788
789 manager_clear_jobs_and_units(m);
790
791 for (c = 0; c < _UNIT_TYPE_MAX; c++)
792 if (unit_vtable[c]->shutdown)
793 unit_vtable[c]->shutdown(m);
794
795 /* If we reexecute ourselves, we keep the root cgroup
796 * around */
797 manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE);
798
799 manager_undo_generators(m);
800
801 bus_done(m);
802
803 hashmap_free(m->units);
804 hashmap_free(m->jobs);
805 hashmap_free(m->watch_pids1);
806 hashmap_free(m->watch_pids2);
807 hashmap_free(m->watch_bus);
808
809 set_free(m->startup_units);
810 set_free(m->failed_units);
811
812 sd_event_source_unref(m->signal_event_source);
813 sd_event_source_unref(m->notify_event_source);
814 sd_event_source_unref(m->time_change_event_source);
815 sd_event_source_unref(m->jobs_in_progress_event_source);
816 sd_event_source_unref(m->idle_pipe_event_source);
817 sd_event_source_unref(m->run_queue_event_source);
818
819 safe_close(m->signal_fd);
820 safe_close(m->notify_fd);
821 safe_close(m->time_change_fd);
822 safe_close(m->kdbus_fd);
823
824 manager_close_idle_pipe(m);
825
826 udev_unref(m->udev);
827 sd_event_unref(m->event);
828
829 free(m->notify_socket);
830
831 lookup_paths_free(&m->lookup_paths);
832 strv_free(m->environment);
833
834 hashmap_free(m->cgroup_unit);
835 set_free_free(m->unit_path_cache);
836
837 free(m->switch_root);
838 free(m->switch_root_init);
839
840 for (i = 0; i < _RLIMIT_MAX; i++)
841 free(m->rlimit[i]);
842
843 assert(hashmap_isempty(m->units_requiring_mounts_for));
844 hashmap_free(m->units_requiring_mounts_for);
845
846 free(m);
847 }
848
849 int manager_enumerate(Manager *m) {
850 int r = 0, q;
851 UnitType c;
852
853 assert(m);
854
855 /* Let's ask every type to load all units from disk/kernel
856 * that it might know */
857 for (c = 0; c < _UNIT_TYPE_MAX; c++)
858 if (unit_vtable[c]->enumerate) {
859 q = unit_vtable[c]->enumerate(m);
860 if (q < 0)
861 r = q;
862 }
863
864 manager_dispatch_load_queue(m);
865 return r;
866 }
867
868 static int manager_coldplug(Manager *m) {
869 int r = 0;
870 Iterator i;
871 Unit *u;
872 char *k;
873
874 assert(m);
875
876 /* Then, let's set up their initial state. */
877 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
878 int q;
879
880 /* ignore aliases */
881 if (u->id != k)
882 continue;
883
884 q = unit_coldplug(u);
885 if (q < 0)
886 r = q;
887 }
888
889 return r;
890 }
891
892 static void manager_build_unit_path_cache(Manager *m) {
893 char **i;
894 _cleanup_free_ DIR *d = NULL;
895 int r;
896
897 assert(m);
898
899 set_free_free(m->unit_path_cache);
900
901 m->unit_path_cache = set_new(string_hash_func, string_compare_func);
902 if (!m->unit_path_cache) {
903 log_error("Failed to allocate unit path cache.");
904 return;
905 }
906
907 /* This simply builds a list of files we know exist, so that
908 * we don't always have to go to disk */
909
910 STRV_FOREACH(i, m->lookup_paths.unit_path) {
911 struct dirent *de;
912
913 d = opendir(*i);
914 if (!d) {
915 if (errno != ENOENT)
916 log_error("Failed to open directory %s: %m", *i);
917 continue;
918 }
919
920 while ((de = readdir(d))) {
921 char *p;
922
923 if (ignore_file(de->d_name))
924 continue;
925
926 p = strjoin(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL);
927 if (!p) {
928 r = -ENOMEM;
929 goto fail;
930 }
931
932 r = set_consume(m->unit_path_cache, p);
933 if (r < 0)
934 goto fail;
935 }
936
937 closedir(d);
938 d = NULL;
939 }
940
941 return;
942
943 fail:
944 log_error("Failed to build unit path cache: %s", strerror(-r));
945
946 set_free_free(m->unit_path_cache);
947 m->unit_path_cache = NULL;
948 }
949
950
951 static int manager_distribute_fds(Manager *m, FDSet *fds) {
952 Unit *u;
953 Iterator i;
954 int r;
955
956 assert(m);
957
958 HASHMAP_FOREACH(u, m->units, i) {
959
960 if (fdset_size(fds) <= 0)
961 break;
962
963 if (UNIT_VTABLE(u)->distribute_fds) {
964 r = UNIT_VTABLE(u)->distribute_fds(u, fds);
965 if (r < 0)
966 return r;
967 }
968 }
969
970 return 0;
971 }
972
973 int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
974 int r, q;
975
976 assert(m);
977
978 dual_timestamp_get(&m->generators_start_timestamp);
979 manager_run_generators(m);
980 dual_timestamp_get(&m->generators_finish_timestamp);
981
982 r = lookup_paths_init(
983 &m->lookup_paths, m->running_as, true,
984 NULL,
985 m->generator_unit_path,
986 m->generator_unit_path_early,
987 m->generator_unit_path_late);
988 if (r < 0)
989 return r;
990
991 manager_build_unit_path_cache(m);
992
993 /* If we will deserialize make sure that during enumeration
994 * this is already known, so we increase the counter here
995 * already */
996 if (serialization)
997 m->n_reloading ++;
998
999 /* First, enumerate what we can from all config files */
1000 dual_timestamp_get(&m->units_load_start_timestamp);
1001 r = manager_enumerate(m);
1002 dual_timestamp_get(&m->units_load_finish_timestamp);
1003
1004 /* Second, deserialize if there is something to deserialize */
1005 if (serialization)
1006 r = manager_deserialize(m, serialization, fds);
1007
1008 /* Any fds left? Find some unit which wants them. This is
1009 * useful to allow container managers to pass some file
1010 * descriptors to us pre-initialized. This enables
1011 * socket-based activation of entire containers. */
1012 if (fdset_size(fds) > 0) {
1013 q = manager_distribute_fds(m, fds);
1014 if (q < 0 && r == 0)
1015 r = q;
1016 }
1017
1018 /* We might have deserialized the notify fd, but if we didn't
1019 * then let's create the bus now */
1020 q = manager_setup_notify(m);
1021 if (q < 0 && r == 0)
1022 r = q;
1023
1024 /* We might have deserialized the kdbus control fd, but if we
1025 * didn't, then let's create the bus now. */
1026 manager_setup_kdbus(m);
1027 manager_connect_bus(m, !!serialization);
1028 bus_track_coldplug(m, &m->subscribed, &m->deserialized_subscribed);
1029
1030 /* Third, fire things up! */
1031 q = manager_coldplug(m);
1032 if (q < 0 && r == 0)
1033 r = q;
1034
1035 if (serialization) {
1036 assert(m->n_reloading > 0);
1037 m->n_reloading --;
1038
1039 /* Let's wait for the UnitNew/JobNew messages being
1040 * sent, before we notify that the reload is
1041 * finished */
1042 m->send_reloading_done = true;
1043 }
1044
1045 return r;
1046 }
1047
1048 int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, sd_bus_error *e, Job **_ret) {
1049 int r;
1050 Transaction *tr;
1051
1052 assert(m);
1053 assert(type < _JOB_TYPE_MAX);
1054 assert(unit);
1055 assert(mode < _JOB_MODE_MAX);
1056
1057 if (mode == JOB_ISOLATE && type != JOB_START) {
1058 sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
1059 return -EINVAL;
1060 }
1061
1062 if (mode == JOB_ISOLATE && !unit->allow_isolate) {
1063 sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
1064 return -EPERM;
1065 }
1066
1067 log_debug_unit(unit->id,
1068 "Trying to enqueue job %s/%s/%s", unit->id,
1069 job_type_to_string(type), job_mode_to_string(mode));
1070
1071 job_type_collapse(&type, unit);
1072
1073 tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY);
1074 if (!tr)
1075 return -ENOMEM;
1076
1077 r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, override, false,
1078 mode == JOB_IGNORE_DEPENDENCIES || mode == JOB_IGNORE_REQUIREMENTS,
1079 mode == JOB_IGNORE_DEPENDENCIES, e);
1080 if (r < 0)
1081 goto tr_abort;
1082
1083 if (mode == JOB_ISOLATE) {
1084 r = transaction_add_isolate_jobs(tr, m);
1085 if (r < 0)
1086 goto tr_abort;
1087 }
1088
1089 r = transaction_activate(tr, m, mode, e);
1090 if (r < 0)
1091 goto tr_abort;
1092
1093 log_debug_unit(unit->id,
1094 "Enqueued job %s/%s as %u", unit->id,
1095 job_type_to_string(type), (unsigned) tr->anchor_job->id);
1096
1097 if (_ret)
1098 *_ret = tr->anchor_job;
1099
1100 transaction_free(tr);
1101 return 0;
1102
1103 tr_abort:
1104 transaction_abort(tr);
1105 transaction_free(tr);
1106 return r;
1107 }
1108
1109 int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, sd_bus_error *e, Job **_ret) {
1110 Unit *unit;
1111 int r;
1112
1113 assert(m);
1114 assert(type < _JOB_TYPE_MAX);
1115 assert(name);
1116 assert(mode < _JOB_MODE_MAX);
1117
1118 r = manager_load_unit(m, name, NULL, NULL, &unit);
1119 if (r < 0)
1120 return r;
1121
1122 return manager_add_job(m, type, unit, mode, override, e, _ret);
1123 }
1124
1125 Job *manager_get_job(Manager *m, uint32_t id) {
1126 assert(m);
1127
1128 return hashmap_get(m->jobs, UINT32_TO_PTR(id));
1129 }
1130
1131 Unit *manager_get_unit(Manager *m, const char *name) {
1132 assert(m);
1133 assert(name);
1134
1135 return hashmap_get(m->units, name);
1136 }
1137
1138 unsigned manager_dispatch_load_queue(Manager *m) {
1139 Unit *u;
1140 unsigned n = 0;
1141
1142 assert(m);
1143
1144 /* Make sure we are not run recursively */
1145 if (m->dispatching_load_queue)
1146 return 0;
1147
1148 m->dispatching_load_queue = true;
1149
1150 /* Dispatches the load queue. Takes a unit from the queue and
1151 * tries to load its data until the queue is empty */
1152
1153 while ((u = m->load_queue)) {
1154 assert(u->in_load_queue);
1155
1156 unit_load(u);
1157 n++;
1158 }
1159
1160 m->dispatching_load_queue = false;
1161 return n;
1162 }
1163
1164 int manager_load_unit_prepare(
1165 Manager *m,
1166 const char *name,
1167 const char *path,
1168 sd_bus_error *e,
1169 Unit **_ret) {
1170
1171 Unit *ret;
1172 UnitType t;
1173 int r;
1174
1175 assert(m);
1176 assert(name || path);
1177
1178 /* This will prepare the unit for loading, but not actually
1179 * load anything from disk. */
1180
1181 if (path && !is_path(path))
1182 return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
1183
1184 if (!name)
1185 name = basename(path);
1186
1187 t = unit_name_to_type(name);
1188
1189 if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, TEMPLATE_INVALID))
1190 return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
1191
1192 ret = manager_get_unit(m, name);
1193 if (ret) {
1194 *_ret = ret;
1195 return 1;
1196 }
1197
1198 ret = unit_new(m, unit_vtable[t]->object_size);
1199 if (!ret)
1200 return -ENOMEM;
1201
1202 if (path) {
1203 ret->fragment_path = strdup(path);
1204 if (!ret->fragment_path) {
1205 unit_free(ret);
1206 return -ENOMEM;
1207 }
1208 }
1209
1210 r = unit_add_name(ret, name);
1211 if (r < 0) {
1212 unit_free(ret);
1213 return r;
1214 }
1215
1216 unit_add_to_load_queue(ret);
1217 unit_add_to_dbus_queue(ret);
1218 unit_add_to_gc_queue(ret);
1219
1220 if (_ret)
1221 *_ret = ret;
1222
1223 return 0;
1224 }
1225
1226 int manager_load_unit(
1227 Manager *m,
1228 const char *name,
1229 const char *path,
1230 sd_bus_error *e,
1231 Unit **_ret) {
1232
1233 int r;
1234
1235 assert(m);
1236
1237 /* This will load the service information files, but not actually
1238 * start any services or anything. */
1239
1240 r = manager_load_unit_prepare(m, name, path, e, _ret);
1241 if (r != 0)
1242 return r;
1243
1244 manager_dispatch_load_queue(m);
1245
1246 if (_ret)
1247 *_ret = unit_follow_merge(*_ret);
1248
1249 return 0;
1250 }
1251
1252 void manager_dump_jobs(Manager *s, FILE *f, const char *prefix) {
1253 Iterator i;
1254 Job *j;
1255
1256 assert(s);
1257 assert(f);
1258
1259 HASHMAP_FOREACH(j, s->jobs, i)
1260 job_dump(j, f, prefix);
1261 }
1262
1263 void manager_dump_units(Manager *s, FILE *f, const char *prefix) {
1264 Iterator i;
1265 Unit *u;
1266 const char *t;
1267
1268 assert(s);
1269 assert(f);
1270
1271 HASHMAP_FOREACH_KEY(u, t, s->units, i)
1272 if (u->id == t)
1273 unit_dump(u, f, prefix);
1274 }
1275
1276 void manager_clear_jobs(Manager *m) {
1277 Job *j;
1278
1279 assert(m);
1280
1281 while ((j = hashmap_first(m->jobs)))
1282 /* No need to recurse. We're cancelling all jobs. */
1283 job_finish_and_invalidate(j, JOB_CANCELED, false);
1284 }
1285
1286 static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) {
1287 Manager *m = userdata;
1288 Job *j;
1289
1290 assert(source);
1291 assert(m);
1292
1293 while ((j = m->run_queue)) {
1294 assert(j->installed);
1295 assert(j->in_run_queue);
1296
1297 job_run_and_invalidate(j);
1298 }
1299
1300 if (m->n_running_jobs > 0)
1301 manager_watch_jobs_in_progress(m);
1302
1303 if (m->n_on_console > 0)
1304 manager_watch_idle_pipe(m);
1305
1306 return 1;
1307 }
1308
1309 static unsigned manager_dispatch_dbus_queue(Manager *m) {
1310 Job *j;
1311 Unit *u;
1312 unsigned n = 0;
1313
1314 assert(m);
1315
1316 if (m->dispatching_dbus_queue)
1317 return 0;
1318
1319 m->dispatching_dbus_queue = true;
1320
1321 while ((u = m->dbus_unit_queue)) {
1322 assert(u->in_dbus_queue);
1323
1324 bus_unit_send_change_signal(u);
1325 n++;
1326 }
1327
1328 while ((j = m->dbus_job_queue)) {
1329 assert(j->in_dbus_queue);
1330
1331 bus_job_send_change_signal(j);
1332 n++;
1333 }
1334
1335 m->dispatching_dbus_queue = false;
1336
1337 if (m->send_reloading_done) {
1338 m->send_reloading_done = false;
1339
1340 bus_manager_send_reloading(m, false);
1341 }
1342
1343 if (m->queued_message)
1344 bus_send_queued_message(m);
1345
1346 return n;
1347 }
1348
1349 static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char *buf, size_t n) {
1350 _cleanup_strv_free_ char **tags = NULL;
1351
1352 assert(m);
1353 assert(u);
1354 assert(buf);
1355 assert(n > 0);
1356
1357 tags = strv_split(buf, "\n\r");
1358 if (!tags) {
1359 log_oom();
1360 return;
1361 }
1362
1363 log_debug_unit(u->id, "Got notification message for unit %s", u->id);
1364
1365 if (UNIT_VTABLE(u)->notify_message)
1366 UNIT_VTABLE(u)->notify_message(u, pid, tags);
1367 }
1368
1369 static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1370 Manager *m = userdata;
1371 ssize_t n;
1372
1373 assert(m);
1374 assert(m->notify_fd == fd);
1375
1376 if (revents != EPOLLIN) {
1377 log_warning("Got unexpected poll event for notify fd.");
1378 return 0;
1379 }
1380
1381 for (;;) {
1382 char buf[4096];
1383 struct iovec iovec = {
1384 .iov_base = buf,
1385 .iov_len = sizeof(buf)-1,
1386 };
1387 bool found = false;
1388
1389 union {
1390 struct cmsghdr cmsghdr;
1391 uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
1392 } control = {};
1393
1394 struct msghdr msghdr = {
1395 .msg_iov = &iovec,
1396 .msg_iovlen = 1,
1397 .msg_control = &control,
1398 .msg_controllen = sizeof(control),
1399 };
1400 struct ucred *ucred;
1401 Unit *u;
1402
1403 n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT);
1404 if (n <= 0) {
1405 if (n == 0)
1406 return -EIO;
1407
1408 if (errno == EAGAIN || errno == EINTR)
1409 break;
1410
1411 return -errno;
1412 }
1413
1414 if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
1415 control.cmsghdr.cmsg_level != SOL_SOCKET ||
1416 control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
1417 control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
1418 log_warning("Received notify message without credentials. Ignoring.");
1419 continue;
1420 }
1421
1422 ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
1423
1424 assert((size_t) n < sizeof(buf));
1425 buf[n] = 0;
1426
1427 u = manager_get_unit_by_pid(m, ucred->pid);
1428 if (u) {
1429 manager_invoke_notify_message(m, u, ucred->pid, buf, n);
1430 found = true;
1431 }
1432
1433 u = hashmap_get(m->watch_pids1, LONG_TO_PTR(ucred->pid));
1434 if (u) {
1435 manager_invoke_notify_message(m, u, ucred->pid, buf, n);
1436 found = true;
1437 }
1438
1439 u = hashmap_get(m->watch_pids2, LONG_TO_PTR(ucred->pid));
1440 if (u) {
1441 manager_invoke_notify_message(m, u, ucred->pid, buf, n);
1442 found = true;
1443 }
1444
1445 if (!found)
1446 log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid);
1447 }
1448
1449 return 0;
1450 }
1451
1452 static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
1453 assert(m);
1454 assert(u);
1455 assert(si);
1456
1457 log_debug_unit(u->id, "Child "PID_FMT" belongs to %s", si->si_pid, u->id);
1458
1459 unit_unwatch_pid(u, si->si_pid);
1460 UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
1461 }
1462
1463 static int manager_dispatch_sigchld(Manager *m) {
1464 assert(m);
1465
1466 for (;;) {
1467 siginfo_t si = {};
1468
1469 /* First we call waitd() for a PID and do not reap the
1470 * zombie. That way we can still access /proc/$PID for
1471 * it while it is a zombie. */
1472 if (waitid(P_ALL, 0, &si, WEXITED|WNOHANG|WNOWAIT) < 0) {
1473
1474 if (errno == ECHILD)
1475 break;
1476
1477 if (errno == EINTR)
1478 continue;
1479
1480 return -errno;
1481 }
1482
1483 if (si.si_pid <= 0)
1484 break;
1485
1486 if (si.si_code == CLD_EXITED || si.si_code == CLD_KILLED || si.si_code == CLD_DUMPED) {
1487 _cleanup_free_ char *name = NULL;
1488 Unit *u;
1489
1490 get_process_comm(si.si_pid, &name);
1491
1492 log_debug("Child "PID_FMT" (%s) died (code=%s, status=%i/%s)",
1493 si.si_pid, strna(name),
1494 sigchld_code_to_string(si.si_code),
1495 si.si_status,
1496 strna(si.si_code == CLD_EXITED
1497 ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL)
1498 : signal_to_string(si.si_status)));
1499
1500 /* And now figure out the unit this belongs
1501 * to, it might be multiple... */
1502 u = manager_get_unit_by_pid(m, si.si_pid);
1503 if (u)
1504 invoke_sigchld_event(m, u, &si);
1505 u = hashmap_get(m->watch_pids1, LONG_TO_PTR(si.si_pid));
1506 if (u)
1507 invoke_sigchld_event(m, u, &si);
1508 u = hashmap_get(m->watch_pids2, LONG_TO_PTR(si.si_pid));
1509 if (u)
1510 invoke_sigchld_event(m, u, &si);
1511 }
1512
1513 /* And now, we actually reap the zombie. */
1514 if (waitid(P_PID, si.si_pid, &si, WEXITED) < 0) {
1515 if (errno == EINTR)
1516 continue;
1517
1518 return -errno;
1519 }
1520 }
1521
1522 return 0;
1523 }
1524
1525 static int manager_start_target(Manager *m, const char *name, JobMode mode) {
1526 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1527 int r;
1528
1529 log_debug_unit(name, "Activating special unit %s", name);
1530
1531 r = manager_add_job_by_name(m, JOB_START, name, mode, true, &error, NULL);
1532 if (r < 0)
1533 log_error_unit(name, "Failed to enqueue %s job: %s", name, bus_error_message(&error, r));
1534
1535 return r;
1536 }
1537
1538 static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1539 Manager *m = userdata;
1540 ssize_t n;
1541 struct signalfd_siginfo sfsi;
1542 bool sigchld = false;
1543
1544 assert(m);
1545 assert(m->signal_fd == fd);
1546
1547 if (revents != EPOLLIN) {
1548 log_warning("Got unexpected events from signal file descriptor.");
1549 return 0;
1550 }
1551
1552 for (;;) {
1553 n = read(m->signal_fd, &sfsi, sizeof(sfsi));
1554 if (n != sizeof(sfsi)) {
1555
1556 if (n >= 0)
1557 return -EIO;
1558
1559 if (errno == EINTR || errno == EAGAIN)
1560 break;
1561
1562 return -errno;
1563 }
1564
1565 log_received_signal(sfsi.ssi_signo == SIGCHLD ||
1566 (sfsi.ssi_signo == SIGTERM && m->running_as == SYSTEMD_USER)
1567 ? LOG_DEBUG : LOG_INFO,
1568 &sfsi);
1569
1570 switch (sfsi.ssi_signo) {
1571
1572 case SIGCHLD:
1573 sigchld = true;
1574 break;
1575
1576 case SIGTERM:
1577 if (m->running_as == SYSTEMD_SYSTEM) {
1578 /* This is for compatibility with the
1579 * original sysvinit */
1580 m->exit_code = MANAGER_REEXECUTE;
1581 break;
1582 }
1583
1584 /* Fall through */
1585
1586 case SIGINT:
1587 if (m->running_as == SYSTEMD_SYSTEM) {
1588 manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
1589 break;
1590 }
1591
1592 /* Run the exit target if there is one, if not, just exit. */
1593 if (manager_start_target(m, SPECIAL_EXIT_TARGET, JOB_REPLACE) < 0) {
1594 m->exit_code = MANAGER_EXIT;
1595 return 0;
1596 }
1597
1598 break;
1599
1600 case SIGWINCH:
1601 if (m->running_as == SYSTEMD_SYSTEM)
1602 manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE);
1603
1604 /* This is a nop on non-init */
1605 break;
1606
1607 case SIGPWR:
1608 if (m->running_as == SYSTEMD_SYSTEM)
1609 manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE);
1610
1611 /* This is a nop on non-init */
1612 break;
1613
1614 case SIGUSR1: {
1615 Unit *u;
1616
1617 u = manager_get_unit(m, SPECIAL_DBUS_SERVICE);
1618
1619 if (!u || UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) {
1620 log_info("Trying to reconnect to bus...");
1621 bus_init(m, true);
1622 }
1623
1624 if (!u || !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) {
1625 log_info("Loading D-Bus service...");
1626 manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE);
1627 }
1628
1629 break;
1630 }
1631
1632 case SIGUSR2: {
1633 _cleanup_free_ char *dump = NULL;
1634 _cleanup_fclose_ FILE *f = NULL;
1635 size_t size;
1636
1637 f = open_memstream(&dump, &size);
1638 if (!f) {
1639 log_warning("Failed to allocate memory stream.");
1640 break;
1641 }
1642
1643 manager_dump_units(m, f, "\t");
1644 manager_dump_jobs(m, f, "\t");
1645
1646 if (ferror(f)) {
1647 log_warning("Failed to write status stream");
1648 break;
1649 }
1650
1651 if (fflush(f)) {
1652 log_warning("Failed to flush status stream");
1653 break;
1654 }
1655
1656 log_dump(LOG_INFO, dump);
1657 break;
1658 }
1659
1660 case SIGHUP:
1661 m->exit_code = MANAGER_RELOAD;
1662 break;
1663
1664 default: {
1665
1666 /* Starting SIGRTMIN+0 */
1667 static const char * const target_table[] = {
1668 [0] = SPECIAL_DEFAULT_TARGET,
1669 [1] = SPECIAL_RESCUE_TARGET,
1670 [2] = SPECIAL_EMERGENCY_TARGET,
1671 [3] = SPECIAL_HALT_TARGET,
1672 [4] = SPECIAL_POWEROFF_TARGET,
1673 [5] = SPECIAL_REBOOT_TARGET,
1674 [6] = SPECIAL_KEXEC_TARGET
1675 };
1676
1677 /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
1678 static const ManagerExitCode code_table[] = {
1679 [0] = MANAGER_HALT,
1680 [1] = MANAGER_POWEROFF,
1681 [2] = MANAGER_REBOOT,
1682 [3] = MANAGER_KEXEC
1683 };
1684
1685 if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
1686 (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
1687 int idx = (int) sfsi.ssi_signo - SIGRTMIN;
1688 manager_start_target(m, target_table[idx],
1689 (idx == 1 || idx == 2) ? JOB_ISOLATE : JOB_REPLACE);
1690 break;
1691 }
1692
1693 if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
1694 (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(code_table)) {
1695 m->exit_code = code_table[sfsi.ssi_signo - SIGRTMIN - 13];
1696 break;
1697 }
1698
1699 switch (sfsi.ssi_signo - SIGRTMIN) {
1700
1701 case 20:
1702 log_debug("Enabling showing of status.");
1703 manager_set_show_status(m, SHOW_STATUS_YES);
1704 break;
1705
1706 case 21:
1707 log_debug("Disabling showing of status.");
1708 manager_set_show_status(m, SHOW_STATUS_NO);
1709 break;
1710
1711 case 22:
1712 log_set_max_level(LOG_DEBUG);
1713 log_notice("Setting log level to debug.");
1714 break;
1715
1716 case 23:
1717 log_set_max_level(LOG_INFO);
1718 log_notice("Setting log level to info.");
1719 break;
1720
1721 case 24:
1722 if (m->running_as == SYSTEMD_USER) {
1723 m->exit_code = MANAGER_EXIT;
1724 return 0;
1725 }
1726
1727 /* This is a nop on init */
1728 break;
1729
1730 case 26:
1731 case 29: /* compatibility: used to be mapped to LOG_TARGET_SYSLOG_OR_KMSG */
1732 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1733 log_notice("Setting log target to journal-or-kmsg.");
1734 break;
1735
1736 case 27:
1737 log_set_target(LOG_TARGET_CONSOLE);
1738 log_notice("Setting log target to console.");
1739 break;
1740
1741 case 28:
1742 log_set_target(LOG_TARGET_KMSG);
1743 log_notice("Setting log target to kmsg.");
1744 break;
1745
1746 default:
1747 log_warning("Got unhandled signal <%s>.", signal_to_string(sfsi.ssi_signo));
1748 }
1749 }
1750 }
1751 }
1752
1753 if (sigchld)
1754 manager_dispatch_sigchld(m);
1755
1756 return 0;
1757 }
1758
1759 static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1760 Manager *m = userdata;
1761 Iterator i;
1762 Unit *u;
1763
1764 assert(m);
1765 assert(m->time_change_fd == fd);
1766
1767 log_struct(LOG_INFO,
1768 MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
1769 "MESSAGE=Time has been changed",
1770 NULL);
1771
1772 /* Restart the watch */
1773 m->time_change_event_source = sd_event_source_unref(m->time_change_event_source);
1774 m->time_change_fd = safe_close(m->time_change_fd);
1775
1776 manager_setup_time_change(m);
1777
1778 HASHMAP_FOREACH(u, m->units, i)
1779 if (UNIT_VTABLE(u)->time_change)
1780 UNIT_VTABLE(u)->time_change(u);
1781
1782 return 0;
1783 }
1784
1785 static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1786 Manager *m = userdata;
1787
1788 assert(m);
1789 assert(m->idle_pipe[2] == fd);
1790
1791 m->no_console_output = m->n_on_console > 0;
1792
1793 m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
1794 manager_close_idle_pipe(m);
1795
1796 return 0;
1797 }
1798
1799 static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) {
1800 Manager *m = userdata;
1801 int r;
1802 uint64_t next;
1803
1804 assert(m);
1805 assert(source);
1806
1807 manager_print_jobs_in_progress(m);
1808
1809 next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_PERIOD_USEC;
1810 r = sd_event_source_set_time(source, next);
1811 if (r < 0)
1812 return r;
1813
1814 return sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
1815 }
1816
1817 int manager_loop(Manager *m) {
1818 int r;
1819
1820 RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000);
1821
1822 assert(m);
1823 m->exit_code = MANAGER_OK;
1824
1825 /* Release the path cache */
1826 set_free_free(m->unit_path_cache);
1827 m->unit_path_cache = NULL;
1828
1829 manager_check_finished(m);
1830
1831 /* There might still be some zombies hanging around from
1832 * before we were exec()'ed. Let's reap them. */
1833 r = manager_dispatch_sigchld(m);
1834 if (r < 0)
1835 return r;
1836
1837 while (m->exit_code == MANAGER_OK) {
1838 usec_t wait_usec;
1839
1840 if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM)
1841 watchdog_ping();
1842
1843 if (!ratelimit_test(&rl)) {
1844 /* Yay, something is going seriously wrong, pause a little */
1845 log_warning("Looping too fast. Throttling execution a little.");
1846 sleep(1);
1847 continue;
1848 }
1849
1850 if (manager_dispatch_load_queue(m) > 0)
1851 continue;
1852
1853 if (manager_dispatch_gc_queue(m) > 0)
1854 continue;
1855
1856 if (manager_dispatch_cleanup_queue(m) > 0)
1857 continue;
1858
1859 if (manager_dispatch_cgroup_queue(m) > 0)
1860 continue;
1861
1862 if (manager_dispatch_dbus_queue(m) > 0)
1863 continue;
1864
1865 /* Sleep for half the watchdog time */
1866 if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM) {
1867 wait_usec = m->runtime_watchdog / 2;
1868 if (wait_usec <= 0)
1869 wait_usec = 1;
1870 } else
1871 wait_usec = USEC_INFINITY;
1872
1873 r = sd_event_run(m->event, wait_usec);
1874 if (r < 0) {
1875 log_error("Failed to run event loop: %s", strerror(-r));
1876 return r;
1877 }
1878 }
1879
1880 return m->exit_code;
1881 }
1882
1883 int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u) {
1884 _cleanup_free_ char *n = NULL;
1885 Unit *u;
1886 int r;
1887
1888 assert(m);
1889 assert(s);
1890 assert(_u);
1891
1892 r = unit_name_from_dbus_path(s, &n);
1893 if (r < 0)
1894 return r;
1895
1896 r = manager_load_unit(m, n, NULL, e, &u);
1897 if (r < 0)
1898 return r;
1899
1900 *_u = u;
1901
1902 return 0;
1903 }
1904
1905 int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) {
1906 const char *p;
1907 unsigned id;
1908 Job *j;
1909 int r;
1910
1911 assert(m);
1912 assert(s);
1913 assert(_j);
1914
1915 p = startswith(s, "/org/freedesktop/systemd1/job/");
1916 if (!p)
1917 return -EINVAL;
1918
1919 r = safe_atou(p, &id);
1920 if (r < 0)
1921 return r;
1922
1923 j = manager_get_job(m, id);
1924 if (!j)
1925 return -ENOENT;
1926
1927 *_j = j;
1928
1929 return 0;
1930 }
1931
1932 void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
1933
1934 #ifdef HAVE_AUDIT
1935 _cleanup_free_ char *p = NULL;
1936 int audit_fd;
1937
1938 audit_fd = get_audit_fd();
1939 if (audit_fd < 0)
1940 return;
1941
1942 /* Don't generate audit events if the service was already
1943 * started and we're just deserializing */
1944 if (m->n_reloading > 0)
1945 return;
1946
1947 if (m->running_as != SYSTEMD_SYSTEM)
1948 return;
1949
1950 if (u->type != UNIT_SERVICE)
1951 return;
1952
1953 p = unit_name_to_prefix_and_instance(u->id);
1954 if (!p) {
1955 log_error_unit(u->id,
1956 "Failed to allocate unit name for audit message: %s", strerror(ENOMEM));
1957 return;
1958 }
1959
1960 if (audit_log_user_comm_message(audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) {
1961 if (errno == EPERM) {
1962 /* We aren't allowed to send audit messages?
1963 * Then let's not retry again. */
1964 close_audit_fd();
1965 } else
1966 log_warning("Failed to send audit message: %m");
1967 }
1968 #endif
1969
1970 }
1971
1972 void manager_send_unit_plymouth(Manager *m, Unit *u) {
1973 union sockaddr_union sa = PLYMOUTH_SOCKET;
1974
1975 int n = 0;
1976 _cleanup_free_ char *message = NULL;
1977 _cleanup_close_ int fd = -1;
1978
1979 /* Don't generate plymouth events if the service was already
1980 * started and we're just deserializing */
1981 if (m->n_reloading > 0)
1982 return;
1983
1984 if (m->running_as != SYSTEMD_SYSTEM)
1985 return;
1986
1987 if (detect_container(NULL) > 0)
1988 return;
1989
1990 if (u->type != UNIT_SERVICE &&
1991 u->type != UNIT_MOUNT &&
1992 u->type != UNIT_SWAP)
1993 return;
1994
1995 /* We set SOCK_NONBLOCK here so that we rather drop the
1996 * message then wait for plymouth */
1997 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1998 if (fd < 0) {
1999 log_error("socket() failed: %m");
2000 return;
2001 }
2002
2003 if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
2004
2005 if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED))
2006 log_error("connect() failed: %m");
2007 return;
2008 }
2009
2010 if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) {
2011 log_oom();
2012 return;
2013 }
2014
2015 errno = 0;
2016 if (write(fd, message, n + 1) != n + 1)
2017 if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED))
2018 log_error("Failed to write Plymouth message: %m");
2019 }
2020
2021 void manager_dispatch_bus_name_owner_changed(
2022 Manager *m,
2023 const char *name,
2024 const char* old_owner,
2025 const char *new_owner) {
2026
2027 Unit *u;
2028
2029 assert(m);
2030 assert(name);
2031
2032 u = hashmap_get(m->watch_bus, name);
2033 if (!u)
2034 return;
2035
2036 UNIT_VTABLE(u)->bus_name_owner_change(u, name, old_owner, new_owner);
2037 }
2038
2039 int manager_open_serialization(Manager *m, FILE **_f) {
2040 const char *path;
2041 int fd = -1;
2042 FILE *f;
2043
2044 assert(_f);
2045
2046 path = m->running_as == SYSTEMD_SYSTEM ? "/run/systemd" : "/tmp";
2047 fd = open_tmpfile(path, O_RDWR|O_CLOEXEC);
2048 if (fd < 0)
2049 return -errno;
2050
2051 log_debug("Serializing state to %s", path);
2052
2053 f = fdopen(fd, "w+");
2054 if (!f) {
2055 safe_close(fd);
2056 return -errno;
2057 }
2058
2059 *_f = f;
2060
2061 return 0;
2062 }
2063
2064 int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
2065 Iterator i;
2066 Unit *u;
2067 const char *t;
2068 char **e;
2069 int r;
2070
2071 assert(m);
2072 assert(f);
2073 assert(fds);
2074
2075 m->n_reloading ++;
2076
2077 fprintf(f, "current-job-id=%i\n", m->current_job_id);
2078 fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
2079 fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs);
2080 fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs);
2081
2082 dual_timestamp_serialize(f, "firmware-timestamp", &m->firmware_timestamp);
2083 dual_timestamp_serialize(f, "loader-timestamp", &m->loader_timestamp);
2084 dual_timestamp_serialize(f, "kernel-timestamp", &m->kernel_timestamp);
2085 dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp);
2086
2087 if (!in_initrd()) {
2088 dual_timestamp_serialize(f, "userspace-timestamp", &m->userspace_timestamp);
2089 dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
2090 dual_timestamp_serialize(f, "security-start-timestamp", &m->security_start_timestamp);
2091 dual_timestamp_serialize(f, "security-finish-timestamp", &m->security_finish_timestamp);
2092 dual_timestamp_serialize(f, "generators-start-timestamp", &m->generators_start_timestamp);
2093 dual_timestamp_serialize(f, "generators-finish-timestamp", &m->generators_finish_timestamp);
2094 dual_timestamp_serialize(f, "units-load-start-timestamp", &m->units_load_start_timestamp);
2095 dual_timestamp_serialize(f, "units-load-finish-timestamp", &m->units_load_finish_timestamp);
2096 }
2097
2098 if (!switching_root) {
2099 STRV_FOREACH(e, m->environment) {
2100 _cleanup_free_ char *ce;
2101
2102 ce = cescape(*e);
2103 if (!ce)
2104 return -ENOMEM;
2105
2106 fprintf(f, "env=%s\n", *e);
2107 }
2108 }
2109
2110 if (m->notify_fd >= 0) {
2111 int copy;
2112
2113 copy = fdset_put_dup(fds, m->notify_fd);
2114 if (copy < 0)
2115 return copy;
2116
2117 fprintf(f, "notify-fd=%i\n", copy);
2118 fprintf(f, "notify-socket=%s\n", m->notify_socket);
2119 }
2120
2121 if (m->kdbus_fd >= 0) {
2122 int copy;
2123
2124 copy = fdset_put_dup(fds, m->kdbus_fd);
2125 if (copy < 0)
2126 return copy;
2127
2128 fprintf(f, "kdbus-fd=%i\n", copy);
2129 }
2130
2131 bus_track_serialize(m->subscribed, f);
2132
2133 fputc('\n', f);
2134
2135 HASHMAP_FOREACH_KEY(u, t, m->units, i) {
2136 if (u->id != t)
2137 continue;
2138
2139 /* Start marker */
2140 fputs(u->id, f);
2141 fputc('\n', f);
2142
2143 r = unit_serialize(u, f, fds, !switching_root);
2144 if (r < 0) {
2145 m->n_reloading --;
2146 return r;
2147 }
2148 }
2149
2150 assert(m->n_reloading > 0);
2151 m->n_reloading --;
2152
2153 if (ferror(f))
2154 return -EIO;
2155
2156 r = bus_fdset_add_all(m, fds);
2157 if (r < 0)
2158 return r;
2159
2160 return 0;
2161 }
2162
2163 int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
2164 int r = 0;
2165
2166 assert(m);
2167 assert(f);
2168
2169 log_debug("Deserializing state...");
2170
2171 m->n_reloading ++;
2172
2173 for (;;) {
2174 char line[LINE_MAX], *l;
2175
2176 if (!fgets(line, sizeof(line), f)) {
2177 if (feof(f))
2178 r = 0;
2179 else
2180 r = -errno;
2181
2182 goto finish;
2183 }
2184
2185 char_array_0(line);
2186 l = strstrip(line);
2187
2188 if (l[0] == 0)
2189 break;
2190
2191 if (startswith(l, "current-job-id=")) {
2192 uint32_t id;
2193
2194 if (safe_atou32(l+15, &id) < 0)
2195 log_debug("Failed to parse current job id value %s", l+15);
2196 else
2197 m->current_job_id = MAX(m->current_job_id, id);
2198
2199 } else if (startswith(l, "n-installed-jobs=")) {
2200 uint32_t n;
2201
2202 if (safe_atou32(l+17, &n) < 0)
2203 log_debug("Failed to parse installed jobs counter %s", l+17);
2204 else
2205 m->n_installed_jobs += n;
2206
2207 } else if (startswith(l, "n-failed-jobs=")) {
2208 uint32_t n;
2209
2210 if (safe_atou32(l+14, &n) < 0)
2211 log_debug("Failed to parse failed jobs counter %s", l+14);
2212 else
2213 m->n_failed_jobs += n;
2214
2215 } else if (startswith(l, "taint-usr=")) {
2216 int b;
2217
2218 b = parse_boolean(l+10);
2219 if (b < 0)
2220 log_debug("Failed to parse taint /usr flag %s", l+10);
2221 else
2222 m->taint_usr = m->taint_usr || b;
2223
2224 } else if (startswith(l, "firmware-timestamp="))
2225 dual_timestamp_deserialize(l+19, &m->firmware_timestamp);
2226 else if (startswith(l, "loader-timestamp="))
2227 dual_timestamp_deserialize(l+17, &m->loader_timestamp);
2228 else if (startswith(l, "kernel-timestamp="))
2229 dual_timestamp_deserialize(l+17, &m->kernel_timestamp);
2230 else if (startswith(l, "initrd-timestamp="))
2231 dual_timestamp_deserialize(l+17, &m->initrd_timestamp);
2232 else if (startswith(l, "userspace-timestamp="))
2233 dual_timestamp_deserialize(l+20, &m->userspace_timestamp);
2234 else if (startswith(l, "finish-timestamp="))
2235 dual_timestamp_deserialize(l+17, &m->finish_timestamp);
2236 else if (startswith(l, "security-start-timestamp="))
2237 dual_timestamp_deserialize(l+25, &m->security_start_timestamp);
2238 else if (startswith(l, "security-finish-timestamp="))
2239 dual_timestamp_deserialize(l+26, &m->security_finish_timestamp);
2240 else if (startswith(l, "generators-start-timestamp="))
2241 dual_timestamp_deserialize(l+27, &m->generators_start_timestamp);
2242 else if (startswith(l, "generators-finish-timestamp="))
2243 dual_timestamp_deserialize(l+28, &m->generators_finish_timestamp);
2244 else if (startswith(l, "units-load-start-timestamp="))
2245 dual_timestamp_deserialize(l+27, &m->units_load_start_timestamp);
2246 else if (startswith(l, "units-load-finish-timestamp="))
2247 dual_timestamp_deserialize(l+28, &m->units_load_finish_timestamp);
2248 else if (startswith(l, "env=")) {
2249 _cleanup_free_ char *uce = NULL;
2250 char **e;
2251
2252 uce = cunescape(l+4);
2253 if (!uce) {
2254 r = -ENOMEM;
2255 goto finish;
2256 }
2257
2258 e = strv_env_set(m->environment, uce);
2259 if (!e) {
2260 r = -ENOMEM;
2261 goto finish;
2262 }
2263
2264 strv_free(m->environment);
2265 m->environment = e;
2266
2267 } else if (startswith(l, "notify-fd=")) {
2268 int fd;
2269
2270 if (safe_atoi(l + 10, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
2271 log_debug("Failed to parse notify fd: %s", l + 10);
2272 else {
2273 m->notify_event_source = sd_event_source_unref(m->notify_event_source);
2274 safe_close(m->notify_fd);
2275 m->notify_fd = fdset_remove(fds, fd);
2276 }
2277
2278 } else if (startswith(l, "notify-socket=")) {
2279 char *n;
2280
2281 n = strdup(l+14);
2282 if (!n) {
2283 r = -ENOMEM;
2284 goto finish;
2285 }
2286
2287 free(m->notify_socket);
2288 m->notify_socket = n;
2289
2290 } else if (startswith(l, "kdbus-fd=")) {
2291 int fd;
2292
2293 if (safe_atoi(l + 9, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
2294 log_debug("Failed to parse kdbus fd: %s", l + 9);
2295 else {
2296 safe_close(m->kdbus_fd);
2297 m->kdbus_fd = fdset_remove(fds, fd);
2298 }
2299
2300 } else if (bus_track_deserialize_item(&m->deserialized_subscribed, l) == 0)
2301 log_debug("Unknown serialization item '%s'", l);
2302 }
2303
2304 for (;;) {
2305 Unit *u;
2306 char name[UNIT_NAME_MAX+2];
2307
2308 /* Start marker */
2309 if (!fgets(name, sizeof(name), f)) {
2310 if (feof(f))
2311 r = 0;
2312 else
2313 r = -errno;
2314
2315 goto finish;
2316 }
2317
2318 char_array_0(name);
2319
2320 r = manager_load_unit(m, strstrip(name), NULL, NULL, &u);
2321 if (r < 0)
2322 goto finish;
2323
2324 r = unit_deserialize(u, f, fds);
2325 if (r < 0)
2326 goto finish;
2327 }
2328
2329 finish:
2330 if (ferror(f))
2331 r = -EIO;
2332
2333 assert(m->n_reloading > 0);
2334 m->n_reloading --;
2335
2336 return r;
2337 }
2338
2339 int manager_reload(Manager *m) {
2340 int r, q;
2341 _cleanup_fclose_ FILE *f = NULL;
2342 _cleanup_fdset_free_ FDSet *fds = NULL;
2343
2344 assert(m);
2345
2346 r = manager_open_serialization(m, &f);
2347 if (r < 0)
2348 return r;
2349
2350 m->n_reloading ++;
2351 bus_manager_send_reloading(m, true);
2352
2353 fds = fdset_new();
2354 if (!fds) {
2355 m->n_reloading --;
2356 return -ENOMEM;
2357 }
2358
2359 r = manager_serialize(m, f, fds, false);
2360 if (r < 0) {
2361 m->n_reloading --;
2362 return r;
2363 }
2364
2365 if (fseeko(f, 0, SEEK_SET) < 0) {
2366 m->n_reloading --;
2367 return -errno;
2368 }
2369
2370 /* From here on there is no way back. */
2371 manager_clear_jobs_and_units(m);
2372 manager_undo_generators(m);
2373 lookup_paths_free(&m->lookup_paths);
2374
2375 /* Find new unit paths */
2376 manager_run_generators(m);
2377
2378 q = lookup_paths_init(
2379 &m->lookup_paths, m->running_as, true,
2380 NULL,
2381 m->generator_unit_path,
2382 m->generator_unit_path_early,
2383 m->generator_unit_path_late);
2384 if (q < 0)
2385 r = q;
2386
2387 manager_build_unit_path_cache(m);
2388
2389 /* First, enumerate what we can from all config files */
2390 q = manager_enumerate(m);
2391 if (q < 0)
2392 r = q;
2393
2394 /* Second, deserialize our stored data */
2395 q = manager_deserialize(m, f, fds);
2396 if (q < 0)
2397 r = q;
2398
2399 fclose(f);
2400 f = NULL;
2401
2402 /* Re-register notify_fd as event source */
2403 q = manager_setup_notify(m);
2404 if (q < 0)
2405 r = q;
2406
2407 /* Third, fire things up! */
2408 q = manager_coldplug(m);
2409 if (q < 0)
2410 r = q;
2411
2412 assert(m->n_reloading > 0);
2413 m->n_reloading--;
2414
2415 m->send_reloading_done = true;
2416
2417 return r;
2418 }
2419
2420 bool manager_is_reloading_or_reexecuting(Manager *m) {
2421 assert(m);
2422
2423 return m->n_reloading != 0;
2424 }
2425
2426 void manager_reset_failed(Manager *m) {
2427 Unit *u;
2428 Iterator i;
2429
2430 assert(m);
2431
2432 HASHMAP_FOREACH(u, m->units, i)
2433 unit_reset_failed(u);
2434 }
2435
2436 bool manager_unit_inactive_or_pending(Manager *m, const char *name) {
2437 Unit *u;
2438
2439 assert(m);
2440 assert(name);
2441
2442 /* Returns true if the unit is inactive or going down */
2443 u = manager_get_unit(m, name);
2444 if (!u)
2445 return true;
2446
2447 return unit_inactive_or_pending(u);
2448 }
2449
2450 void manager_check_finished(Manager *m) {
2451 char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
2452 usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec;
2453 Unit *u = NULL;
2454 Iterator i;
2455
2456 assert(m);
2457
2458 if (m->n_running_jobs == 0)
2459 m->jobs_in_progress_event_source = sd_event_source_unref(m->jobs_in_progress_event_source);
2460
2461 if (hashmap_size(m->jobs) > 0) {
2462
2463 if (m->jobs_in_progress_event_source) {
2464 sd_event_source_set_time(m->jobs_in_progress_event_source,
2465 now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC);
2466 }
2467
2468 return;
2469 }
2470
2471 manager_flip_auto_status(m, false);
2472
2473 /* Notify Type=idle units that we are done now */
2474 m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
2475 manager_close_idle_pipe(m);
2476
2477 /* Turn off confirm spawn now */
2478 m->confirm_spawn = false;
2479
2480 /* This is no longer the first boot */
2481 manager_set_first_boot(m, false);
2482
2483 if (dual_timestamp_is_set(&m->finish_timestamp))
2484 return;
2485
2486 dual_timestamp_get(&m->finish_timestamp);
2487
2488 if (m->running_as == SYSTEMD_SYSTEM && detect_container(NULL) <= 0) {
2489
2490 /* Note that m->kernel_usec.monotonic is always at 0,
2491 * and m->firmware_usec.monotonic and
2492 * m->loader_usec.monotonic should be considered
2493 * negative values. */
2494
2495 firmware_usec = m->firmware_timestamp.monotonic - m->loader_timestamp.monotonic;
2496 loader_usec = m->loader_timestamp.monotonic - m->kernel_timestamp.monotonic;
2497 userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic;
2498 total_usec = m->firmware_timestamp.monotonic + m->finish_timestamp.monotonic;
2499
2500 if (dual_timestamp_is_set(&m->initrd_timestamp)) {
2501
2502 kernel_usec = m->initrd_timestamp.monotonic - m->kernel_timestamp.monotonic;
2503 initrd_usec = m->userspace_timestamp.monotonic - m->initrd_timestamp.monotonic;
2504
2505 if (!log_on_console())
2506 log_struct(LOG_INFO,
2507 MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
2508 "KERNEL_USEC="USEC_FMT, kernel_usec,
2509 "INITRD_USEC="USEC_FMT, initrd_usec,
2510 "USERSPACE_USEC="USEC_FMT, userspace_usec,
2511 "MESSAGE=Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.",
2512 format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC),
2513 format_timespan(initrd, sizeof(initrd), initrd_usec, USEC_PER_MSEC),
2514 format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC),
2515 format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
2516 NULL);
2517 } else {
2518 kernel_usec = m->userspace_timestamp.monotonic - m->kernel_timestamp.monotonic;
2519 initrd_usec = 0;
2520
2521 if (!log_on_console())
2522 log_struct(LOG_INFO,
2523 MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
2524 "KERNEL_USEC="USEC_FMT, kernel_usec,
2525 "USERSPACE_USEC="USEC_FMT, userspace_usec,
2526 "MESSAGE=Startup finished in %s (kernel) + %s (userspace) = %s.",
2527 format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC),
2528 format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC),
2529 format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
2530 NULL);
2531 }
2532 } else {
2533 firmware_usec = loader_usec = initrd_usec = kernel_usec = 0;
2534 total_usec = userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic;
2535
2536 if (!log_on_console())
2537 log_struct(LOG_INFO,
2538 MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
2539 "USERSPACE_USEC="USEC_FMT, userspace_usec,
2540 "MESSAGE=Startup finished in %s.",
2541 format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
2542 NULL);
2543 }
2544
2545 SET_FOREACH(u, m->startup_units, i)
2546 if (u->cgroup_path)
2547 cgroup_context_apply(unit_get_cgroup_context(u), unit_get_cgroup_mask(u), u->cgroup_path, manager_state(m));
2548
2549 bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
2550
2551 sd_notifyf(false,
2552 "READY=1\nSTATUS=Startup finished in %s.",
2553 format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC));
2554 }
2555
2556 static int create_generator_dir(Manager *m, char **generator, const char *name) {
2557 char *p;
2558 int r;
2559
2560 assert(m);
2561 assert(generator);
2562 assert(name);
2563
2564 if (*generator)
2565 return 0;
2566
2567 if (m->running_as == SYSTEMD_SYSTEM && getpid() == 1) {
2568 /* systemd --system, not running --test */
2569
2570 p = strappend("/run/systemd/", name);
2571 if (!p)
2572 return log_oom();
2573
2574 r = mkdir_p_label(p, 0755);
2575 if (r < 0) {
2576 log_error("Failed to create generator directory %s: %s",
2577 p, strerror(-r));
2578 free(p);
2579 return r;
2580 }
2581 } else if (m->running_as == SYSTEMD_USER) {
2582 const char *s = NULL;
2583
2584 s = getenv("XDG_RUNTIME_DIR");
2585 if (!s)
2586 return -EINVAL;
2587 p = strjoin(s, "/systemd/", name, NULL);
2588 if (!p)
2589 return log_oom();
2590
2591 r = mkdir_p_label(p, 0755);
2592 if (r < 0) {
2593 log_error("Failed to create generator directory %s: %s",
2594 p, strerror(-r));
2595 free(p);
2596 return r;
2597 }
2598 } else {
2599 /* systemd --system --test */
2600
2601 p = strjoin("/tmp/systemd-", name, ".XXXXXX", NULL);
2602 if (!p)
2603 return log_oom();
2604
2605 if (!mkdtemp(p)) {
2606 log_error("Failed to create generator directory %s: %m",
2607 p);
2608 free(p);
2609 return -errno;
2610 }
2611 }
2612
2613 *generator = p;
2614 return 0;
2615 }
2616
2617 static void trim_generator_dir(Manager *m, char **generator) {
2618 assert(m);
2619 assert(generator);
2620
2621 if (!*generator)
2622 return;
2623
2624 if (rmdir(*generator) >= 0) {
2625 free(*generator);
2626 *generator = NULL;
2627 }
2628
2629 return;
2630 }
2631
2632 void manager_run_generators(Manager *m) {
2633 _cleanup_closedir_ DIR *d = NULL;
2634 const char *generator_path;
2635 const char *argv[5];
2636 int r;
2637
2638 assert(m);
2639
2640 if (m->test_run)
2641 return;
2642
2643 generator_path = m->running_as == SYSTEMD_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH;
2644 d = opendir(generator_path);
2645 if (!d) {
2646 if (errno == ENOENT)
2647 return;
2648
2649 log_error("Failed to enumerate generator directory %s: %m",
2650 generator_path);
2651 return;
2652 }
2653
2654 r = create_generator_dir(m, &m->generator_unit_path, "generator");
2655 if (r < 0)
2656 goto finish;
2657
2658 r = create_generator_dir(m, &m->generator_unit_path_early, "generator.early");
2659 if (r < 0)
2660 goto finish;
2661
2662 r = create_generator_dir(m, &m->generator_unit_path_late, "generator.late");
2663 if (r < 0)
2664 goto finish;
2665
2666 argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */
2667 argv[1] = m->generator_unit_path;
2668 argv[2] = m->generator_unit_path_early;
2669 argv[3] = m->generator_unit_path_late;
2670 argv[4] = NULL;
2671
2672 RUN_WITH_UMASK(0022)
2673 execute_directory(generator_path, d, DEFAULT_TIMEOUT_USEC, (char**) argv);
2674
2675 finish:
2676 trim_generator_dir(m, &m->generator_unit_path);
2677 trim_generator_dir(m, &m->generator_unit_path_early);
2678 trim_generator_dir(m, &m->generator_unit_path_late);
2679 }
2680
2681 static void remove_generator_dir(Manager *m, char **generator) {
2682 assert(m);
2683 assert(generator);
2684
2685 if (!*generator)
2686 return;
2687
2688 strv_remove(m->lookup_paths.unit_path, *generator);
2689 rm_rf(*generator, false, true, false);
2690
2691 free(*generator);
2692 *generator = NULL;
2693 }
2694
2695 void manager_undo_generators(Manager *m) {
2696 assert(m);
2697
2698 remove_generator_dir(m, &m->generator_unit_path);
2699 remove_generator_dir(m, &m->generator_unit_path_early);
2700 remove_generator_dir(m, &m->generator_unit_path_late);
2701 }
2702
2703 int manager_environment_add(Manager *m, char **minus, char **plus) {
2704 char **a = NULL, **b = NULL, **l;
2705 assert(m);
2706
2707 l = m->environment;
2708
2709 if (!strv_isempty(minus)) {
2710 a = strv_env_delete(l, 1, minus);
2711 if (!a)
2712 return -ENOMEM;
2713
2714 l = a;
2715 }
2716
2717 if (!strv_isempty(plus)) {
2718 b = strv_env_merge(2, l, plus);
2719 if (!b)
2720 return -ENOMEM;
2721
2722 l = b;
2723 }
2724
2725 if (m->environment != l)
2726 strv_free(m->environment);
2727 if (a != l)
2728 strv_free(a);
2729 if (b != l)
2730 strv_free(b);
2731
2732 m->environment = l;
2733 manager_clean_environment(m);
2734 strv_sort(m->environment);
2735
2736 return 0;
2737 }
2738
2739 int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) {
2740 int i;
2741
2742 assert(m);
2743
2744 for (i = 0; i < _RLIMIT_MAX; i++) {
2745 if (!default_rlimit[i])
2746 continue;
2747
2748 m->rlimit[i] = newdup(struct rlimit, default_rlimit[i], 1);
2749 if (!m->rlimit[i])
2750 return -ENOMEM;
2751 }
2752
2753 return 0;
2754 }
2755
2756 void manager_recheck_journal(Manager *m) {
2757 Unit *u;
2758
2759 assert(m);
2760
2761 if (m->running_as != SYSTEMD_SYSTEM)
2762 return;
2763
2764 u = manager_get_unit(m, SPECIAL_JOURNALD_SOCKET);
2765 if (u && SOCKET(u)->state != SOCKET_RUNNING) {
2766 log_close_journal();
2767 return;
2768 }
2769
2770 u = manager_get_unit(m, SPECIAL_JOURNALD_SERVICE);
2771 if (u && SERVICE(u)->state != SERVICE_RUNNING) {
2772 log_close_journal();
2773 return;
2774 }
2775
2776 /* Hmm, OK, so the socket is fully up and the service is up
2777 * too, then let's make use of the thing. */
2778 log_open();
2779 }
2780
2781 void manager_set_show_status(Manager *m, ShowStatus mode) {
2782 assert(m);
2783 assert(IN_SET(mode, SHOW_STATUS_AUTO, SHOW_STATUS_NO, SHOW_STATUS_YES, SHOW_STATUS_TEMPORARY));
2784
2785 if (m->running_as != SYSTEMD_SYSTEM)
2786 return;
2787
2788 m->show_status = mode;
2789
2790 if (mode > 0)
2791 touch("/run/systemd/show-status");
2792 else
2793 unlink("/run/systemd/show-status");
2794 }
2795
2796 static bool manager_get_show_status(Manager *m) {
2797 assert(m);
2798
2799 if (m->running_as != SYSTEMD_SYSTEM)
2800 return false;
2801
2802 if (m->no_console_output)
2803 return false;
2804
2805 if (!IN_SET(manager_state(m), MANAGER_STARTING, MANAGER_STOPPING))
2806 return false;
2807
2808 if (m->show_status > 0)
2809 return true;
2810
2811 /* If Plymouth is running make sure we show the status, so
2812 * that there's something nice to see when people press Esc */
2813
2814 return plymouth_running();
2815 }
2816
2817 void manager_set_first_boot(Manager *m, bool b) {
2818 assert(m);
2819
2820 if (m->running_as != SYSTEMD_SYSTEM)
2821 return;
2822
2823 m->first_boot = b;
2824
2825 if (m->first_boot)
2826 touch("/run/systemd/first-boot");
2827 else
2828 unlink("/run/systemd/first-boot");
2829 }
2830
2831 void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) {
2832 va_list ap;
2833
2834 if (!manager_get_show_status(m))
2835 return;
2836
2837 /* XXX We should totally drop the check for ephemeral here
2838 * and thus effectively make 'Type=idle' pointless. */
2839 if (ephemeral && m->n_on_console > 0)
2840 return;
2841
2842 va_start(ap, format);
2843 status_vprintf(status, true, ephemeral, format, ap);
2844 va_end(ap);
2845 }
2846
2847 int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found) {
2848 _cleanup_free_ char *p = NULL;
2849 Unit *found;
2850
2851 assert(m);
2852 assert(path);
2853 assert(suffix);
2854 assert(_found);
2855
2856 p = unit_name_from_path(path, suffix);
2857 if (!p)
2858 return -ENOMEM;
2859
2860 found = manager_get_unit(m, p);
2861 if (!found) {
2862 *_found = NULL;
2863 return 0;
2864 }
2865
2866 *_found = found;
2867 return 1;
2868 }
2869
2870 Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
2871 char p[strlen(path)+1];
2872
2873 assert(m);
2874 assert(path);
2875
2876 strcpy(p, path);
2877 path_kill_slashes(p);
2878
2879 return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p);
2880 }
2881
2882 const char *manager_get_runtime_prefix(Manager *m) {
2883 assert(m);
2884
2885 return m->running_as == SYSTEMD_SYSTEM ?
2886 "/run" :
2887 getenv("XDG_RUNTIME_DIR");
2888 }
2889
2890 ManagerState manager_state(Manager *m) {
2891 Unit *u;
2892
2893 assert(m);
2894
2895 /* Did we ever finish booting? If not then we are still starting up */
2896 if (!dual_timestamp_is_set(&m->finish_timestamp))
2897 return MANAGER_STARTING;
2898
2899 /* Is the special shutdown target queued? If so, we are in shutdown state */
2900 u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET);
2901 if (u && u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_TRY_RESTART, JOB_RELOAD_OR_START))
2902 return MANAGER_STOPPING;
2903
2904 /* Are the rescue or emergency targets active or queued? If so we are in maintenance state */
2905 u = manager_get_unit(m, SPECIAL_RESCUE_TARGET);
2906 if (u && (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)) ||
2907 (u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_TRY_RESTART, JOB_RELOAD_OR_START))))
2908 return MANAGER_MAINTENANCE;
2909
2910 u = manager_get_unit(m, SPECIAL_EMERGENCY_TARGET);
2911 if (u && (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)) ||
2912 (u->job && IN_SET(u->job->type, JOB_START, JOB_RESTART, JOB_TRY_RESTART, JOB_RELOAD_OR_START))))
2913 return MANAGER_MAINTENANCE;
2914
2915 /* Are there any failed units? If so, we are in degraded mode */
2916 if (set_size(m->failed_units) > 0)
2917 return MANAGER_DEGRADED;
2918
2919 return MANAGER_RUNNING;
2920 }
2921
2922 static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
2923 [MANAGER_STARTING] = "starting",
2924 [MANAGER_RUNNING] = "running",
2925 [MANAGER_DEGRADED] = "degraded",
2926 [MANAGER_MAINTENANCE] = "maintenance",
2927 [MANAGER_STOPPING] = "stopping",
2928 };
2929
2930 DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState);