]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/manager.c
Merge pull request #20476 from jamacku/new-feature-reloaded-stamp
[thirdparty/systemd.git] / src / core / manager.c
index b767b0ee6c5eae0c32a289c641f52f74b8917ba3..c5c6e628685c8c300af31733da8e74546faff66e 100644 (file)
@@ -44,9 +44,9 @@
 #include "exit-status.h"
 #include "fd-util.h"
 #include "fileio.h"
-#include "fs-util.h"
 #include "generator-setup.h"
 #include "hashmap.h"
+#include "inotify-util.h"
 #include "install.h"
 #include "io-util.h"
 #include "label.h"
@@ -58,7 +58,7 @@
 #include "manager-dump.h"
 #include "manager-serialize.h"
 #include "memory-util.h"
-#include "mkdir.h"
+#include "mkdir-label.h"
 #include "parse-util.h"
 #include "path-lookup.h"
 #include "path-util.h"
@@ -930,6 +930,14 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
                 r = manager_setup_sigchld_event_source(m);
                 if (r < 0)
                         return r;
+
+#if HAVE_LIBBPF
+                if (MANAGER_IS_SYSTEM(m) && lsm_bpf_supported()) {
+                        r = lsm_bpf_setup(m);
+                        if (r < 0)
+                                return r;
+                }
+#endif
         }
 
         if (test_run_flags == 0) {
@@ -1535,6 +1543,10 @@ Manager* manager_free(Manager *m) {
                 m->prefix[dt] = mfree(m->prefix[dt]);
         free(m->received_credentials);
 
+#if BPF_FRAMEWORK
+        lsm_bpf_destroy(m->restrict_fs);
+#endif
+
         return mfree(m);
 }
 
@@ -1717,13 +1729,20 @@ static void manager_ready(Manager *m) {
         /* Let's finally catch up with any changes that took place while we were reloading/reexecing */
         manager_catchup(m);
 
+        /* Create a file which will indicate when the manager started loading units the last time. */
+        (void) touch_file("/run/systemd/systemd-units-load", false,
+                m->timestamps[MANAGER_TIMESTAMP_UNITS_LOAD].realtime ?: now(CLOCK_REALTIME),
+                UID_INVALID, GID_INVALID, 0444);
+
         m->honor_device_enumeration = true;
 }
 
 Manager* manager_reloading_start(Manager *m) {
         m->n_reloading++;
+        dual_timestamp_get(m->timestamps + MANAGER_TIMESTAMP_UNITS_LOAD);
         return m;
 }
+
 void manager_reloading_stopp(Manager **m) {
         if (*m) {
                 assert((*m)->n_reloading > 0);
@@ -1758,7 +1777,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo
 
         {
                 /* This block is (optionally) done with the reloading counter bumped */
-                _cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
+                _unused_ _cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
 
                 /* If we will deserialize make sure that during enumeration this is already known, so we increase the
                  * counter here already */
@@ -1810,7 +1829,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo
 
                 r = manager_varlink_init(m);
                 if (r < 0)
-                        log_warning_errno(r, "Failed to set up Varlink server, ignoring: %m");
+                        log_warning_errno(r, "Failed to set up Varlink, ignoring: %m");
 
                 /* Third, fire things up! */
                 manager_coldplug(m);
@@ -2236,6 +2255,18 @@ static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) {
         return 1;
 }
 
+void manager_trigger_run_queue(Manager *m) {
+        int r;
+
+        assert(m);
+
+        r = sd_event_source_set_enabled(
+                        m->run_queue_event_source,
+                        prioq_isempty(m->run_queue) ? SD_EVENT_OFF : SD_EVENT_ONESHOT);
+        if (r < 0)
+                log_warning_errno(r, "Failed to enable job run queue event source, ignoring: %m");
+}
+
 static unsigned manager_dispatch_dbus_queue(Manager *m) {
         unsigned n = 0, budget;
         Unit *u;
@@ -2421,18 +2452,19 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
         }
 
         n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
-        if (IN_SET(n, -EAGAIN, -EINTR))
-                return 0; /* Spurious wakeup, try again */
-        if (n == -EXFULL) {
-                log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
-                return 0;
-        }
-        if (n < 0)
+        if (n < 0) {
+                if (ERRNO_IS_TRANSIENT(n))
+                        return 0; /* Spurious wakeup, try again */
+                if (n == -EXFULL) {
+                        log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
+                        return 0;
+                }
                 /* If this is any other, real error, then let's stop processing this socket. This of course
                  * means we won't take notification messages anymore, but that's still better than busy
                  * looping around this: being woken up over and over again but being unable to actually read
                  * the message off the socket. */
                 return log_error_errno(n, "Failed to receive notification message: %m");
+        }
 
         CMSG_FOREACH(cmsg, &msghdr) {
                 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
@@ -2692,19 +2724,18 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
         }
 
         n = read(m->signal_fd, &sfsi, sizeof(sfsi));
-        if (n != sizeof(sfsi)) {
-                if (n >= 0) {
-                        log_warning("Truncated read from signal fd (%zu bytes), ignoring!", n);
-                        return 0;
-                }
-
-                if (IN_SET(errno, EINTR, EAGAIN))
+        if (n < 0) {
+                if (ERRNO_IS_TRANSIENT(errno))
                         return 0;
 
                 /* We return an error here, which will kill this handler,
                  * to avoid a busy loop on read error. */
                 return log_error_errno(errno, "Reading from signal fd failed: %m");
         }
+        if (n != sizeof(sfsi)) {
+                log_warning("Truncated read from signal fd (%zu bytes), ignoring!", n);
+                return 0;
+        }
 
         log_received_signal(sfsi.ssi_signo == SIGCHLD ||
                             (sfsi.ssi_signo == SIGTERM && MANAGER_IS_USER(m))
@@ -2978,13 +3009,8 @@ int manager_loop(Manager *m) {
                 return log_error_errno(r, "Failed to enable SIGCHLD event source: %m");
 
         while (m->objective == MANAGER_OK) {
-                usec_t wait_usec, watchdog_usec;
 
-                watchdog_usec = manager_get_watchdog(m, WATCHDOG_RUNTIME);
-                if (m->runtime_watchdog_running)
-                        (void) watchdog_ping();
-                else if (timestamp_is_set(watchdog_usec))
-                        manager_retry_runtime_watchdog(m);
+                (void) watchdog_ping();
 
                 if (!ratelimit_below(&rl)) {
                         /* Yay, something is going seriously wrong, pause a little */
@@ -3020,12 +3046,7 @@ int manager_loop(Manager *m) {
                         continue;
 
                 /* Sleep for watchdog runtime wait time */
-                if (timestamp_is_set(watchdog_usec))
-                        wait_usec = watchdog_runtime_wait();
-                else
-                        wait_usec = USEC_INFINITY;
-
-                r = sd_event_run(m->event, wait_usec);
+                r = sd_event_run(m->event, watchdog_runtime_wait());
                 if (r < 0)
                         return log_error_errno(r, "Failed to run event loop: %m");
         }
@@ -3203,7 +3224,6 @@ usec_t manager_get_watchdog(Manager *m, WatchdogType t) {
 }
 
 void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
-        int r = 0;
 
         assert(m);
 
@@ -3214,23 +3234,13 @@ void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
                 return;
 
         if (t == WATCHDOG_RUNTIME)
-                if (!timestamp_is_set(m->watchdog_overridden[WATCHDOG_RUNTIME])) {
-                        if (timestamp_is_set(timeout)) {
-                                r = watchdog_set_timeout(&timeout);
-
-                                if (r >= 0)
-                                        m->runtime_watchdog_running = true;
-                        } else {
-                                watchdog_close(true);
-                                m->runtime_watchdog_running = false;
-                        }
-                }
+                if (!timestamp_is_set(m->watchdog_overridden[WATCHDOG_RUNTIME]))
+                        (void) watchdog_setup(timeout);
 
         m->watchdog[t] = timeout;
 }
 
 int manager_override_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
-        int r = 0;
 
         assert(m);
 
@@ -3241,41 +3251,17 @@ int manager_override_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
                 return 0;
 
         if (t == WATCHDOG_RUNTIME) {
-                usec_t *p;
+                usec_t usec = timestamp_is_set(timeout) ? timeout : m->watchdog[t];
 
-                p = timestamp_is_set(timeout) ? &timeout : &m->watchdog[t];
-                if (timestamp_is_set(*p)) {
-                        r = watchdog_set_timeout(p);
-
-                        if (r >= 0)
-                                m->runtime_watchdog_running = true;
-                } else {
-                        watchdog_close(true);
-                        m->runtime_watchdog_running = false;
-                }
+                (void) watchdog_setup(usec);
         }
 
         m->watchdog_overridden[t] = timeout;
-
         return 0;
 }
 
-void manager_retry_runtime_watchdog(Manager *m) {
-        int r = 0;
-
-        assert(m);
-
-        if (timestamp_is_set(m->watchdog_overridden[WATCHDOG_RUNTIME]))
-                r = watchdog_set_timeout(&m->watchdog_overridden[WATCHDOG_RUNTIME]);
-        else
-                r = watchdog_set_timeout(&m->watchdog[WATCHDOG_RUNTIME]);
-
-        if (r >= 0)
-                m->runtime_watchdog_running = true;
-}
-
 int manager_reload(Manager *m) {
-        _cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
+        _unused_ _cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
         _cleanup_fdset_free_ FDSet *fds = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
@@ -3490,27 +3476,38 @@ static void manager_notify_finished(Manager *m) {
 }
 
 static void user_manager_send_ready(Manager *m) {
+        int r;
+
         assert(m);
 
         /* We send READY=1 on reaching basic.target only when running in --user mode. */
         if (!MANAGER_IS_USER(m) || m->ready_sent)
                 return;
 
-        sd_notifyf(false,
-                   "READY=1\n"
-                   "STATUS=Reached " SPECIAL_BASIC_TARGET ".");
+        r = sd_notify(false,
+                      "READY=1\n"
+                      "STATUS=Reached " SPECIAL_BASIC_TARGET ".");
+        if (r < 0)
+                log_warning_errno(r, "Failed to send readiness notification, ignoring: %m");
+
         m->ready_sent = true;
         m->status_ready = false;
 }
 
 static void manager_send_ready(Manager *m) {
+        int r;
+
         if (m->ready_sent && m->status_ready)
                 /* Skip the notification if nothing changed. */
                 return;
 
-        sd_notifyf(false,
-                   "%sSTATUS=Ready.",
-                   m->ready_sent ? "READY=1\n" : "");
+        r = sd_notify(false,
+                      "READY=1\n"
+                      "STATUS=Ready.");
+        if (r < 0)
+                log_full_errno(m->ready_sent ? LOG_DEBUG : LOG_WARNING, r,
+                               "Failed to send readiness notification, ignoring: %m");
+
         m->ready_sent = m->status_ready = true;
 }
 
@@ -4273,7 +4270,7 @@ int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t re
 
         l = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
         if (l < 0) {
-                if (IN_SET(errno, EINTR, EAGAIN))
+                if (ERRNO_IS_TRANSIENT(errno))
                         return 0;
 
                 return log_error_errno(errno, "Failed to read from user lookup fd: %m");
@@ -4469,6 +4466,7 @@ static const char *const manager_timestamp_table[_MANAGER_TIMESTAMP_MAX] = {
         [MANAGER_TIMESTAMP_GENERATORS_FINISH]        = "generators-finish",
         [MANAGER_TIMESTAMP_UNITS_LOAD_START]         = "units-load-start",
         [MANAGER_TIMESTAMP_UNITS_LOAD_FINISH]        = "units-load-finish",
+        [MANAGER_TIMESTAMP_UNITS_LOAD]               = "units-load",
         [MANAGER_TIMESTAMP_INITRD_SECURITY_START]    = "initrd-security-start",
         [MANAGER_TIMESTAMP_INITRD_SECURITY_FINISH]   = "initrd-security-finish",
         [MANAGER_TIMESTAMP_INITRD_GENERATORS_START]  = "initrd-generators-start",