From 66f35161f6568386526bdfeab18e6b74b8b13608 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 27 Mar 2024 00:30:45 +0000 Subject: [PATCH] core: add counter for soft-reboot iterations Allow to query via D-Bus how many times the current booted system has been soft rebooted --- man/org.freedesktop.systemd1.xml | 12 ++++++++++-- src/core/dbus-manager.c | 1 + src/core/main.c | 5 +++++ src/core/manager-serialize.c | 11 ++++++++++- src/core/manager.h | 2 ++ test/units/testsuite-82.sh | 8 ++++++++ 6 files changed, 36 insertions(+), 3 deletions(-) diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 1f30f65bf7c..b148a0ee397 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -560,6 +560,8 @@ node /org/freedesktop/systemd1 { readonly i DefaultOOMScoreAdjust = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly s CtrlAltDelBurstAction = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly u SoftRebootsCount = ...; }; interface org.freedesktop.DBus.Peer { ... }; interface org.freedesktop.DBus.Introspectable { ... }; @@ -1251,6 +1253,8 @@ node /org/freedesktop/systemd1 { + + @@ -1787,6 +1791,9 @@ node /org/freedesktop/systemd1 { UnitPath encodes the currently active unit file search path. It is an array of file system paths encoded as strings. + SoftRebootsCount encodes how many soft-reboots were successfully completed + since the last full boot. + Virtualization contains a short ID string describing the virtualization technology the system runs in. On bare-metal hardware this is the empty string. Otherwise, it contains an identifier such as kvm, vmware and so on. For a full list of @@ -11993,8 +12000,9 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ SoftReboot(), and DumpUnitFileDescriptorStore() were added in version 254. StartAuxiliaryScope(), - SoftRebootStartTimestamp and - SoftRebootStartTimestampMonotonic were added in version 256. + SoftRebootStartTimestamp, + SoftRebootStartTimestampMonotonic and + SoftRebootsCount were added in version 256. Unit Objects diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index e7ad850d35a..bba466b9008 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -3140,6 +3140,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_PROPERTY("DefaultOOMPolicy", "s", bus_property_get_oom_policy, offsetof(Manager, defaults.oom_policy), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultOOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CtrlAltDelBurstAction", "s", bus_property_get_emergency_action, offsetof(Manager, cad_burst_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SoftRebootsCount", "u", bus_property_get_unsigned, offsetof(Manager, soft_reboots_count), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_METHOD_WITH_ARGS("GetUnit", SD_BUS_ARGS("s", name), diff --git a/src/core/main.c b/src/core/main.c index b086122a8c8..1aeab10ddbc 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -3192,6 +3192,11 @@ int main(int argc, char *argv[]) { goto finish; } + /* If we got a SoftRebootStart timestamp during deserialization, then we are in a new soft-reboot + * iteration, so bump the counter now before starting units, so that they can reliably read it. */ + if (dual_timestamp_is_set(&m->timestamps[MANAGER_TIMESTAMP_SOFTREBOOT_START])) + m->soft_reboots_count++; + /* This will close all file descriptors that were opened, but not claimed by any unit. */ fds = fdset_free(fds); arg_serialization = safe_fclose(arg_serialization); diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c index 3af6723e5f6..284f4987a28 100644 --- a/src/core/manager-serialize.c +++ b/src/core/manager-serialize.c @@ -109,6 +109,8 @@ int manager_serialize( (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_format(f, "soft-reboots-count", "%u", m->soft_reboots_count); + for (ManagerTimestamp q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { _cleanup_free_ char *joined = NULL; @@ -517,7 +519,14 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { (void) varlink_server_deserialize_one(m->varlink_server, val, fds); } else if ((val = startswith(l, "dump-ratelimit="))) deserialize_ratelimit(&m->dump_ratelimit, "dump-ratelimit", val); - else { + 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 { ManagerTimestamp q; for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { diff --git a/src/core/manager.h b/src/core/manager.h index c1782ea5f74..0e2531a4a7d 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -504,6 +504,8 @@ struct Manager { /* Pin the systemd-executor binary, so that it never changes until re-exec, ensuring we don't have * serialization/deserialization compatibility issues during upgrades. */ int executor_fd; + + unsigned soft_reboots_count; }; static inline usec_t manager_default_timeout_abort_usec(Manager *m) { diff --git a/test/units/testsuite-82.sh b/test/units/testsuite-82.sh index 224cd75c7fe..8ff69c90e4d 100755 --- a/test/units/testsuite-82.sh +++ b/test/units/testsuite-82.sh @@ -27,6 +27,8 @@ if [ -f /run/testsuite82.touch3 ]; then echo "This is the fourth boot!" systemd-notify --status="Fourth Boot" + test "$(busctl -j get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager SoftRebootsCount | jq -r '.data')" -eq 3 + rm /run/testsuite82.touch3 mount rmdir /original-root /run/nextroot @@ -52,6 +54,8 @@ elif [ -f /run/testsuite82.touch2 ]; then echo "This is the third boot!" systemd-notify --status="Third Boot" + test "$(busctl -j get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager SoftRebootsCount | jq -r '.data')" -eq 2 + rm /run/testsuite82.touch2 # Check that the fdstore entry still exists @@ -95,6 +99,8 @@ elif [ -f /run/testsuite82.touch ]; then echo "This is the second boot!" systemd-notify --status="Second Boot" + test "$(busctl -j get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager SoftRebootsCount | jq -r '.data')" -eq 1 + # Clean up what we created earlier rm /run/testsuite82.touch @@ -151,6 +157,8 @@ else # This is the first boot systemd-notify --status="First Boot" + test "$(busctl -j get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager SoftRebootsCount | jq -r '.data')" -eq 0 + # Let's upload an fd to the fdstore, so that we can verify fdstore passing works correctly T="/dev/shm/fdstore.$RANDOM" echo "wuffwuff" >"$T"