[systemd-devel] [PATCH] service: add support for reboot argument when triggered by StartLimitAction=
Michael Olbrich
m.olbrich at pengutronix.de
Fri Mar 21 07:34:27 PDT 2014
When rebooting with systemctl, an optional argument can be passed to the
reboot system call. This makes it possible the specify the argument in a
service file and use it when the service triggers a restart.
This is useful to distinguish between manual reboots and reboots caused by
failing services.
---
man/systemd.service.xml | 13 +++++++++++++
src/core/dbus-service.c | 1 +
src/core/load-fragment-gperf.gperf.m4 | 1 +
src/core/service.c | 23 ++++++++++++++++++++++-
src/core/service.h | 1 +
5 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 5b3afb8..a2a1b6b 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -1017,6 +1017,19 @@ ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting>
<option>none</option>.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>RebootArgument=</varname></term>
+ <listitem><para>Configure the optional
+ argument for the
+ <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ system call if
+ <varname>StartLimitAction=</varname>
+ is a reboot action. This works just
+ like the optional argument to
+ <command>systemctl reboot</command>
+ command.</para></listitem>
+ </varlistentry>
+
</variablelist>
<para>Check
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index 0451790..45bfecf 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -50,6 +50,7 @@ const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitAction", "s", property_get_start_limit_action, offsetof(Service, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Service, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST),
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 55fd3da..defd66e 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -183,6 +183,7 @@ Service.WatchdogSec, config_parse_sec, 0,
Service.StartLimitInterval, config_parse_sec, 0, offsetof(Service, start_limit.interval)
Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Service, start_limit.burst)
Service.StartLimitAction, config_parse_start_limit_action, 0, offsetof(Service, start_limit_action)
+Service.RebootArgument, config_parse_string, 0, offsetof(Service, reboot_arg)
Service.Type, config_parse_service_type, 0, offsetof(Service, type)
Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only)
diff --git a/src/core/service.c b/src/core/service.c
index 78a2e06..9026dc5 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -24,6 +24,8 @@
#include <dirent.h>
#include <unistd.h>
#include <sys/reboot.h>
+#include <linux/reboot.h>
+#include <sys/syscall.h>
#include "manager.h"
#include "unit.h"
@@ -2369,6 +2371,18 @@ static int service_start_limit_test(Service *s) {
if (ratelimit_test(&s->start_limit))
return 0;
+ if ((s->start_limit_action == SERVICE_START_LIMIT_REBOOT ||
+ s->start_limit_action == SERVICE_START_LIMIT_REBOOT_FORCE) && s->reboot_arg) {
+ int r;
+
+ r = write_string_file(REBOOT_PARAM_FILE, s->reboot_arg);
+ if (r < 0) {
+ log_error("Failed to write reboot param to "
+ REBOOT_PARAM_FILE": %s", strerror(-r));
+ return r;
+ }
+ }
+
switch (s->start_limit_action) {
case SERVICE_START_LIMIT_NONE:
@@ -2404,7 +2418,14 @@ static int service_start_limit_test(Service *s) {
log_warning_unit(UNIT(s)->id,
"%s start request repeated too quickly, rebooting immediately.", UNIT(s)->id);
sync();
- reboot(RB_AUTOBOOT);
+ if (s->reboot_arg) {
+ log_info("Rebooting with arg '%s'.", s->reboot_arg);
+ syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+ LINUX_REBOOT_CMD_RESTART2, s->reboot_arg);
+ } else {
+ log_info("Rebooting.");
+ reboot(RB_AUTOBOOT);
+ }
break;
default:
diff --git a/src/core/service.h b/src/core/service.h
index 1992926..fd05e9b 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -189,6 +189,7 @@ struct Service {
RateLimit start_limit;
StartLimitAction start_limit_action;
+ char *reboot_arg;
UnitRef accept_socket;
--
1.9.1
More information about the systemd-devel
mailing list