core: add helper macros for deserialization

A helper function would seem more natural, but there are two reasons why a
macro is needed:
- many bool fields are bitfields, so we can't take a pointer, and using a macro
  allows us to avoid taking a pointer.
- we have a few diffent types (bool, uint64_t, FreezerState), and we can have
  type safety without specifying the type by using the macro.

This also makes the error messages more informative: they print the exact field
identifier that failed, which is more useful for debugging than a description.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2021-02-12 11:59:41 +01:00
parent 2d3b784dfb
commit 9466ec13a5
2 changed files with 51 additions and 138 deletions
+51 -137
View File
@@ -172,6 +172,32 @@ static int unit_deserialize_job(Unit *u, FILE *f) {
return 0;
}
#define MATCH_DESERIALIZE(key, l, v, parse_func, target) \
({ \
bool _deserialize_matched = streq(l, key); \
if (_deserialize_matched) { \
int _deserialize_r = parse_func(v); \
if (_deserialize_r < 0) \
log_unit_debug_errno(u, _deserialize_r, \
"Failed to parse \"%s=%s\", ignoring.", l, v); \
else \
target = _deserialize_r; \
}; \
_deserialize_matched; \
})
#define MATCH_DESERIALIZE_IMMEDIATE(key, l, v, parse_func, target) \
({ \
bool _deserialize_matched = streq(l, key); \
if (_deserialize_matched) { \
int _deserialize_r = parse_func(v, &target); \
if (_deserialize_r < 0) \
log_unit_debug_errno(u, _deserialize_r, \
"Failed to parse \"%s=%s\", ignoring", l, v); \
}; \
_deserialize_matched; \
})
int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
int r;
@@ -233,130 +259,48 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
} else if (streq(l, "assert-timestamp")) {
(void) deserialize_dual_timestamp(v, &u->assert_timestamp);
continue;
} else if (streq(l, "condition-result")) {
r = parse_boolean(v);
if (r < 0)
log_unit_debug(u, "Failed to parse condition result value %s, ignoring.", v);
else
u->condition_result = r;
} else if (MATCH_DESERIALIZE("condition-result", l, v, parse_boolean, u->condition_result))
continue;
} else if (streq(l, "assert-result")) {
r = parse_boolean(v);
if (r < 0)
log_unit_debug(u, "Failed to parse assert result value %s, ignoring.", v);
else
u->assert_result = r;
else if (MATCH_DESERIALIZE("assert-result", l, v, parse_boolean, u->assert_result))
continue;
} else if (streq(l, "transient")) {
r = parse_boolean(v);
if (r < 0)
log_unit_debug(u, "Failed to parse transient bool %s, ignoring.", v);
else
u->transient = r;
else if (MATCH_DESERIALIZE("transient", l, v, parse_boolean, u->transient))
continue;
} else if (streq(l, "in-audit")) {
r = parse_boolean(v);
if (r < 0)
log_unit_debug(u, "Failed to parse in-audit bool %s, ignoring.", v);
else
u->in_audit = r;
else if (MATCH_DESERIALIZE("in-audit", l, v, parse_boolean, u->in_audit))
continue;
} else if (streq(l, "exported-invocation-id")) {
r = parse_boolean(v);
if (r < 0)
log_unit_debug(u, "Failed to parse exported invocation ID bool %s, ignoring.", v);
else
u->exported_invocation_id = r;
else if (MATCH_DESERIALIZE("exported-invocation-id", l, v, parse_boolean, u->exported_invocation_id))
continue;
} else if (streq(l, "exported-log-level-max")) {
r = parse_boolean(v);
if (r < 0)
log_unit_debug(u, "Failed to parse exported log level max bool %s, ignoring.", v);
else
u->exported_log_level_max = r;
else if (MATCH_DESERIALIZE("exported-log-level-max", l, v, parse_boolean, u->exported_log_level_max))
continue;
} else if (streq(l, "exported-log-extra-fields")) {
r = parse_boolean(v);
if (r < 0)
log_unit_debug(u, "Failed to parse exported log extra fields bool %s, ignoring.", v);
else
u->exported_log_extra_fields = r;
else if (MATCH_DESERIALIZE("exported-log-extra-fields", l, v, parse_boolean, u->exported_log_extra_fields))
continue;
} else if (streq(l, "exported-log-rate-limit-interval")) {
r = parse_boolean(v);
if (r < 0)
log_unit_debug(u, "Failed to parse exported log rate limit interval %s, ignoring.", v);
else
u->exported_log_ratelimit_interval = r;
else if (MATCH_DESERIALIZE("exported-log-rate-limit-interval", l, v, parse_boolean, u->exported_log_ratelimit_interval))
continue;
} else if (streq(l, "exported-log-rate-limit-burst")) {
r = parse_boolean(v);
if (r < 0)
log_unit_debug(u, "Failed to parse exported log rate limit burst %s, ignoring.", v);
else
u->exported_log_ratelimit_burst = r;
else if (MATCH_DESERIALIZE("exported-log-rate-limit-burst", l, v, parse_boolean, u->exported_log_ratelimit_burst))
continue;
} else if (STR_IN_SET(l, "cpu-usage-base", "cpuacct-usage-base")) {
r = safe_atou64(v, &u->cpu_usage_base);
if (r < 0)
log_unit_debug(u, "Failed to parse CPU usage base %s, ignoring.", v);
else if (MATCH_DESERIALIZE_IMMEDIATE("cpu-usage-base", l, v, safe_atou64, u->cpu_usage_base) ||
MATCH_DESERIALIZE_IMMEDIATE("cpuacct-usage-base", l, v, safe_atou64, u->cpu_usage_base))
continue;
} else if (streq(l, "cpu-usage-last")) {
r = safe_atou64(v, &u->cpu_usage_last);
if (r < 0)
log_unit_debug(u, "Failed to read CPU usage last %s, ignoring.", v);
else if (MATCH_DESERIALIZE_IMMEDIATE("cpu-usage-last", l, v, safe_atou64, u->cpu_usage_last))
continue;
} else if (streq(l, "managed-oom-kill-last")) {
r = safe_atou64(v, &u->managed_oom_kill_last);
if (r < 0)
log_unit_debug(u, "Failed to read managed OOM kill last %s, ignoring.", v);
else if (MATCH_DESERIALIZE_IMMEDIATE("managed-oom-kill-last", l, v, safe_atou64, u->managed_oom_kill_last))
continue;
} else if (streq(l, "oom-kill-last")) {
r = safe_atou64(v, &u->oom_kill_last);
if (r < 0)
log_unit_debug(u, "Failed to read OOM kill last %s, ignoring.", v);
else if (MATCH_DESERIALIZE_IMMEDIATE("oom-kill-last", l, v, safe_atou64, u->oom_kill_last))
continue;
} else if (streq(l, "cgroup")) {
else if (streq(l, "cgroup")) {
r = unit_set_cgroup_path(u, v);
if (r < 0)
log_unit_debug_errno(u, r, "Failed to set cgroup path %s, ignoring: %m", v);
@@ -365,47 +309,27 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
(void) unit_watch_cgroup_memory(u);
continue;
} else if (streq(l, "cgroup-realized")) {
int b;
b = parse_boolean(v);
if (b < 0)
log_unit_debug(u, "Failed to parse cgroup-realized bool %s, ignoring.", v);
else
u->cgroup_realized = b;
} else if (MATCH_DESERIALIZE("cgroup-realized", l, v, parse_boolean, u->cgroup_realized))
continue;
} else if (streq(l, "cgroup-realized-mask")) {
r = cg_mask_from_string(v, &u->cgroup_realized_mask);
if (r < 0)
log_unit_debug(u, "Failed to parse cgroup-realized-mask %s, ignoring.", v);
else if (MATCH_DESERIALIZE_IMMEDIATE("cgroup-realized-mask", l, v, cg_mask_from_string, u->cgroup_realized_mask))
continue;
} else if (streq(l, "cgroup-enabled-mask")) {
r = cg_mask_from_string(v, &u->cgroup_enabled_mask);
if (r < 0)
log_unit_debug(u, "Failed to parse cgroup-enabled-mask %s, ignoring.", v);
else if (MATCH_DESERIALIZE_IMMEDIATE("cgroup-enabled-mask", l, v, cg_mask_from_string, u->cgroup_enabled_mask))
continue;
} else if (streq(l, "cgroup-invalidated-mask")) {
r = cg_mask_from_string(v, &u->cgroup_invalidated_mask);
if (r < 0)
log_unit_debug(u, "Failed to parse cgroup-invalidated-mask %s, ignoring.", v);
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 (streq(l, "ref-uid")) {
uid_t uid;
r = parse_uid(v, &uid);
if (r < 0)
log_unit_debug(u, "Failed to parse referenced UID %s, ignoring.", v);
log_unit_debug(u, "Failed to parse \"%s=%s\", ignoring.", l, v);
else
unit_ref_uid_gid(u, uid, GID_INVALID);
continue;
} else if (streq(l, "ref-gid")) {
@@ -413,25 +337,23 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
r = parse_gid(v, &gid);
if (r < 0)
log_unit_debug(u, "Failed to parse referenced GID %s, ignoring.", v);
log_unit_debug(u, "Failed to parse \"%s=%s\", ignoring.", l, v);
else
unit_ref_uid_gid(u, UID_INVALID, gid);
continue;
} else if (streq(l, "ref")) {
r = strv_extend(&u->deserialized_refs, v);
if (r < 0)
return log_oom();
continue;
} else if (streq(l, "invocation-id")) {
sd_id128_t id;
r = sd_id128_from_string(v, &id);
if (r < 0)
log_unit_debug(u, "Failed to parse invocation id %s, ignoring.", v);
log_unit_debug(u, "Failed to parse \"%s=%s\", ignoring.", l, v);
else {
r = unit_set_invocation_id(u, id);
if (r < 0)
@@ -439,17 +361,9 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
}
continue;
} else if (streq(l, "freezer-state")) {
FreezerState s;
s = freezer_state_from_string(v);
if (s < 0)
log_unit_debug(u, "Failed to deserialize freezer-state '%s', ignoring.", v);
else
u->freezer_state = s;
} else if (MATCH_DESERIALIZE("freezer-state", l, v, freezer_state_from_string, u->freezer_state))
continue;
}
/* Check if this is an IP accounting metric serialization field */
m = string_table_lookup(ip_accounting_metric_field, ELEMENTSOF(ip_accounting_metric_field), l);
-1
View File
@@ -3261,7 +3261,6 @@ bool unit_can_serialize(Unit *u) {
return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item;
}
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, UnitDependencyMask mask) {
_cleanup_free_ char *e = NULL;
Unit *device;