diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-07-02 15:53:38 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-07-19 11:27:11 +0200 |
commit | a01ba4b2b8deeb31c65f8ed525ebab51972919bf (patch) | |
tree | 12b7af1bfd29760e8e47c3648b1841d25f79c5d7 /src/core | |
parent | 95b63c755b73606e3dce094d92024c1e57ee5ed4 (diff) | |
download | systemd-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.c | 1 | ||||
-rw-r--r-- | src/core/manager-serialize.c | 536 | ||||
-rw-r--r-- | src/core/manager-serialize.h | 13 | ||||
-rw-r--r-- | src/core/manager.c | 531 | ||||
-rw-r--r-- | src/core/manager.h | 7 | ||||
-rw-r--r-- | src/core/meson.build | 2 |
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 |