[systemd-devel] [PATCH 3/4] WIP: manager: add a global watchdog reboot timestamp

Michael Olbrich m.olbrich at pengutronix.de
Mon Oct 24 09:04:04 PDT 2011


This patch adds WatchdogRebootTimestamp[Monotonic] to the systemd
manager API. It contains the earliest point in time when systemd might
reboot the system because the timer for WatchdogRebootUSec for a
service expired.
If we assume the system takes Xus to shut down then
WatchdogRebootTimestamp + Xus should never be in the past. A watchdog
daemon handling the hardware watchdog can use this information to
determine when to let the hardware watchdog restart the system.
This is convenience information for a watchdog daemon. With this the
it can avoid a lot of D-Bus calls that are necessary to calculate the
same value.
---
 src/dbus-manager.c |    4 ++++
 src/manager.c      |   20 ++++++++++++++++++++
 src/manager.h      |    3 +++
 src/service.c      |    2 ++
 4 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/src/dbus-manager.c b/src/dbus-manager.c
index 7b68156..2254ec8 100644
--- a/src/dbus-manager.c
+++ b/src/dbus-manager.c
@@ -223,6 +223,8 @@
         "  <property name=\"StartupTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"WatchdogRebootTimestamp\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"WatchdogRebootTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n"  \
         "  <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
         "  <property name=\"NNames\" type=\"u\" access=\"read\"/>\n"    \
@@ -506,6 +508,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
                 { "org.freedesktop.systemd1.Manager", "StartupTimestampMonotonic", bus_property_append_uint64, "t", &m->startup_timestamp.monotonic },
                 { "org.freedesktop.systemd1.Manager", "FinishTimestamp", bus_property_append_uint64,  "t",  &m->finish_timestamp.realtime },
                 { "org.freedesktop.systemd1.Manager", "FinishTimestampMonotonic", bus_property_append_uint64, "t",&m->finish_timestamp.monotonic },
+                { "org.freedesktop.systemd1.Manager", "WatchdogRebootTimestamp", bus_property_append_uint64,  "t",  &m->watchdog_timestamp.realtime },
+                { "org.freedesktop.systemd1.Manager", "WatchdogRebootTimestampMonotonic", bus_property_append_uint64, "t",&m->watchdog_timestamp.monotonic },
                 { "org.freedesktop.systemd1.Manager", "LogLevel",      bus_manager_append_log_level,  "s",  m, bus_manager_set_log_level },
                 { "org.freedesktop.systemd1.Manager", "LogTarget",     bus_manager_append_log_target, "s",  m, bus_manager_set_log_target },
                 { "org.freedesktop.systemd1.Manager", "NNames",        bus_manager_append_n_names,    "u",  m                  },
diff --git a/src/manager.c b/src/manager.c
index 111167a..b20db14 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -3174,6 +3174,26 @@ bool manager_get_show_status(Manager *m) {
         return plymouth_running();
 }
 
+void manager_update_watchdog(Manager *m) {
+        Iterator i;
+        Unit *u;
+        Service *s;
+        const char *k;
+        dual_timestamp timestamp = {0, 0};
+
+        HASHMAP_FOREACH_KEY(u, k, m->units, i) {
+                if (!(s = SERVICE(u)))
+                        continue;
+                if (!dual_timestamp_is_set(&s->watchdog_timestamp))
+                        continue;
+                if (!dual_timestamp_is_set(&timestamp) || ((s->watchdog_timestamp.monotonic + s->watchdog_reboot_usec) < timestamp.monotonic)) {
+                        timestamp.monotonic = s->watchdog_timestamp.monotonic + s->watchdog_reboot_usec;
+                        timestamp.realtime = s->watchdog_timestamp.realtime + s->watchdog_reboot_usec;
+                }
+        }
+        m->watchdog_timestamp = timestamp;
+}
+
 static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = {
         [MANAGER_SYSTEM] = "system",
         [MANAGER_USER] = "user"
diff --git a/src/manager.h b/src/manager.h
index 5deb569..872d2ea 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -147,6 +147,7 @@ struct Manager {
         dual_timestamp initrd_timestamp;
         dual_timestamp startup_timestamp;
         dual_timestamp finish_timestamp;
+        dual_timestamp watchdog_timestamp;
 
         char *generator_unit_path;
 
@@ -293,6 +294,8 @@ void manager_recheck_syslog(Manager *m);
 void manager_set_show_status(Manager *m, bool b);
 bool manager_get_show_status(Manager *m);
 
+void manager_update_watchdog(Manager *m);
+
 const char *manager_running_as_to_string(ManagerRunningAs i);
 ManagerRunningAs manager_running_as_from_string(const char *s);
 
diff --git a/src/service.c b/src/service.c
index b0c775c..0e51071 100644
--- a/src/service.c
+++ b/src/service.c
@@ -206,6 +206,7 @@ static void service_stop_watchdog(Service *s) {
         unit_unwatch_timer(UNIT(s), &s->watchdog_reboot_watch);
         s->watchdog_timestamp.realtime = 0;
         s->watchdog_timestamp.monotonic = 0;
+        manager_update_watchdog(s->meta.manager);
 }
 
 static void service_reset_watchdog(Service *s) {
@@ -221,6 +222,7 @@ static void service_reset_watchdog(Service *s) {
                 if ((r = unit_watch_timer(UNIT(s), s->watchdog_reboot_usec, &s->watchdog_reboot_watch)) < 0)
                         log_warning("%s failed to install watchdog reboot timer: %s", s->meta.id, strerror(-r));
         }
+        manager_update_watchdog(s->meta.manager);
 }
 
 static void service_done(Unit *u) {
-- 
1.7.7



More information about the systemd-devel mailing list