/
niceSOFT
/
systemd
Обзор
Документация
Войти
/
niceSOFT
/
systemd
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/core/manager-serialize.c
839 строк
36 KB
Sinity
core/dbus: do not block the manager on GetId during bus (re-)connection
20 июл 2026, 05:53
20 июл 2026, 05:53
1166f44
Код
Авторство
О чём код?
/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "sd-id128.h" #include "alloc-util.h" #include "bpf-restrict-fsaccess.h" #include "dbus.h" #include "dynamic-user.h" #include "fd-util.h" #include "fdset.h" #include "fileio.h" #include "format-util.h" #include "glyph-util.h" #include "hashmap.h" #include "initrd-util.h" #include "job.h" #include "manager.h" #include "manager-serialize.h" #include "parse-util.h" #include "serialize.h" #include "set.h" #include "string-util.h" #include "strv.h" #include "syslog-util.h" #include "unit.h" #include "unit-name.h" #include "unit-serialize.h" #include "user-util.h" #include "varlink.h" #include "varlink-serialize.h" int manager_open_serialization(Manager *m, FILE **ret_f) { assert(ret_f); return open_serialization_file("systemd-state", ret_f); } static bool manager_timestamp_shall_serialize(ManagerTimestamp t) { if (!in_initrd()) return true; /* In the initrd the following timestamps describe the host boot we are about to hand over to, * which re-takes them, so don't serialize them. */ 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 ManagerTimestamp map_timestamp_serialization(ManagerObjective previous_objective, ManagerTimestamp t) { /* Returns the timestamp field a serialized timestamp 't' should be deserialized into, given the * objective the previous instance serialized under, or _MANAGER_TIMESTAMP_INVALID to drop it. */ /* Both across a soft-reboot and a switch-root the new instance runs through the early boot phases * again, so drop those timestamps to have them re-measured; the firmware/loader/kernel/initrd ones * are kept. */ if (IN_SET(previous_objective, MANAGER_SOFT_REBOOT, MANAGER_SWITCH_ROOT) && 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)) return _MANAGER_TIMESTAMP_INVALID; /* Across a soft-reboot the old instance's shutdown timestamps describe the boot that is going away, * so move them into the previous-shutdown-* fields. */ if (previous_objective == MANAGER_SOFT_REBOOT) switch (t) { case MANAGER_TIMESTAMP_SHUTDOWN_START: return MANAGER_TIMESTAMP_PREVIOUS_SHUTDOWN_START; case MANAGER_TIMESTAMP_SHUTDOWN_FINISH: return MANAGER_TIMESTAMP_PREVIOUS_SHUTDOWN_FINISH; default: break; } return t; } 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, "last-transaction-id", "%" PRIu64, m->last_transaction_id); (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-logged", m->taint_logged); (void) serialize_bool(f, "service-watchdogs", m->service_watchdogs); 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]); (void) serialize_usec(f, "pretimeout-watchdog-overridden", m->watchdog_overridden[WATCHDOG_PRETIMEOUT]); (void) serialize_item(f, "pretimeout-watchdog-governor-overridden", m->watchdog_pretimeout_governor_overridden); (void) serialize_item(f, "previous-objective", manager_objective_to_string(m->objective)); (void) serialize_item_format(f, "soft-reboots-count", "%u", m->soft_reboots_count); (void) serialize_item_format(f, "kexecs-count", "%u", m->kexecs_count); (void) serialize_item_format(f, "fd-store-upstream-next-index", "%" PRIu64, m->fd_store_upstream_next_index); 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->user_lookup_fds[0] >= 0) { r = serialize_fd_many(f, fds, "user-lookup", m->user_lookup_fds, 2); if (r < 0) return r; } if (m->handoff_timestamp_fds[0] >= 0) { r = serialize_fd_many(f, fds, "handoff-timestamp-fds", m->handoff_timestamp_fds, 2); if (r < 0) return r; } (void) serialize_ratelimit(f, "dump-ratelimit", &m->dump_ratelimit); (void) serialize_ratelimit(f, "reload-reexec-ratelimit", &m->reload_reexec_ratelimit); (void) serialize_ratelimit(f, "event-loop-ratelimit", &m->event_loop_ratelimit); (void) serialize_id128(f, "bus-id", sd_id128_is_null(m->bus_id) ? m->deserialized_bus_id : m->bus_id); bus_track_serialize(m->subscribed, f, "subscribed"); (void) serialize_strv(f, "subscribed", m->subscribed_as_strv); 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_shared_runtime_serialize(m, f, fds); if (r < 0) return r; r = varlink_server_serialize(m->varlink_server, /* name = */ NULL, f, fds); if (r < 0) return r; r = varlink_server_serialize(m->metrics_varlink_server, "metrics", f, fds); if (r < 0) return r; r = bpf_restrict_fsaccess_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_state(u, f, fds, switching_root); if (r < 0) return r; } 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_collect_serialized_unit_names(FILE *f, Set **ret) { _cleanup_set_free_ Set *serialized_units = NULL; off_t offset; int r; assert(f); assert(ret); offset = ftello(f); if (offset < 0) return log_error_errno(errno, "Failed to determine serialization offset: %m"); for (;;) { _cleanup_free_ char *line = NULL; r = read_stripped_line(f, LONG_LINE_MAX, &line); if (r < 0) return log_error_errno(r, "Failed to read serialization line: %m"); if (r == 0) break; r = set_ensure_consume(&serialized_units, &string_hash_ops_free, TAKE_PTR(line)); if (r < 0) return log_oom(); r = unit_deserialize_state_skip(f); if (r < 0) return r; } if (fseeko(f, offset, SEEK_SET) < 0) return log_error_errno(errno, "Failed to reset serialization offset: %m"); *ret = TAKE_PTR(serialized_units); return 0; } static int manager_synthesize_orphaned_unit( Manager *m, const char *original_name, const char *canonical_name, FILE *f, FDSet *fds) { _cleanup_(unit_freep) Unit *orphan = NULL; _cleanup_free_ char *orphaned_name = NULL; sd_id128_t rnd; UnitType t; int r; assert(m); assert(original_name); assert(canonical_name); assert(f); assert(fds); t = unit_name_to_type(original_name); if (t < 0) return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot synthesize unit for '%s' (overridden by alias to '%s'): invalid unit type. Skipping stale state.", original_name, canonical_name); /* Only transition units that track external resources and can be renamed/know aliases, forget internal ones (eg: timers) */ if (!unit_vtable[t]->track_orphaned) return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Cannot synthesize unit for '%s' (overridden by alias to '%s'): unsupported unit type. Skipping stale state.", original_name, canonical_name); /* Use a naming convention with an "orphaned-" prefix to make it clear at a glance that these units * were synthesized to adopt resources from a now-aliased unit */ r = sd_id128_randomize(&rnd); if (r < 0) return log_warning_errno(r, "Failed to generate random ID for orphan unit: %m"); if (asprintf(&orphaned_name, "orphaned-r" SD_ID128_FORMAT_STR ".%s", SD_ID128_FORMAT_VAL(rnd), unit_type_to_string(t)) < 0) return log_oom(); r = unit_new_for_name(m, unit_vtable[t]->object_size, orphaned_name, &orphan); if (r < 0) return log_warning_errno(r, "Failed to allocate orphan unit '%s': %m", orphaned_name); /* Force the state as we know the unit file is gone, so it will hang around as long as resources are * active, and then it will be automatically collected */ orphan->load_state = UNIT_NOT_FOUND; /* Ensure the orphan also gets garbage-collected when it ends up in 'failed' state. */ orphan->collect_mode = COLLECT_INACTIVE_OR_FAILED; _cleanup_free_ char *description = strjoin("Orphaned resources adopted from aliased unit ", original_name); if (!description) return log_oom(); r = unit_deserialize_state(orphan, f, fds); if (r < 0) return log_notice_errno(r, "Failed to deserialize state into orphan unit '%s': %m", orphaned_name); /* From this point on the serialized stream for this unit has been fully consumed, so avoid failing. */ log_warning("Unit file for '%s' was overridden by a symlink to '%s'. Synthesized orphan unit '%s' to retain tracking of the previous unit's processes.", original_name, canonical_name, orphaned_name); /* Override Description= so it's clear what this is for and can be traced back to the original. */ free_and_replace(orphan->description, description); /* Any jobs reinstalled from the deserialized state targeted the original unit. Most of them * (start, restart, reload, ...) make no sense for the synthesized orphan, especially after a * service-to-scope conversion, so cancel them. JOB_STOP is the exception: a stop request that was * already pending on the original unit is exactly what we want to keep around, since it'll cause * the synthesized unit to just go away immediately. */ if (orphan->job && orphan->job->type != JOB_STOP) job_finish_and_invalidate(orphan->job, JOB_CANCELED, /* recursive= */ false, /* already= */ false); if (orphan->nop_job) job_finish_and_invalidate(orphan->nop_job, JOB_CANCELED, /* recursive= */ false, /* already= */ false); TAKE_PTR(orphan); return 0; } static int manager_deserialize_one_unit( Manager *m, const char *name, FILE *f, FDSet *fds, Set *serialized_units) { Unit *u; int r; r = manager_load_unit(m, name, NULL, NULL, &u); if (r == -ENOMEM) return log_oom(); if (r < 0) return log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", name); if (!streq(u->id, name) && set_contains(serialized_units, u->id)) { /* * The unit from the state file (name) resolved to a different canonical unit (u->id), and * the canonical unit also has its own state entry. * * This means the state entry for the unit name is stale. That is, when the state was * serialized, the name referred to an independent unit, but it now resolves as an alias to * the canonical unit. Deserializing it would overwrite the canonical unit's own serialized * state, and thus corrupt its live runtime state. * * It is very important to note that this only affects units that were independent when the * state file was written, but are now aliases (either because a reload created the symlink, * or the symlink existed but this is the first reload). Normal aliases that were already * aliases during the most recent serialization are filtered out in manager_serialize(), so * they never appear in the state file. * * If the canonical unit does not have its own state entry, then this is instead a rename or * canonical ID change, and this state entry is the only state we have for the unit. In that * case we must preserve it. After doing so, we insert the canonical unit's ID into the set * so that any further aliases resolving to the same unit are skipped. * * The serialized data represents the old, independent unit. Deserializing this stale state * onto the canonical unit would corrupt its live state. Instead, we synthesize a new unloaded * unit with a unique name and migrate the cgroup/PID/etc. tracking from the stale state * into it, so that the resources from the previously independent unit remain tracked. * * Take as an example, a.service is running. Someone created symlink b.service -> a.service. * On first reload, the state file still has b.service as an independent unit (from before * the symlink existed), but b.service now resolves to a.service. We retain a.service's * running state, and synthesize an unloaded unit to keep tracking the processes that * b.service used to own. * * Note: Log messages from this code path are checked in TEST-07-PID1.alias-corruption.sh, * so the test case may need adjustment if they are changed. */ r = manager_synthesize_orphaned_unit(m, name, u->id, f, fds); if (r < 0) /* If we fail to orphan for any reason, then discard the unit */ r = unit_deserialize_state_skip(f); return r; } r = unit_deserialize_state(u, f, fds); if (r == -ENOMEM) return log_oom(); if (r < 0) return log_notice_errno(r, "Failed to deserialize unit \"%s\", skipping: %m", name); /* If this unit was deserialized under an alias name (that is, it is a rename), record the canonical * ID so that any further aliases pointing to the same unit are correctly skipped. */ if (!streq(u->id, name)) { r = set_put_strdup(&serialized_units, u->id); if (r < 0) return log_oom(); } return 0; } static int manager_deserialize_units( Manager *m, FILE *f, FDSet *fds) { _cleanup_set_free_ Set *serialized_units = NULL; int r; r = manager_collect_serialized_unit_names(f, &serialized_units); if (r < 0) return r; for (;;) { _cleanup_free_ char *line = NULL; /* Start marker */ r = read_stripped_line(f, LONG_LINE_MAX, &line); if (r < 0) return log_error_errno(r, "Failed to read serialization line: %m"); if (r == 0) break; r = manager_deserialize_one_unit(m, line, f, fds, serialized_units); if (r == -ENOMEM) return r; if (r < 0) { r = unit_deserialize_state_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: %s", value); 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); } static void deserialize_restrict_fsaccess(Manager *m, const char *l, FDSet *fds) { const char *val; int fd; FOREACH_ELEMENT(name, restrict_fsaccess_link_names) { val = startswith(l, *name); if (!val) continue; val = startswith(val, "="); if (!val) continue; fd = deserialize_fd(fds, val); if (fd < 0) { log_warning_errno(fd, "bpf-restrict-fsaccess: Failed to deserialize FD for %s: %m", *name); return; } close_and_replace(m->restrict_fsaccess_link_fds[name - restrict_fsaccess_link_names], fd); return; } val = startswith(l, "restrict-fsaccess-bss-map="); if (!val) return; fd = deserialize_fd(fds, val); if (fd < 0) { log_warning_errno(fd, "bpf-restrict-fsaccess: Failed to deserialize FD for .bss map: %m"); return; } close_and_replace(m->restrict_fsaccess_bss_map_fd, fd); } int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { int r; 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 %s %m", fd, glyph(GLYPH_ARROW_RIGHT)); else log_debug("Received serialized fd %i %s %s", fd, glyph(GLYPH_ARROW_RIGHT), 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 *l = NULL; const char *val; r = deserialize_read_line(f, &l); if (r < 0) return r; if (r == 0) /* eof or end marker */ break; if ((val = startswith(l, "last-transaction-id="))) { uint64_t id; if (safe_atou64(val, &id) < 0) log_notice("Failed to parse last transaction id value '%s', ignoring.", val); else m->last_transaction_id = MAX(m->last_transaction_id, id); } else 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-logged="))) { r = parse_boolean(val); if (r < 0) log_notice("Failed to parse taint-logged flag '%s', ignoring.", val); else m->taint_logged = m->taint_logged || r; } else if ((val = startswith(l, "service-watchdogs="))) { r = parse_boolean(val); if (r < 0) log_notice("Failed to parse service-watchdogs flag '%s', ignoring.", val); else m->service_watchdogs = r; } 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 ((val = startswith(l, "pretimeout-watchdog-overridden="))) { usec_t t; if (deserialize_usec(val, &t) < 0) log_notice("Failed to parse pretimeout-watchdog-overridden value '%s', ignoring.", val); else manager_override_watchdog(m, WATCHDOG_PRETIMEOUT, t); } else if ((val = startswith(l, "pretimeout-watchdog-governor-overridden="))) { r = free_and_strdup(&m->watchdog_pretimeout_governor_overridden, val); if (r < 0) return r; } else if ((val = startswith(l, "env="))) { r = deserialize_environment(val, &m->client_environment); if (r < 0) log_notice_errno(r, "Failed to parse environment entry: \"%s\", ignoring: %m", val); } else if ((val = startswith(l, "notify-fd="))) { int fd; fd = deserialize_fd(fds, val); if (fd >= 0) { m->notify_event_source = sd_event_source_disable_unref(m->notify_event_source); close_and_replace(m->notify_fd, 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, "user-lookup="))) { m->user_lookup_event_source = sd_event_source_disable_unref(m->user_lookup_event_source); safe_close_pair(m->user_lookup_fds); r = deserialize_fd_many(fds, val, 2, m->user_lookup_fds); if (r < 0) log_warning_errno(r, "Failed to parse user-lookup fds: \"%s\", ignoring: %m", val); } else if ((val = startswith(l, "handoff-timestamp-fds="))) { m->handoff_timestamp_event_source = sd_event_source_disable_unref(m->handoff_timestamp_event_source); safe_close_pair(m->handoff_timestamp_fds); r = deserialize_fd_many(fds, val, 2, m->handoff_timestamp_fds); if (r < 0) log_warning_errno(r, "Failed to parse handoff-timestamp fds: \"%s\", ignoring: %m", val); } else if ((val = startswith(l, "dynamic-user="))) dynamic_user_deserialize_one(m, val, fds, NULL); 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_shared_runtime_deserialize_one(m, val, fds); else if ((val = startswith(l, "bus-id="))) { r = sd_id128_from_string(val, &m->deserialized_bus_id); if (r < 0) return r; } else if ((val = startswith(l, "subscribed="))) { r = strv_extend(&m->subscribed_as_strv, val); if (r < 0) return r; } else if ((val = startswith(l, "varlink-server-metrics-"))) { if (m->objective == MANAGER_RELOAD) /* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */ continue; r = manager_setup_varlink_metrics_server(m); if (r < 0) log_warning_errno(r, "Failed to setup metrics varlink server, ignoring: %m"); else (void) varlink_server_deserialize_one(m->metrics_varlink_server, val, fds); } else if ((val = startswith(l, "varlink-server-"))) { if (m->objective == MANAGER_RELOAD) /* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */ continue; r = manager_setup_varlink_server(m); if (r < 0) log_warning_errno(r, "Failed to setup varlink server, ignoring: %m"); else (void) varlink_server_deserialize_one(m->varlink_server, val, fds); } else if (startswith(l, "restrict-fsaccess-")) deserialize_restrict_fsaccess(m, l, fds); else if ((val = startswith(l, "dump-ratelimit="))) deserialize_ratelimit(&m->dump_ratelimit, "dump-ratelimit", val); else if ((val = startswith(l, "reload-reexec-ratelimit="))) deserialize_ratelimit(&m->reload_reexec_ratelimit, "reload-reexec-ratelimit", val); else if ((val = startswith(l, "event-loop-ratelimit="))) deserialize_ratelimit(&m->event_loop_ratelimit, "event-loop-ratelimit", val); else if ((val = startswith(l, "soft-reboots-count="))) { unsigned n; if (safe_atou(val, &n) < 0) log_notice("Failed to parse soft reboots counter '%s', ignoring.", val); else m->soft_reboots_count = n; } else if ((val = startswith(l, "kexecs-count="))) { unsigned n; if (safe_atou(val, &n) < 0) log_notice("Failed to parse kexecs counter '%s', ignoring.", val); else m->kexecs_count = n; } else if ((val = startswith(l, "fd-store-upstream-next-index="))) { if (safe_atou64(val, &m->fd_store_upstream_next_index) < 0) log_notice("Failed to parse fd-store-upstream-next-index '%s', ignoring.", val); } else if ((val = startswith(l, "previous-objective="))) { ManagerObjective objective; objective = manager_objective_from_string(val); if (objective < 0) log_notice("Failed to parse previous objective '%s', ignoring.", val); else m->previous_objective = objective; } 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 */ ManagerTimestamp target = map_timestamp_serialization(m->previous_objective, q); if (target >= 0) (void) deserialize_dual_timestamp(val, m->timestamps + target); } else if (!STARTSWITH_SET(l, "kdbus-fd=", "honor-device-enumeration=", "ready-sent=", "cgroups-agent-fd=")) /* ignore deprecated values */ log_notice("Unknown serialization item '%s', ignoring.", l); } } return manager_deserialize_units(m, f, fds); }