summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-07-02 15:53:38 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-07-19 11:27:11 +0200
commita01ba4b2b8deeb31c65f8ed525ebab51972919bf (patch)
tree12b7af1bfd29760e8e47c3648b1841d25f79c5d7 /src/core
parent95b63c755b73606e3dce094d92024c1e57ee5ed4 (diff)
downloadsystemd-a01ba4b2b8deeb31c65f8ed525ebab51972919bf.tar.gz
core: split out manager-serialize.[ch]
The file is super long, so let's split this out one subject to a new file.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/main.c1
-rw-r--r--src/core/manager-serialize.c536
-rw-r--r--src/core/manager-serialize.h13
-rw-r--r--src/core/manager.c531
-rw-r--r--src/core/manager.h7
-rw-r--r--src/core/meson.build2
6 files changed, 557 insertions, 533 deletions
diff --git a/src/core/main.c b/src/core/main.c
index 72d7c6b116..57d4f033dd 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -55,6 +55,7 @@
#include "machine-id-setup.h"
#include "manager.h"
#include "manager-dump.h"
+#include "manager-serialize.h"
#include "mkdir.h"
#include "mount-setup.h"
#include "os-util.h"
diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c
new file mode 100644
index 0000000000..60a35f48f3
--- /dev/null
+++ b/src/core/manager-serialize.c
@@ -0,0 +1,536 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "clean-ipc.h"
+#include "dbus.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "format-util.h"
+#include "macro.h"
+#include "manager-serialize.h"
+#include "manager.h"
+#include "parse-util.h"
+#include "serialize.h"
+#include "syslog-util.h"
+#include "unit-serialize.h"
+#include "user-util.h"
+
+int manager_open_serialization(Manager *m, FILE **ret_f) {
+ _cleanup_close_ int fd = -1;
+ FILE *f;
+
+ assert(ret_f);
+
+ fd = open_serialization_fd("systemd-state");
+ if (fd < 0)
+ return fd;
+
+ f = take_fdopen(&fd, "w+");
+ if (!f)
+ return -errno;
+
+ *ret_f = f;
+ return 0;
+}
+
+static bool manager_timestamp_shall_serialize(ManagerTimestamp t) {
+ if (!in_initrd())
+ return true;
+
+ /* The following timestamps only apply to the host system, hence only serialize them there */
+ return !IN_SET(t,
+ MANAGER_TIMESTAMP_USERSPACE, MANAGER_TIMESTAMP_FINISH,
+ MANAGER_TIMESTAMP_SECURITY_START, MANAGER_TIMESTAMP_SECURITY_FINISH,
+ MANAGER_TIMESTAMP_GENERATORS_START, MANAGER_TIMESTAMP_GENERATORS_FINISH,
+ MANAGER_TIMESTAMP_UNITS_LOAD_START, MANAGER_TIMESTAMP_UNITS_LOAD_FINISH);
+}
+
+static void manager_serialize_uid_refs_internal(
+ FILE *f,
+ Hashmap *uid_refs,
+ const char *field_name) {
+
+ void *p, *k;
+
+ assert(f);
+ assert(field_name);
+
+ /* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as
+ * the actual counter of it is better rebuild after a reload/reexec. */
+
+ HASHMAP_FOREACH_KEY(p, k, uid_refs) {
+ uint32_t c;
+ uid_t uid;
+
+ uid = PTR_TO_UID(k);
+ c = PTR_TO_UINT32(p);
+
+ if (!(c & DESTROY_IPC_FLAG))
+ continue;
+
+ (void) serialize_item_format(f, field_name, UID_FMT, uid);
+ }
+}
+
+static void manager_serialize_uid_refs(Manager *m, FILE *f) {
+ manager_serialize_uid_refs_internal(f, m->uid_refs, "destroy-ipc-uid");
+}
+
+static void manager_serialize_gid_refs(Manager *m, FILE *f) {
+ manager_serialize_uid_refs_internal(f, m->gid_refs, "destroy-ipc-gid");
+}
+
+int manager_serialize(
+ Manager *m,
+ FILE *f,
+ FDSet *fds,
+ bool switching_root) {
+
+ const char *t;
+ Unit *u;
+ int r;
+
+ assert(m);
+ assert(f);
+ assert(fds);
+
+ _cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m);
+
+ (void) serialize_item_format(f, "current-job-id", "%" PRIu32, m->current_job_id);
+ (void) serialize_item_format(f, "n-installed-jobs", "%u", m->n_installed_jobs);
+ (void) serialize_item_format(f, "n-failed-jobs", "%u", m->n_failed_jobs);
+ (void) serialize_bool(f, "taint-usr", m->taint_usr);
+ (void) serialize_bool(f, "ready-sent", m->ready_sent);
+ (void) serialize_bool(f, "taint-logged", m->taint_logged);
+ (void) serialize_bool(f, "service-watchdogs", m->service_watchdogs);
+
+ /* After switching root, udevd has not been started yet. So, enumeration results should not be emitted. */
+ (void) serialize_bool(f, "honor-device-enumeration", !switching_root);
+
+ if (m->show_status_overridden != _SHOW_STATUS_INVALID)
+ (void) serialize_item(f, "show-status-overridden",
+ show_status_to_string(m->show_status_overridden));
+
+ if (m->log_level_overridden)
+ (void) serialize_item_format(f, "log-level-override", "%i", log_get_max_level());
+ if (m->log_target_overridden)
+ (void) serialize_item(f, "log-target-override", log_target_to_string(log_get_target()));
+
+ (void) serialize_usec(f, "runtime-watchdog-overridden", m->watchdog_overridden[WATCHDOG_RUNTIME]);
+ (void) serialize_usec(f, "reboot-watchdog-overridden", m->watchdog_overridden[WATCHDOG_REBOOT]);
+ (void) serialize_usec(f, "kexec-watchdog-overridden", m->watchdog_overridden[WATCHDOG_KEXEC]);
+
+ for (ManagerTimestamp q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
+ _cleanup_free_ char *joined = NULL;
+
+ if (!manager_timestamp_shall_serialize(q))
+ continue;
+
+ joined = strjoin(manager_timestamp_to_string(q), "-timestamp");
+ if (!joined)
+ return log_oom();
+
+ (void) serialize_dual_timestamp(f, joined, m->timestamps + q);
+ }
+
+ if (!switching_root)
+ (void) serialize_strv(f, "env", m->client_environment);
+
+ if (m->notify_fd >= 0) {
+ r = serialize_fd(f, fds, "notify-fd", m->notify_fd);
+ if (r < 0)
+ return r;
+
+ (void) serialize_item(f, "notify-socket", m->notify_socket);
+ }
+
+ if (m->cgroups_agent_fd >= 0) {
+ r = serialize_fd(f, fds, "cgroups-agent-fd", m->cgroups_agent_fd);
+ if (r < 0)
+ return r;
+ }
+
+ if (m->user_lookup_fds[0] >= 0) {
+ int copy0, copy1;
+
+ copy0 = fdset_put_dup(fds, m->user_lookup_fds[0]);
+ if (copy0 < 0)
+ return log_error_errno(copy0, "Failed to add user lookup fd to serialization: %m");
+
+ copy1 = fdset_put_dup(fds, m->user_lookup_fds[1]);
+ if (copy1 < 0)
+ return log_error_errno(copy1, "Failed to add user lookup fd to serialization: %m");
+
+ (void) serialize_item_format(f, "user-lookup", "%i %i", copy0, copy1);
+ }
+
+ bus_track_serialize(m->subscribed, f, "subscribed");
+
+ r = dynamic_user_serialize(m, f, fds);
+ if (r < 0)
+ return r;
+
+ manager_serialize_uid_refs(m, f);
+ manager_serialize_gid_refs(m, f);
+
+ r = exec_runtime_serialize(m, f, fds);
+ if (r < 0)
+ return r;
+
+ (void) fputc('\n', f);
+
+ HASHMAP_FOREACH_KEY(u, t, m->units) {
+ if (u->id != t)
+ continue;
+
+ r = unit_serialize(u, f, fds, switching_root);
+ if (r < 0)
+ return r;
+ }
+
+ r = fflush_and_check(f);
+ if (r < 0)
+ return log_error_errno(r, "Failed to flush serialization: %m");
+
+ r = bus_fdset_add_all(m, fds);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add bus sockets to serialization: %m");
+
+ return 0;
+}
+
+static int manager_deserialize_one_unit(Manager *m, const char *name, FILE *f, FDSet *fds) {
+ Unit *u;
+ int r;
+
+ r = manager_load_unit(m, name, NULL, NULL, &u);
+ if (r < 0) {
+ if (r == -ENOMEM)
+ return r;
+ return log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", name);
+ }
+
+ r = unit_deserialize(u, f, fds);
+ if (r < 0) {
+ if (r == -ENOMEM)
+ return r;
+ return log_notice_errno(r, "Failed to deserialize unit \"%s\", skipping: %m", name);
+ }
+
+ return 0;
+}
+
+static int manager_deserialize_units(Manager *m, FILE *f, FDSet *fds) {
+ const char *unit_name;
+ int r;
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+ /* Start marker */
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read serialization line: %m");
+ if (r == 0)
+ break;
+
+ unit_name = strstrip(line);
+
+ r = manager_deserialize_one_unit(m, unit_name, f, fds);
+ if (r == -ENOMEM)
+ return r;
+ if (r < 0) {
+ r = unit_deserialize_skip(f);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+static void manager_deserialize_uid_refs_one_internal(
+ Hashmap** uid_refs,
+ const char *value) {
+
+ uid_t uid;
+ uint32_t c;
+ int r;
+
+ assert(uid_refs);
+ assert(value);
+
+ r = parse_uid(value, &uid);
+ if (r < 0 || uid == 0) {
+ log_debug("Unable to parse UID/GID reference serialization: " UID_FMT, uid);
+ return;
+ }
+
+ if (hashmap_ensure_allocated(uid_refs, &trivial_hash_ops) < 0) {
+ log_oom();
+ return;
+ }
+
+ c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid)));
+ if (c & DESTROY_IPC_FLAG)
+ return;
+
+ c |= DESTROY_IPC_FLAG;
+
+ r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c));
+ if (r < 0) {
+ log_debug_errno(r, "Failed to add UID/GID reference entry: %m");
+ return;
+ }
+}
+
+static void manager_deserialize_uid_refs_one(Manager *m, const char *value) {
+ manager_deserialize_uid_refs_one_internal(&m->uid_refs, value);
+}
+
+static void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
+ manager_deserialize_uid_refs_one_internal(&m->gid_refs, value);
+}
+
+int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
+ int r = 0;
+
+ assert(m);
+ assert(f);
+
+ if (DEBUG_LOGGING) {
+ if (fdset_isempty(fds))
+ log_debug("No file descriptors passed");
+ else {
+ int fd;
+
+ FDSET_FOREACH(fd, fds) {
+ _cleanup_free_ char *fn = NULL;
+
+ r = fd_get_path(fd, &fn);
+ if (r < 0)
+ log_debug_errno(r, "Received serialized fd %i → %m", fd);
+ else
+ log_debug("Received serialized fd %i → %s", fd, strna(fn));
+ }
+ }
+ }
+
+ log_debug("Deserializing state...");
+
+ /* If we are not in reload mode yet, enter it now. Not that this is recursive, a caller might already have
+ * increased it to non-zero, which is why we just increase it by one here and down again at the end of this
+ * call. */
+ _cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m);
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+ const char *val, *l;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read serialization line: %m");
+ if (r == 0)
+ break;
+
+ l = strstrip(line);
+ if (isempty(l)) /* end marker */
+ break;
+
+ if ((val = startswith(l, "current-job-id="))) {
+ uint32_t id;
+
+ if (safe_atou32(val, &id) < 0)
+ log_notice("Failed to parse current job id value '%s', ignoring.", val);
+ else
+ m->current_job_id = MAX(m->current_job_id, id);
+
+ } else if ((val = startswith(l, "n-installed-jobs="))) {
+ uint32_t n;
+
+ if (safe_atou32(val, &n) < 0)
+ log_notice("Failed to parse installed jobs counter '%s', ignoring.", val);
+ else
+ m->n_installed_jobs += n;
+
+ } else if ((val = startswith(l, "n-failed-jobs="))) {
+ uint32_t n;
+
+ if (safe_atou32(val, &n) < 0)
+ log_notice("Failed to parse failed jobs counter '%s', ignoring.", val);
+ else
+ m->n_failed_jobs += n;
+
+ } else if ((val = startswith(l, "taint-usr="))) {
+ int b;
+
+ b = parse_boolean(val);
+ if (b < 0)
+ log_notice("Failed to parse taint /usr flag '%s', ignoring.", val);
+ else
+ m->taint_usr = m->taint_usr || b;
+
+ } else if ((val = startswith(l, "ready-sent="))) {
+ int b;
+
+ b = parse_boolean(val);
+ if (b < 0)
+ log_notice("Failed to parse ready-sent flag '%s', ignoring.", val);
+ else
+ m->ready_sent = m->ready_sent || b;
+
+ } else if ((val = startswith(l, "taint-logged="))) {
+ int b;
+
+ b = parse_boolean(val);
+ if (b < 0)
+ log_notice("Failed to parse taint-logged flag '%s', ignoring.", val);
+ else
+ m->taint_logged = m->taint_logged || b;
+
+ } else if ((val = startswith(l, "service-watchdogs="))) {
+ int b;
+
+ b = parse_boolean(val);
+ if (b < 0)
+ log_notice("Failed to parse service-watchdogs flag '%s', ignoring.", val);
+ else
+ m->service_watchdogs = b;
+
+ } else if ((val = startswith(l, "honor-device-enumeration="))) {
+ int b;
+
+ b = parse_boolean(val);
+ if (b < 0)
+ log_notice("Failed to parse honor-device-enumeration flag '%s', ignoring.", val);
+ else
+ m->honor_device_enumeration = b;
+
+ } else if ((val = startswith(l, "show-status-overridden="))) {
+ ShowStatus s;
+
+ s = show_status_from_string(val);
+ if (s < 0)
+ log_notice("Failed to parse show-status-overridden flag '%s', ignoring.", val);
+ else
+ manager_override_show_status(m, s, "deserialize");
+
+ } else if ((val = startswith(l, "log-level-override="))) {
+ int level;
+
+ level = log_level_from_string(val);
+ if (level < 0)
+ log_notice("Failed to parse log-level-override value '%s', ignoring.", val);
+ else
+ manager_override_log_level(m, level);
+
+ } else if ((val = startswith(l, "log-target-override="))) {
+ LogTarget target;
+
+ target = log_target_from_string(val);
+ if (target < 0)
+ log_notice("Failed to parse log-target-override value '%s', ignoring.", val);
+ else
+ manager_override_log_target(m, target);
+
+ } else if ((val = startswith(l, "runtime-watchdog-overridden="))) {
+ usec_t t;
+
+ if (deserialize_usec(val, &t) < 0)
+ log_notice("Failed to parse runtime-watchdog-overridden value '%s', ignoring.", val);
+ else
+ manager_override_watchdog(m, WATCHDOG_RUNTIME, t);
+
+ } else if ((val = startswith(l, "reboot-watchdog-overridden="))) {
+ usec_t t;
+
+ if (deserialize_usec(val, &t) < 0)
+ log_notice("Failed to parse reboot-watchdog-overridden value '%s', ignoring.", val);
+ else
+ manager_override_watchdog(m, WATCHDOG_REBOOT, t);
+
+ } else if ((val = startswith(l, "kexec-watchdog-overridden="))) {
+ usec_t t;
+
+ if (deserialize_usec(val, &t) < 0)
+ log_notice("Failed to parse kexec-watchdog-overridden value '%s', ignoring.", val);
+ else
+ manager_override_watchdog(m, WATCHDOG_KEXEC, t);
+
+ } else if (startswith(l, "env=")) {
+ r = deserialize_environment(l + 4, &m->client_environment);
+ if (r < 0)
+ log_notice_errno(r, "Failed to parse environment entry: \"%s\", ignoring: %m", l);
+
+ } else if ((val = startswith(l, "notify-fd="))) {
+ int fd;
+
+ if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
+ log_notice("Failed to parse notify fd, ignoring: \"%s\"", val);
+ else {
+ m->notify_event_source = sd_event_source_disable_unref(m->notify_event_source);
+ safe_close(m->notify_fd);
+ m->notify_fd = fdset_remove(fds, fd);
+ }
+
+ } else if ((val = startswith(l, "notify-socket="))) {
+ r = free_and_strdup(&m->notify_socket, val);
+ if (r < 0)
+ return r;
+
+ } else if ((val = startswith(l, "cgroups-agent-fd="))) {
+ int fd;
+
+ if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
+ log_notice("Failed to parse cgroups agent fd, ignoring.: %s", val);
+ else {
+ m->cgroups_agent_event_source = sd_event_source_disable_unref(m->cgroups_agent_event_source);
+ safe_close(m->cgroups_agent_fd);
+ m->cgroups_agent_fd = fdset_remove(fds, fd);
+ }
+
+ } else if ((val = startswith(l, "user-lookup="))) {
+ int fd0, fd1;
+
+ if (sscanf(val, "%i %i", &fd0, &fd1) != 2 || fd0 < 0 || fd1 < 0 || fd0 == fd1 || !fdset_contains(fds, fd0) || !fdset_contains(fds, fd1))
+ log_notice("Failed to parse user lookup fd, ignoring: %s", val);
+ else {
+ m->user_lookup_event_source = sd_event_source_disable_unref(m->user_lookup_event_source);
+ safe_close_pair(m->user_lookup_fds);
+ m->user_lookup_fds[0] = fdset_remove(fds, fd0);
+ m->user_lookup_fds[1] = fdset_remove(fds, fd1);
+ }
+
+ } else if ((val = startswith(l, "dynamic-user=")))
+ dynamic_user_deserialize_one(m, val, fds);
+ else if ((val = startswith(l, "destroy-ipc-uid=")))
+ manager_deserialize_uid_refs_one(m, val);
+ else if ((val = startswith(l, "destroy-ipc-gid=")))
+ manager_deserialize_gid_refs_one(m, val);
+ else if ((val = startswith(l, "exec-runtime=")))
+ (void) exec_runtime_deserialize_one(m, val, fds);
+ else if ((val = startswith(l, "subscribed="))) {
+
+ if (strv_extend(&m->deserialized_subscribed, val) < 0)
+ return -ENOMEM;
+
+ } else {
+ ManagerTimestamp q;
+
+ for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
+ val = startswith(l, manager_timestamp_to_string(q));
+ if (!val)
+ continue;
+
+ val = startswith(val, "-timestamp=");
+ if (val)
+ break;
+ }
+
+ if (q < _MANAGER_TIMESTAMP_MAX) /* found it */
+ (void) deserialize_dual_timestamp(val, m->timestamps + q);
+ else if (!startswith(l, "kdbus-fd=")) /* ignore kdbus */
+ log_notice("Unknown serialization item '%s', ignoring.", l);
+ }
+ }
+
+ return manager_deserialize_units(m, f, fds);
+}
diff --git a/src/core/manager-serialize.h b/src/core/manager-serialize.h
new file mode 100644
index 0000000000..c52261e378
--- /dev/null
+++ b/src/core/manager-serialize.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <stdbool.h>
+
+#include "manager.h"
+#include "fdset.h"
+
+#define DESTROY_IPC_FLAG (UINT32_C(1) << 31)
+
+int manager_open_serialization(Manager *m, FILE **ret_f);
+int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root);
+int manager_deserialize(Manager *m, FILE *f, FDSet *fds);
diff --git a/src/core/manager.c b/src/core/manager.c
index 18bdd83342..72f1e109d7 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -56,6 +56,7 @@
#include "macro.h"
#include "manager.h"
#include "manager-dump.h"
+#include "manager-serialize.h"
#include "memory-util.h"
#include "mkdir.h"
#include "parse-util.h"
@@ -66,7 +67,6 @@
#include "rlimit-util.h"
#include "rm-rf.h"
#include "selinux-util.h"
-#include "serialize.h"
#include "signal-util.h"
#include "socket-util.h"
#include "special.h"
@@ -82,7 +82,6 @@
#include "transaction.h"
#include "umask-util.h"
#include "unit-name.h"
-#include "unit-serialize.h"
#include "user-util.h"
#include "virt.h"
#include "watchdog.h"
@@ -1686,11 +1685,11 @@ static void manager_ready(Manager *m) {
m->honor_device_enumeration = true;
}
-static Manager* manager_reloading_start(Manager *m) {
+Manager* manager_reloading_start(Manager *m) {
m->n_reloading++;
return m;
}
-static void manager_reloading_stopp(Manager **m) {
+void manager_reloading_stopp(Manager **m) {
if (*m) {
assert((*m)->n_reloading > 0);
(*m)->n_reloading--;
@@ -3154,242 +3153,6 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) {
log_error_errno(errno, "Failed to write Plymouth message: %m");
}
-int manager_open_serialization(Manager *m, FILE **_f) {
- _cleanup_close_ int fd = -1;
- FILE *f;
-
- assert(_f);
-
- fd = open_serialization_fd("systemd-state");
- if (fd < 0)
- return fd;
-
- f = take_fdopen(&fd, "w+");
- if (!f)
- return -errno;
-
- *_f = f;
- return 0;
-}
-
-static bool manager_timestamp_shall_serialize(ManagerTimestamp t) {
-
- if (!in_initrd())
- return true;
-
- /* The following timestamps only apply to the host system, hence only serialize them there */
- return !IN_SET(t,
- MANAGER_TIMESTAMP_USERSPACE, MANAGER_TIMESTAMP_FINISH,
- MANAGER_TIMESTAMP_SECURITY_START, MANAGER_TIMESTAMP_SECURITY_FINISH,
- MANAGER_TIMESTAMP_GENERATORS_START, MANAGER_TIMESTAMP_GENERATORS_FINISH,
- MANAGER_TIMESTAMP_UNITS_LOAD_START, MANAGER_TIMESTAMP_UNITS_LOAD_FINISH);
-}
-
-#define DESTROY_IPC_FLAG (UINT32_C(1) << 31)
-
-static void manager_serialize_uid_refs_internal(
- FILE *f,
- Hashmap *uid_refs,
- const char *field_name) {
-
- void *p, *k;
-
- assert(f);
- assert(field_name);
-
- /* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as
- * the actual counter of it is better rebuild after a reload/reexec. */
-
- HASHMAP_FOREACH_KEY(p, k, uid_refs) {
- uint32_t c;
- uid_t uid;
-
- uid = PTR_TO_UID(k);
- c = PTR_TO_UINT32(p);
-
- if (!(c & DESTROY_IPC_FLAG))
- continue;
-
- (void) serialize_item_format(f, field_name, UID_FMT, uid);
- }
-}
-
-static void manager_serialize_uid_refs(Manager *m, FILE *f) {
- manager_serialize_uid_refs_internal(f, m->uid_refs, "destroy-ipc-uid");
-}
-
-static void manager_serialize_gid_refs(Manager *m, FILE *f) {
- manager_serialize_uid_refs_internal(f, m->gid_refs, "destroy-ipc-gid");
-}
-
-int manager_serialize(
- Manager *m,
- FILE *f,
- FDSet *fds,
- bool switching_root) {
-
- const char *t;
- Unit *u;
- int r;
-
- assert(m);
- assert(f);
- assert(fds);
-
- _cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m);
-
- (void) serialize_item_format(f, "current-job-id", "%" PRIu32, m->current_job_id);
- (void) serialize_item_format(f, "n-installed-jobs", "%u", m->n_installed_jobs);
- (void) serialize_item_format(f, "n-failed-jobs", "%u", m->n_failed_jobs);
- (void) serialize_bool(f, "taint-usr", m->taint_usr);
- (void) serialize_bool(f, "ready-sent", m->ready_sent);
- (void) serialize_bool(f, "taint-logged", m->taint_logged);
- (void) serialize_bool(f, "service-watchdogs", m->service_watchdogs);
-
- /* After switching root, udevd has not been started yet. So, enumeration results should not be emitted. */
- (void) serialize_bool(f, "honor-device-enumeration", !switching_root);
-
- if (m->show_status_overridden != _SHOW_STATUS_INVALID)
- (void) serialize_item(f, "show-status-overridden",
- show_status_to_string(m->show_status_overridden));
-
- if (m->log_level_overridden)
- (void) serialize_item_format(f, "log-level-override", "%i", log_get_max_level());
- if (m->log_target_overridden)
- (void) serialize_item(f, "log-target-override", log_target_to_string(log_get_target()));
-
- (void) serialize_usec(f, "runtime-watchdog-overridden", m->watchdog_overridden[WATCHDOG_RUNTIME]);
- (void) serialize_usec(f, "reboot-watchdog-overridden", m->watchdog_overridden[WATCHDOG_REBOOT]);
- (void) serialize_usec(f, "kexec-watchdog-overridden", m->watchdog_overridden[WATCHDOG_KEXEC]);
-
- for (ManagerTimestamp q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
- _cleanup_free_ char *joined = NULL;
-
- if (!manager_timestamp_shall_serialize(q))
- continue;
-
- joined = strjoin(manager_timestamp_to_string(q), "-timestamp");
- if (!joined)
- return log_oom();
-
- (void) serialize_dual_timestamp(f, joined, m->timestamps + q);
- }
-
- if (!switching_root)
- (void) serialize_strv(f, "env", m->client_environment);
-
- if (m->notify_fd >= 0) {
- r = serialize_fd(f, fds, "notify-fd", m->notify_fd);
- if (r < 0)
- return r;
-
- (void) serialize_item(f, "notify-socket", m->notify_socket);
- }
-
- if (m->cgroups_agent_fd >= 0) {
- r = serialize_fd(f, fds, "cgroups-agent-fd", m->cgroups_agent_fd);
- if (r < 0)
- return r;
- }
-
- if (m->user_lookup_fds[0] >= 0) {
- int copy0, copy1;
-
- copy0 = fdset_put_dup(fds, m->user_lookup_fds[0]);
- if (copy0 < 0)
- return log_error_errno(copy0, "Failed to add user lookup fd to serialization: %m");
-
- copy1 = fdset_put_dup(fds, m->user_lookup_fds[1]);
- if (copy1 < 0)
- return log_error_errno(copy1, "Failed to add user lookup fd to serialization: %m");
-
- (void) serialize_item_format(f, "user-lookup", "%i %i", copy0, copy1);
- }
-
- bus_track_serialize(m->subscribed, f, "subscribed");
-
- r = dynamic_user_serialize(m, f, fds);
- if (r < 0)
- return r;
-
- manager_serialize_uid_refs(m, f);
- manager_serialize_gid_refs(m, f);
-
- r = exec_runtime_serialize(m, f, fds);
- if (r < 0)
- return r;
-
- (void) fputc('\n', f);
-
- HASHMAP_FOREACH_KEY(u, t, m->units) {
- if (u->id != t)
- continue;
-
- r = unit_serialize(u, f, fds, switching_root);
- if (r < 0)
- return r;
- }
-
- r = fflush_and_check(f);
- if (r < 0)
- return log_error_errno(r, "Failed to flush serialization: %m");
-
- r = bus_fdset_add_all(m, fds);
- if (r < 0)
- return log_error_errno(r, "Failed to add bus sockets to serialization: %m");
-
- return 0;
-}
-
-static int manager_deserialize_one_unit(Manager *m, const char *name, FILE *f, FDSet *fds) {
- Unit *u;
- int r;
-
- r = manager_load_unit(m, name, NULL, NULL, &u);
- if (r < 0) {
- if (r == -ENOMEM)
- return r;
- return log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", name);
- }
-
- r = unit_deserialize(u, f, fds);
- if (r < 0) {
- if (r == -ENOMEM)
- return r;
- return log_notice_errno(r, "Failed to deserialize unit \"%s\", skipping: %m", name);
- }
-
- return 0;
-}
-
-static int manager_deserialize_units(Manager *m, FILE *f, FDSet *fds) {
- const char *unit_name;
- int r;
-
- for (;;) {
- _cleanup_free_ char *line = NULL;
- /* Start marker */
- r = read_line(f, LONG_LINE_MAX, &line);
- if (r < 0)
- return log_error_errno(r, "Failed to read serialization line: %m");
- if (r == 0)
- break;
-
- unit_name = strstrip(line);
-
- r = manager_deserialize_one_unit(m, unit_name, f, fds);
- if (r == -ENOMEM)
- return r;
- if (r < 0) {
- r = unit_deserialize_skip(f);
- if (r < 0)
- return r;
- }
- }
-
- return 0;
-}
-
usec_t manager_get_watchdog(Manager *m, WatchdogType t) {
assert(m);
@@ -3474,294 +3237,6 @@ void manager_retry_runtime_watchdog(Manager *m) {
m->runtime_watchdog_running = true;
}
-static void manager_deserialize_uid_refs_one_internal(
- Hashmap** uid_refs,
- const char *value) {
-
- uid_t uid;
- uint32_t c;
- int r;
-
- assert(uid_refs);
- assert(value);
-
- r = parse_uid(value, &uid);
- if (r < 0 || uid == 0) {
- log_debug("Unable to parse UID/GID reference serialization: " UID_FMT, uid);
- return;
- }
-
- if (hashmap_ensure_allocated(uid_refs, &trivial_hash_ops) < 0) {
- log_oom();
- return;
- }
-
- c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid)));
- if (c & DESTROY_IPC_FLAG)
- return;
-
- c |= DESTROY_IPC_FLAG;
-
- r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c));
- if (r < 0) {
- log_debug_errno(r, "Failed to add UID/GID reference entry: %m");
- return;
- }
-}
-
-static void manager_deserialize_uid_refs_one(Manager *m, const char *value) {
- manager_deserialize_uid_refs_one_internal(&m->uid_refs, value);
-}
-
-static void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
- manager_deserialize_uid_refs_one_internal(&m->gid_refs, value);
-}
-
-int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
- int r = 0;
-
- assert(m);
- assert(f);
-
- if (DEBUG_LOGGING) {
- if (fdset_isempty(fds))
- log_debug("No file descriptors passed");
- else {
- int fd;
-
- FDSET_FOREACH(fd, fds) {
- _cleanup_free_ char *fn = NULL;
-
- r = fd_get_path(fd, &fn);
- if (r < 0)
- log_debug_errno(r, "Received serialized fd %i → %m", fd);
- else
- log_debug("Received serialized fd %i → %s", fd, strna(fn));
- }
- }
- }
-
- log_debug("Deserializing state...");
-
- /* If we are not in reload mode yet, enter it now. Not that this is recursive, a caller might already have
- * increased it to non-zero, which is why we just increase it by one here and down again at the end of this
- * call. */
- _cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m);
-
- for (;;) {
- _cleanup_free_ char *line = NULL;
- const char *val, *l;
-
- r = read_line(f, LONG_LINE_MAX, &line);
- if (r < 0)
- return log_error_errno(r, "Failed to read serialization line: %m");
- if (r == 0)
- break;
-
- l = strstrip(line);
- if (isempty(l)) /* end marker */
- break;
-
- if ((val = startswith(l, "current-job-id="))) {
- uint32_t id;
-
- if (safe_atou32(val, &id) < 0)
- log_notice("Failed to parse current job id value '%s', ignoring.", val);
- else
- m->current_job_id = MAX(m->current_job_id, id);
-
- } else if ((val = startswith(l, "n-installed-jobs="))) {
- uint32_t n;
-
- if (safe_atou32(val, &n) < 0)
- log_notice("Failed to parse installed jobs counter '%s', ignoring.", val);
- else
- m->n_installed_jobs += n;
-
- } else if ((val = startswith(l, "n-failed-jobs="))) {
- uint32_t n;
-
- if (safe_atou32(val, &n) < 0)
- log_notice("Failed to parse failed jobs counter '%s', ignoring.", val);
- else
- m->n_failed_jobs += n;
-
- } else if ((val = startswith(l, "taint-usr="))) {
- int b;
-
- b = parse_boolean(val);
- if (b < 0)
- log_notice("Failed to parse taint /usr flag '%s', ignoring.", val);
- else
- m->taint_usr = m->taint_usr || b;
-
- } else if ((val = startswith(l, "ready-sent="))) {
- int b;
-
- b = parse_boolean(val);
- if (b < 0)
- log_notice("Failed to parse ready-sent flag '%s', ignoring.", val);
- else
- m->ready_sent = m->ready_sent || b;
-
- } else if ((val = startswith(l, "taint-logged="))) {
- int b;
-
- b = parse_boolean(val);
- if (b < 0)
- log_notice("Failed to parse taint-logged flag '%s', ignoring.", val);
- else
- m->taint_logged = m->taint_logged || b;
-
- } else if ((val = startswith(l, "service-watchdogs="))) {
- int b;
-
- b = parse_boolean(val);
- if (b < 0)
- log_notice("Failed to parse service-watchdogs flag '%s', ignoring.", val);
- else
- m->service_watchdogs = b;
-
- } else if ((val = startswith(l, "honor-device-enumeration="))) {
- int b;
-
- b = parse_boolean(val);
- if (b < 0)
- log_notice("Failed to parse honor-device-enumeration flag '%s', ignoring.", val);
- else
- m->honor_device_enumeration = b;
-
- } else if ((val = startswith(l, "show-status-overridden="))) {
- ShowStatus s;
-
- s = show_status_from_string(val);
- if (s < 0)
- log_notice("Failed to parse show-status-overridden flag '%s', ignoring.", val);
- else
- manager_override_show_status(m, s, "deserialize");
-
- } else if ((val = startswith(l, "log-level-override="))) {
- int level;
-
- level = log_level_from_string(val);
- if (level < 0)
- log_notice("Failed to parse log-level-override value '%s', ignoring.", val);
- else
- manager_override_log_level(m, level);
-
- } else if ((val = startswith(l, "log-target-override="))) {
- LogTarget target;
-
- target = log_target_from_string(val);
- if (target < 0)
- log_notice("Failed to parse log-target-override value '%s', ignoring.", val);
- else
- manager_override_log_target(m, target);
-
- } else if ((val = startswith(l, "runtime-watchdog-overridden="))) {
- usec_t t;
-
- if (deserialize_usec(val, &t) < 0)
- log_notice("Failed to parse runtime-watchdog-overridden value '%s', ignoring.", val);
- else
- manager_override_watchdog(m, WATCHDOG_RUNTIME, t);
-
- } else if ((val = startswith(l, "reboot-watchdog-overridden="))) {
- usec_t t;
-
- if (deserialize_usec(val, &t) < 0)
- log_notice("Failed to parse reboot-watchdog-overridden value '%s', ignoring.", val);
- else
- manager_override_watchdog(m, WATCHDOG_REBOOT, t);
-
- } else if ((val = startswith(l, "kexec-watchdog-overridden="))) {
- usec_t t;
-
- if (deserialize_usec(val, &t) < 0)
- log_notice("Failed to parse kexec-watchdog-overridden value '%s', ignoring.", val);
- else
- manager_override_watchdog(m, WATCHDOG_KEXEC, t);
-
- } else if (startswith(l, "env=")) {
- r = deserialize_environment(l + 4, &m->client_environment);
- if (r < 0)
- log_notice_errno(r, "Failed to parse environment entry: \"%s\", ignoring: %m", l);
-
- } else if ((val = startswith(l, "notify-fd="))) {
- int fd;
-
- if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
- log_notice("Failed to parse notify fd, ignoring: \"%s\"", val);
- else {
- m->notify_event_source = sd_event_source_disable_unref(m->notify_event_source);
- safe_close(m->notify_fd);
- m->notify_fd = fdset_remove(fds, fd);
- }
-
- } else if ((val = startswith(l, "notify-socket="))) {
- r = free_and_strdup(&m->notify_socket, val);
- if (r < 0)
- return r;
-
- } else if ((val = startswith(l, "cgroups-agent-fd="))) {
- int fd;
-
- if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
- log_notice("Failed to parse cgroups agent fd, ignoring.: %s", val);
- else {
- m->cgroups_agent_event_source = sd_event_source_disable_unref(m->cgroups_agent_event_source);
- safe_close(m->cgroups_agent_fd);
- m->cgroups_agent_fd = fdset_remove(fds, fd);
- }
-
- } else if ((val = startswith(l, "user-lookup="))) {
- int fd0, fd1;
-
- if (sscanf(val, "%i %i", &fd0, &fd1) != 2 || fd0 < 0 || fd1 < 0 || fd0 == fd1 || !fdset_contains(fds, fd0) || !fdset_contains(fds, fd1))
- log_notice("Failed to parse user lookup fd, ignoring: %s", val);
- else {
- m->user_lookup_event_source = sd_event_source_disable_unref(m->user_lookup_event_source);
- safe_close_pair(m->user_lookup_fds);
- m->user_lookup_fds[0] = fdset_remove(fds, fd0);
- m->user_lookup_fds[1] = fdset_remove(fds, fd1);
- }
-
- } else if ((val = startswith(l, "dynamic-user=")))
- dynamic_user_deserialize_one(m, val, fds);
- else if ((val = startswith(l, "destroy-ipc-uid=")))
- manager_deserialize_uid_refs_one(m, val);
- else if ((val = startswith(l, "destroy-ipc-gid=")))
- manager_deserialize_gid_refs_one(m, val);
- else if ((val = startswith(l, "exec-runtime=")))
- (void) exec_runtime_deserialize_one(m, val, fds);
- else if ((val = startswith(l, "subscribed="))) {
-
- if (strv_extend(&m->deserialized_subscribed, val) < 0)
- return -ENOMEM;
-
- } else {
- ManagerTimestamp q;
-
- for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
- val = startswith(l, manager_timestamp_to_string(q));
- if (!val)
- continue;
-
- val = startswith(val, "-timestamp=");
- if (val)
- break;
- }
-
- if (q < _MANAGER_TIMESTAMP_MAX) /* found it */
- (void) deserialize_dual_timestamp(val, m->timestamps + q);
- else if (!startswith(l, "kdbus-fd=")) /* ignore kdbus */
- log_notice("Unknown serialization item '%s', ignoring.", l);
- }
- }
-
- return manager_deserialize_units(m, f, fds);
-}
-
int manager_reload(Manager *m) {
_cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
_cleanup_fdset_free_ FDSet *fds = NULL;
diff --git a/src/core/manager.h b/src/core/manager.h
index b3e7c68e6d..6b1ed48beb 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -500,12 +500,9 @@ int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit);
int manager_loop(Manager *m);
-int manager_open_serialization(Manager *m, FILE **_f);
-
-int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root);
-int manager_deserialize(Manager *m, FILE *f, FDSet *fds);
-
int manager_reload(Manager *m);
+Manager* manager_reloading_start(Manager *m);
+void manager_reloading_stopp(Manager **m);
void manager_reset_failed(Manager *m);
diff --git a/src/core/meson.build b/src/core/meson.build
index f0d2c6f642..1c364a53e2 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -87,6 +87,8 @@ libcore_sources = '''
locale-setup.h
manager-dump.c
manager-dump.h
+ manager-serialize.c
+ manager-serialize.h
manager.c
manager.h
mount.c