From: Ivan Kruglov Date: Thu, 7 May 2026 12:05:24 +0000 (-0700) Subject: core: implement SwapContext/Runtime for io.systemd.Unit.List + tests X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ed4740a0dc63d1f85e48d6959b8e077f63d1eef6;p=thirdparty%2Fsystemd.git core: implement SwapContext/Runtime for io.systemd.Unit.List + tests Add varlink context and runtime builders for .swap units: SwapContext: What, Priority, Options, TimeoutUSec, ExecActivate, ExecDeactivate SwapRuntime: ControlPID, Result, CleanResult, UID, GID (SwapResult enum) SwapResult is exposed as a proper varlink enum type. Runtime follows the same pattern as MountRuntime (ControlPID, Result, CleanResult, ref UID/GID). The integration test is conditional since swap units may not be present on all systems. Co-developed-by: Claude Opus 4.6 --- diff --git a/src/core/meson.build b/src/core/meson.build index 796669814bf..e59a683c9a5 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -75,6 +75,7 @@ libcore_sources = files( 'varlink-mount.c', 'varlink-path.c', 'varlink-scope.c', + 'varlink-swap.c', 'varlink-unit.c', ) diff --git a/src/core/varlink-swap.c b/src/core/varlink-swap.c new file mode 100644 index 00000000000..055e73a9cda --- /dev/null +++ b/src/core/varlink-swap.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "sd-json.h" + +#include "json-util.h" +#include "swap.h" +#include "user-util.h" +#include "varlink-common.h" +#include "varlink-swap.h" + +int swap_context_build_json(sd_json_variant **ret, const char *name, void *userdata) { + Swap *s = ASSERT_PTR(SWAP(userdata)); + + return sd_json_buildo( + ASSERT_PTR(ret), + SD_JSON_BUILD_PAIR_STRING("What", s->what), + JSON_BUILD_PAIR_INTEGER_NON_NEGATIVE("Priority", swap_get_priority(s)), + JSON_BUILD_PAIR_STRING_NON_EMPTY("Options", swap_get_options(s)), + JSON_BUILD_PAIR_FINITE_USEC("TimeoutUSec", s->timeout_usec), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("ExecActivate", exec_command_build_json, &s->exec_command[SWAP_EXEC_ACTIVATE]), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("ExecDeactivate", exec_command_build_json, &s->exec_command[SWAP_EXEC_DEACTIVATE])); +} + +int swap_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata) { + Unit *u = ASSERT_PTR(userdata); + Swap *s = ASSERT_PTR(SWAP(u)); + + return sd_json_buildo( + ASSERT_PTR(ret), + SD_JSON_BUILD_PAIR_CONDITION(pidref_is_set(&s->control_pid), "ControlPID", JSON_BUILD_PIDREF(&s->control_pid)), + JSON_BUILD_PAIR_ENUM("Result", swap_result_to_string(s->result)), + JSON_BUILD_PAIR_ENUM("CleanResult", swap_result_to_string(s->clean_result)), + SD_JSON_BUILD_PAIR_CONDITION(uid_is_valid(u->ref_uid), "UID", SD_JSON_BUILD_UNSIGNED(u->ref_uid)), + SD_JSON_BUILD_PAIR_CONDITION(gid_is_valid(u->ref_gid), "GID", SD_JSON_BUILD_UNSIGNED(u->ref_gid))); +} diff --git a/src/core/varlink-swap.h b/src/core/varlink-swap.h new file mode 100644 index 00000000000..f76aa63fb15 --- /dev/null +++ b/src/core/varlink-swap.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "core-forward.h" + +int swap_context_build_json(sd_json_variant **ret, const char *name, void *userdata); +int swap_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata); diff --git a/src/core/varlink-unit.c b/src/core/varlink-unit.c index 30b912ddf10..fa017e95515 100644 --- a/src/core/varlink-unit.c +++ b/src/core/varlink-unit.c @@ -31,6 +31,7 @@ #include "varlink-mount.h" #include "varlink-path.h" #include "varlink-scope.h" +#include "varlink-swap.h" #include "varlink-unit.h" #include "varlink-util.h" @@ -167,6 +168,7 @@ static int unit_context_build_json(sd_json_variant **ret, const char *name, void [UNIT_PATH] = path_context_build_json, [UNIT_SCOPE] = scope_context_build_json, [UNIT_SERVICE] = service_context_build_json, + [UNIT_SWAP] = swap_context_build_json, }; return sd_json_buildo( @@ -334,6 +336,7 @@ static int unit_runtime_build_json(sd_json_variant **ret, const char *name, void [UNIT_MOUNT] = mount_runtime_build_json, [UNIT_PATH] = path_runtime_build_json, [UNIT_SCOPE] = scope_runtime_build_json, + [UNIT_SWAP] = swap_runtime_build_json, }; return sd_json_buildo( diff --git a/src/shared/varlink-io.systemd.Unit.c b/src/shared/varlink-io.systemd.Unit.c index 83a728e2cc6..4d77e64a740 100644 --- a/src/shared/varlink-io.systemd.Unit.c +++ b/src/shared/varlink-io.systemd.Unit.c @@ -1041,6 +1041,46 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_FIELD_COMMENT("Result of scope operation"), SD_VARLINK_DEFINE_FIELD_BY_TYPE(Result, ScopeResult, 0)); +/* SwapContext + * https://www.freedesktop.org/software/systemd/man/latest/systemd.swap.html */ +static SD_VARLINK_DEFINE_STRUCT_TYPE( + SwapContext, + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.swap.html#What="), + SD_VARLINK_DEFINE_FIELD(What, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.swap.html#Priority="), + SD_VARLINK_DEFINE_FIELD(Priority, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.swap.html#Options="), + SD_VARLINK_DEFINE_FIELD(Options, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.swap.html#TimeoutSec="), + SD_VARLINK_DEFINE_FIELD(TimeoutUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Activate command"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(ExecActivate, ExecCommand, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Deactivate command"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(ExecDeactivate, ExecCommand, SD_VARLINK_NULLABLE)); + +SD_VARLINK_DEFINE_ENUM_TYPE( + SwapResult, + SD_VARLINK_DEFINE_ENUM_VALUE(success), + SD_VARLINK_DEFINE_ENUM_VALUE(resources), + SD_VARLINK_DEFINE_ENUM_VALUE(timeout), + SD_VARLINK_DEFINE_ENUM_VALUE(exit_code), + SD_VARLINK_DEFINE_ENUM_VALUE(signal), + SD_VARLINK_DEFINE_ENUM_VALUE(core_dump), + SD_VARLINK_DEFINE_ENUM_VALUE(start_limit_hit)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + SwapRuntime, + SD_VARLINK_FIELD_COMMENT("PID of the current swap control process"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(ControlPID, ProcessId, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Result of swap operation"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(Result, SwapResult, 0), + SD_VARLINK_FIELD_COMMENT("Result of cleaning operation"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(CleanResult, SwapResult, 0), + SD_VARLINK_FIELD_COMMENT("Reference UID"), + SD_VARLINK_DEFINE_FIELD(UID, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Reference GID"), + SD_VARLINK_DEFINE_FIELD(GID, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); + /* Service-specific types */ /* Keep in sync with service_type_table[] in src/core/service.c */ @@ -1237,7 +1277,9 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_FIELD_COMMENT("The path context of the unit"), SD_VARLINK_DEFINE_FIELD_BY_TYPE(Path, PathContext, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("The scope context of the unit"), - SD_VARLINK_DEFINE_FIELD_BY_TYPE(Scope, ScopeContext, SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_FIELD_BY_TYPE(Scope, ScopeContext, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("The swap context of the unit"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(Swap, SwapContext, SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( ActivationDetails, @@ -1415,7 +1457,9 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_FIELD_COMMENT("The path runtime of the unit"), SD_VARLINK_DEFINE_FIELD_BY_TYPE(Path, PathRuntime, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("The scope runtime of the unit"), - SD_VARLINK_DEFINE_FIELD_BY_TYPE(Scope, ScopeRuntime, SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_FIELD_BY_TYPE(Scope, ScopeRuntime, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("The swap runtime of the unit"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(Swap, SwapRuntime, SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_METHOD_FULL( List, @@ -1586,6 +1630,9 @@ SD_VARLINK_DEFINE_INTERFACE( &vl_type_ScopeContext, &vl_type_ScopeResult, &vl_type_ScopeRuntime, + &vl_type_SwapContext, + &vl_type_SwapResult, + &vl_type_SwapRuntime, /* UnitContext enums */ &vl_type_CollectMode, diff --git a/src/shared/varlink-io.systemd.Unit.h b/src/shared/varlink-io.systemd.Unit.h index 54d2dad1c13..230fc5c43ee 100644 --- a/src/shared/varlink-io.systemd.Unit.h +++ b/src/shared/varlink-io.systemd.Unit.h @@ -33,6 +33,7 @@ extern const sd_varlink_symbol vl_type_MountResult; extern const sd_varlink_symbol vl_type_PathType; extern const sd_varlink_symbol vl_type_PathResult; extern const sd_varlink_symbol vl_type_ScopeResult; +extern const sd_varlink_symbol vl_type_SwapResult; extern const sd_varlink_symbol vl_type_CollectMode; extern const sd_varlink_symbol vl_type_JobMode; extern const sd_varlink_symbol vl_type_ServiceType; diff --git a/src/test/test-varlink-idl-unit.c b/src/test/test-varlink-idl-unit.c index 5e9ce4ce061..eba3a7d96a5 100644 --- a/src/test/test-varlink-idl-unit.c +++ b/src/test/test-varlink-idl-unit.c @@ -75,6 +75,9 @@ TEST(unit_enums_idl) { /* ScopeRuntime enums */ TEST_IDL_ENUM(ScopeResult, scope_result, vl_type_ScopeResult); + /* SwapRuntime enums */ + TEST_IDL_ENUM(SwapResult, swap_result, vl_type_SwapResult); + /* UnitContext enums */ TEST_IDL_ENUM(CollectMode, collect_mode, vl_type_CollectMode); TEST_IDL_ENUM(EmergencyAction, emergency_action, vl_type_EmergencyAction); diff --git a/test/units/TEST-74-AUX-UTILS.varlinkctl.sh b/test/units/TEST-74-AUX-UTILS.varlinkctl.sh index 900eda1138c..4d9649f2d70 100755 --- a/test/units/TEST-74-AUX-UTILS.varlinkctl.sh +++ b/test/units/TEST-74-AUX-UTILS.varlinkctl.sh @@ -258,6 +258,13 @@ test -n "$scope_id" scope_params=$(jq -cn --arg name "$scope_id" '{name: $name}') varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "$scope_params" | jq -e '.context.Scope' varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "$scope_params" | jq -e '.runtime.Scope' +# test for SwapContext/Runtime (swap units may not be present on all systems) +swap_id=$(varlinkctl call --collect /run/systemd/io.systemd.Manager io.systemd.Unit.List '{}' | jq -r '.[] | select(.context.Type == "swap" and .runtime.LoadState == "loaded") .context.ID // empty' | tail -n 1) +if test -n "$swap_id"; then + swap_params=$(jq -cn --arg name "$swap_id" '{name: $name}') + varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "$swap_params" | jq -e '.context.Swap' + varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "$swap_params" | jq -e '.runtime.Swap' +fi # test io.systemd.Metrics varlinkctl info /run/systemd/report/io.systemd.Manager