/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "bpf-socket-bind.h"
#include "bus-util.h"
#include "dbus.h"
#include "fileio-label.h"
[CGROUP_IO_WRITE_OPERATIONS] = "io-accounting-write-operations-last",
};
-int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
+int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool switching_root) {
int r;
assert(u);
assert(f);
assert(fds);
- if (unit_can_serialize(u)) {
+ if (switching_root && UNIT_VTABLE(u)->exclude_from_switch_root_serialization) {
+ /* In the new root, paths for mounts and automounts will be different, so it doesn't make
+ * much sense to serialize things. API file systems will be moved to the new root, but we
+ * don't have mount units for those. */
+ log_unit_debug(u, "not serializing before switch-root");
+ return 0;
+ }
+
+ /* Start marker */
+ fputs(u->id, f);
+ fputc('\n', f);
+
+ assert(!!UNIT_VTABLE(u)->serialize == !!UNIT_VTABLE(u)->deserialize_item);
+
+ if (UNIT_VTABLE(u)->serialize) {
r = UNIT_VTABLE(u)->serialize(u, f, fds);
if (r < 0)
return r;
(void) serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask);
(void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", u->cgroup_invalidated_mask);
+ (void) bpf_serialize_socket_bind(u, f, fds);
+
+ (void) bpf_program_serialize_attachment(f, fds, "ip-bpf-ingress-installed", u->ip_bpf_ingress_installed);
+ (void) bpf_program_serialize_attachment(f, fds, "ip-bpf-egress-installed", u->ip_bpf_egress_installed);
+ (void) bpf_program_serialize_attachment_set(f, fds, "ip-bpf-custom-ingress-installed", u->ip_bpf_custom_ingress_installed);
+ (void) bpf_program_serialize_attachment_set(f, fds, "ip-bpf-custom-egress-installed", u->ip_bpf_custom_egress_installed);
+
if (uid_is_valid(u->ref_uid))
(void) serialize_item_format(f, "ref-uid", UID_FMT, u->ref_uid);
if (gid_is_valid(u->ref_gid))
(void) serialize_item_format(f, ip_accounting_metric_field[m], "%" PRIu64, v);
}
- if (serialize_jobs) {
+ if (!switching_root) {
if (u->job) {
fputs("job\n", f);
job_serialize(u->job, f);
else if (MATCH_DESERIALIZE_IMMEDIATE("cgroup-invalidated-mask", l, v, cg_mask_from_string, u->cgroup_invalidated_mask))
continue;
- else if (streq(l, "ref-uid")) {
+ else if (STR_IN_SET(l, "ipv4-socket-bind-bpf-link-fd", "ipv6-socket-bind-bpf-link-fd")) {
+ int fd;
+
+ if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
+ log_unit_debug(u, "Failed to parse %s value: %s, ignoring.", l, v);
+ else {
+ if (fdset_remove(fds, fd) < 0) {
+ log_unit_debug(u, "Failed to remove %s value=%d from fdset", l, fd);
+ continue;
+ }
+
+ (void) bpf_socket_bind_add_initial_link_fd(u, fd);
+ }
+ continue;
+
+ } else if (streq(l, "ip-bpf-ingress-installed")) {
+ (void) bpf_program_deserialize_attachment(v, fds, &u->ip_bpf_ingress_installed);
+ continue;
+ } else if (streq(l, "ip-bpf-egress-installed")) {
+ (void) bpf_program_deserialize_attachment(v, fds, &u->ip_bpf_egress_installed);
+ continue;
+
+ } else if (streq(l, "ip-bpf-custom-ingress-installed")) {
+ (void) bpf_program_deserialize_attachment_set(v, fds, &u->ip_bpf_custom_ingress_installed);
+ continue;
+ } else if (streq(l, "ip-bpf-custom-egress-installed")) {
+ (void) bpf_program_deserialize_attachment_set(v, fds, &u->ip_bpf_custom_egress_installed);
+ continue;
+
+ } else if (streq(l, "ref-uid")) {
uid_t uid;
r = parse_uid(v, &uid);
continue;
}
- if (unit_can_serialize(u)) {
- r = exec_runtime_deserialize_compat(u, l, v, fds);
- if (r < 0) {
- log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l);
- continue;
- }
-
+ r = exec_runtime_deserialize_compat(u, l, v, fds);
+ if (r < 0) {
+ log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l);
+ continue;
+ } else if (r > 0)
/* Returns positive if key was handled by the call */
- if (r > 0)
- continue;
+ continue;
+ if (UNIT_VTABLE(u)->deserialize_item) {
r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
if (r < 0)
log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l);
/* Let's make sure that everything that is deserialized also gets any potential new cgroup settings
* applied after we are done. For that we invalidate anything already realized, so that we can
* realize it again. */
- unit_invalidate_cgroup(u, _CGROUP_MASK_ALL);
- unit_invalidate_cgroup_bpf(u);
+ if (u->cgroup_realized) {
+ unit_invalidate_cgroup(u, _CGROUP_MASK_ALL);
+ unit_invalidate_cgroup_bpf(u);
+ }
return 0;
}
"%s\tNeed Daemon Reload: %s\n"
"%s\tTransient: %s\n"
"%s\tPerpetual: %s\n"
- "%s\tGarbage Collection Mode: %s\n"
- "%s\tSlice: %s\n"
- "%s\tCGroup: %s\n"
- "%s\tCGroup realized: %s\n",
+ "%s\tGarbage Collection Mode: %s\n",
prefix, unit_description(u),
prefix, strna(u->instance),
prefix, unit_load_state_to_string(u->load_state),
prefix, yes_no(unit_need_daemon_reload(u)),
prefix, yes_no(u->transient),
prefix, yes_no(u->perpetual),
- prefix, collect_mode_to_string(u->collect_mode),
- prefix, strna(unit_slice_name(u)),
- prefix, strna(u->cgroup_path),
- prefix, yes_no(u->cgroup_realized));
+ prefix, collect_mode_to_string(u->collect_mode));
if (u->markers != 0) {
fprintf(f, "%s\tMarkers:", prefix);
fputs("\n", f);
}
- if (u->cgroup_realized_mask != 0) {
- _cleanup_free_ char *s = NULL;
- (void) cg_mask_to_string(u->cgroup_realized_mask, &s);
- fprintf(f, "%s\tCGroup realized mask: %s\n", prefix, strnull(s));
- }
+ if (UNIT_HAS_CGROUP_CONTEXT(u)) {
+ fprintf(f,
+ "%s\tSlice: %s\n"
+ "%s\tCGroup: %s\n"
+ "%s\tCGroup realized: %s\n",
+ prefix, strna(unit_slice_name(u)),
+ prefix, strna(u->cgroup_path),
+ prefix, yes_no(u->cgroup_realized));
+
+ if (u->cgroup_realized_mask != 0) {
+ _cleanup_free_ char *s = NULL;
+ (void) cg_mask_to_string(u->cgroup_realized_mask, &s);
+ fprintf(f, "%s\tCGroup realized mask: %s\n", prefix, strnull(s));
+ }
- if (u->cgroup_enabled_mask != 0) {
- _cleanup_free_ char *s = NULL;
- (void) cg_mask_to_string(u->cgroup_enabled_mask, &s);
- fprintf(f, "%s\tCGroup enabled mask: %s\n", prefix, strnull(s));
- }
+ if (u->cgroup_enabled_mask != 0) {
+ _cleanup_free_ char *s = NULL;
+ (void) cg_mask_to_string(u->cgroup_enabled_mask, &s);
+ fprintf(f, "%s\tCGroup enabled mask: %s\n", prefix, strnull(s));
+ }
- m = unit_get_own_mask(u);
- if (m != 0) {
- _cleanup_free_ char *s = NULL;
- (void) cg_mask_to_string(m, &s);
- fprintf(f, "%s\tCGroup own mask: %s\n", prefix, strnull(s));
- }
+ m = unit_get_own_mask(u);
+ if (m != 0) {
+ _cleanup_free_ char *s = NULL;
+ (void) cg_mask_to_string(m, &s);
+ fprintf(f, "%s\tCGroup own mask: %s\n", prefix, strnull(s));
+ }
- m = unit_get_members_mask(u);
- if (m != 0) {
- _cleanup_free_ char *s = NULL;
- (void) cg_mask_to_string(m, &s);
- fprintf(f, "%s\tCGroup members mask: %s\n", prefix, strnull(s));
- }
+ m = unit_get_members_mask(u);
+ if (m != 0) {
+ _cleanup_free_ char *s = NULL;
+ (void) cg_mask_to_string(m, &s);
+ fprintf(f, "%s\tCGroup members mask: %s\n", prefix, strnull(s));
+ }
- m = unit_get_delegate_mask(u);
- if (m != 0) {
- _cleanup_free_ char *s = NULL;
- (void) cg_mask_to_string(m, &s);
- fprintf(f, "%s\tCGroup delegate mask: %s\n", prefix, strnull(s));
+ m = unit_get_delegate_mask(u);
+ if (m != 0) {
+ _cleanup_free_ char *s = NULL;
+ (void) cg_mask_to_string(m, &s);
+ fprintf(f, "%s\tCGroup delegate mask: %s\n", prefix, strnull(s));
+ }
}
if (!sd_id128_is_null(u->invocation_id))
UnitDependencyInfo di;
Unit *other;
- HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d]) {
+ HASHMAP_FOREACH_KEY(di.data, other, unit_get_dependencies(u, d)) {
bool space = false;
fprintf(f, "%s\t%s: %s (", prefix, unit_dependency_to_string(d), other->id);
"%s\tRefuseManualStart: %s\n"
"%s\tRefuseManualStop: %s\n"
"%s\tDefaultDependencies: %s\n"
+ "%s\tOnSuccessJobMode: %s\n"
"%s\tOnFailureJobMode: %s\n"
"%s\tIgnoreOnIsolate: %s\n",
prefix, yes_no(u->stop_when_unneeded),
prefix, yes_no(u->refuse_manual_start),
prefix, yes_no(u->refuse_manual_stop),
prefix, yes_no(u->default_dependencies),
+ prefix, job_mode_to_string(u->on_success_job_mode),
prefix, job_mode_to_string(u->on_failure_job_mode),
prefix, yes_no(u->ignore_on_isolate));