summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fixme4
-rw-r--r--man/systemctl.xml19
-rw-r--r--man/systemd.xml2
-rw-r--r--src/automount.c13
-rw-r--r--src/dbus-manager.c33
-rw-r--r--src/dbus-unit.c7
-rw-r--r--src/dbus-unit.h1
-rw-r--r--src/manager.c10
-rw-r--r--src/manager.h2
-rw-r--r--src/mount.c13
-rw-r--r--src/path.c13
-rw-r--r--src/service.c13
-rw-r--r--src/socket.c13
-rw-r--r--src/swap.c27
-rw-r--r--src/systemctl.c71
-rw-r--r--src/timer.c13
-rw-r--r--src/unit.c7
-rw-r--r--src/unit.h5
18 files changed, 249 insertions, 17 deletions
diff --git a/fixme b/fixme
index 30cfaac34..29e0fde74 100644
--- a/fixme
+++ b/fixme
@@ -47,8 +47,6 @@
* debian deadlock when partition auf noauto is.
-* maintenance units müssen vergessen werden
-
* fingerprint.target, wireless.target, gps.target
* fix merging of device units
@@ -57,6 +55,8 @@
* pahole
+* color aus bei stdout auf !tty
+
External:
* default.target must be %ghosted...
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 42682b787..737bcbe02 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -314,6 +314,25 @@
properties of the job is
shown.</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><command>reset-maintenance [NAME...]</command></term>
+
+ <listitem><para>Reset maintenance
+ state of the specified units, or if no
+ unit name is passed of all units. When
+ a unit fails in some way (i.e. process
+ exiting with non-zero error code,
+ terminating abnormally or timing out)
+ it will automatically enter
+ maintenance state and its exit codes
+ and status is recorded for
+ introspection by the administrator
+ until the service is restarted or
+ reset with this
+ command.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><command>load [NAME...]</command></term>
diff --git a/man/systemd.xml b/man/systemd.xml
index 25f24ce72..c027b4f66 100644
--- a/man/systemd.xml
+++ b/man/systemd.xml
@@ -226,7 +226,7 @@
<para>systemd provides a dependency system between
various entities called "units". Units encapsulate
various objects that are relevant for system boot-up
- and maintainance. The majority of units are configured
+ and maintenance. The majority of units are configured
in unit configuration files, whose syntax and basic
set of options is described in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
diff --git a/src/automount.c b/src/automount.c
index e685c96a7..213b178ea 100644
--- a/src/automount.c
+++ b/src/automount.c
@@ -791,6 +791,17 @@ static void automount_shutdown(Manager *m) {
close_nointr_nofail(m->dev_autofs_fd);
}
+static void automount_reset_maintenance(Unit *u) {
+ Automount *a = AUTOMOUNT(u);
+
+ assert(a);
+
+ if (a->state == AUTOMOUNT_MAINTENANCE)
+ automount_set_state(a, AUTOMOUNT_DEAD);
+
+ a->failure = false;
+}
+
static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
[AUTOMOUNT_DEAD] = "dead",
[AUTOMOUNT_WAITING] = "waiting",
@@ -827,6 +838,8 @@ const UnitVTable automount_vtable = {
.fd_event = automount_fd_event,
+ .reset_maintenance = automount_reset_maintenance,
+
.bus_message_handler = bus_automount_message_handler,
.shutdown = automount_shutdown
diff --git a/src/dbus-manager.c b/src/dbus-manager.c
index c717ccd81..969c43052 100644
--- a/src/dbus-manager.c
+++ b/src/dbus-manager.c
@@ -72,11 +72,15 @@
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
+ " <method name=\"ResetMaintenanceUnit\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " </method>\n" \
" <method name=\"GetJob\">\n" \
" <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"ClearJobs\"/>\n" \
+ " <method name=\"ResetMaintenance\"/>\n" \
" <method name=\"ListUnits\">\n" \
" <arg name=\"units\" type=\"a(sssssouso)\" direction=\"out\"/>\n" \
" </method>\n" \
@@ -362,6 +366,34 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetMaintenance")) {
+
+ manager_reset_maintenance(m);
+
+ if (!(reply = dbus_message_new_method_return(message)))
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetMaintenanceUnit")) {
+ const char *name;
+ Unit *u;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+
+ if (!(u = manager_get_unit(m, name))) {
+ dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ }
+
+ unit_reset_maintenance(u);
+
+ if (!(reply = dbus_message_new_method_return(message)))
+ goto oom;
+
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
DBusMessageIter iter, sub;
Iterator i;
@@ -733,7 +765,6 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
} else
return bus_default_message_handler(m, connection, message, NULL, properties);
-
if (job_type != _JOB_TYPE_INVALID) {
const char *name, *smode;
JobMode mode;
diff --git a/src/dbus-unit.c b/src/dbus-unit.c
index ce3413099..2dcd032a4 100644
--- a/src/dbus-unit.c
+++ b/src/dbus-unit.c
@@ -298,6 +298,13 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrTryRestart")) {
reload_if_possible = true;
job_type = JOB_TRY_RESTART;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ResetMaintenance")) {
+
+ unit_reset_maintenance(u);
+
+ if (!(reply = dbus_message_new_method_return(message)))
+ goto oom;
+
} else if (UNIT_VTABLE(u)->bus_message_handler)
return UNIT_VTABLE(u)->bus_message_handler(u, connection, message);
else
diff --git a/src/dbus-unit.h b/src/dbus-unit.h
index 0b9c62f86..e49f82d8c 100644
--- a/src/dbus-unit.h
+++ b/src/dbus-unit.h
@@ -56,6 +56,7 @@
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
+ " <method name=\"ResetMaintenance\"/>\n" \
" <signal name=\"Changed\"/>\n" \
" <property name=\"Id\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Names\" type=\"as\" access=\"read\"/>\n" \
diff --git a/src/manager.c b/src/manager.c
index 7b2586fb0..8a9b9dd44 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -2466,6 +2466,16 @@ bool manager_is_booting_or_shutting_down(Manager *m) {
return false;
}
+void manager_reset_maintenance(Manager *m) {
+ Unit *u;
+ Iterator i;
+
+ assert(m);
+
+ HASHMAP_FOREACH(u, m->units, i)
+ unit_reset_maintenance(u);
+}
+
static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = {
[MANAGER_SYSTEM] = "system",
[MANAGER_SESSION] = "session"
diff --git a/src/manager.h b/src/manager.h
index c492ffa55..96de120d3 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -247,6 +247,8 @@ int manager_reload(Manager *m);
bool manager_is_booting_or_shutting_down(Manager *m);
+void manager_reset_maintenance(Manager *m);
+
const char *manager_running_as_to_string(ManagerRunningAs i);
ManagerRunningAs manager_running_as_from_string(const char *s);
diff --git a/src/mount.c b/src/mount.c
index bee3c9a60..c1a1d5114 100644
--- a/src/mount.c
+++ b/src/mount.c
@@ -1538,6 +1538,17 @@ finish:
return r;
}
+static void mount_reset_maintenance(Unit *u) {
+ Mount *m = MOUNT(u);
+
+ assert(m);
+
+ if (m->state == MOUNT_MAINTENANCE)
+ mount_set_state(m, MOUNT_DEAD);
+
+ m->failure = false;
+}
+
static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
[MOUNT_DEAD] = "dead",
[MOUNT_MOUNTING] = "mounting",
@@ -1595,6 +1606,8 @@ const UnitVTable mount_vtable = {
.sigchld_event = mount_sigchld_event,
.timer_event = mount_timer_event,
+ .reset_maintenance = mount_reset_maintenance,
+
.bus_message_handler = bus_mount_message_handler,
.enumerate = mount_enumerate,
diff --git a/src/path.c b/src/path.c
index a9fa3771a..f4c20940d 100644
--- a/src/path.c
+++ b/src/path.c
@@ -560,6 +560,17 @@ fail:
log_error("Failed find path unit: %s", strerror(-r));
}
+static void path_reset_maintenance(Unit *u) {
+ Path *p = PATH(u);
+
+ assert(p);
+
+ if (p->state == PATH_MAINTENANCE)
+ path_set_state(p, PATH_DEAD);
+
+ p->failure = false;
+}
+
static const char* const path_state_table[_PATH_STATE_MAX] = {
[PATH_DEAD] = "dead",
[PATH_WAITING] = "waiting",
@@ -598,5 +609,7 @@ const UnitVTable path_vtable = {
.fd_event = path_fd_event,
+ .reset_maintenance = path_reset_maintenance,
+
.bus_message_handler = bus_path_message_handler
};
diff --git a/src/service.c b/src/service.c
index a5d1ebd84..6b786d1bb 100644
--- a/src/service.c
+++ b/src/service.c
@@ -2734,6 +2734,17 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock) {
return 0;
}
+static void service_reset_maintenance(Unit *u) {
+ Service *s = SERVICE(u);
+
+ assert(s);
+
+ if (s->state == SERVICE_MAINTENANCE)
+ service_set_state(s, SERVICE_DEAD);
+
+ s->failure = false;
+}
+
static const char* const service_state_table[_SERVICE_STATE_MAX] = {
[SERVICE_DEAD] = "dead",
[SERVICE_START_PRE] = "start-pre",
@@ -2821,6 +2832,8 @@ const UnitVTable service_vtable = {
.sigchld_event = service_sigchld_event,
.timer_event = service_timer_event,
+ .reset_maintenance = service_reset_maintenance,
+
.cgroup_notify_empty = service_cgroup_notify_event,
.notify_message = service_notify_message,
diff --git a/src/socket.c b/src/socket.c
index 4cf21cf0b..2c9d69391 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1698,6 +1698,17 @@ void socket_connection_unref(Socket *s) {
log_debug("%s: One connection closed, %u left.", s->meta.id, s->n_connections);
}
+static void socket_reset_maintenance(Unit *u) {
+ Socket *s = SOCKET(u);
+
+ assert(s);
+
+ if (s->state == SOCKET_MAINTENANCE)
+ socket_set_state(s, SOCKET_DEAD);
+
+ s->failure = false;
+}
+
static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
[SOCKET_DEAD] = "dead",
[SOCKET_START_PRE] = "start-pre",
@@ -1750,5 +1761,7 @@ const UnitVTable socket_vtable = {
.sigchld_event = socket_sigchld_event,
.timer_event = socket_timer_event,
+ .reset_maintenance = socket_reset_maintenance,
+
.bus_message_handler = bus_socket_message_handler
};
diff --git a/src/swap.c b/src/swap.c
index de468a043..6765a4ae3 100644
--- a/src/swap.c
+++ b/src/swap.c
@@ -542,14 +542,6 @@ static void swap_shutdown(Manager *m) {
}
}
-static const char* const swap_state_table[_SWAP_STATE_MAX] = {
- [SWAP_DEAD] = "dead",
- [SWAP_ACTIVE] = "active",
- [SWAP_MAINTENANCE] = "maintenance"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
-
static int swap_enumerate(Manager *m) {
int r;
assert(m);
@@ -564,6 +556,23 @@ static int swap_enumerate(Manager *m) {
return r;
}
+static void swap_reset_maintenance(Unit *u) {
+ Swap *s = SWAP(u);
+
+ assert(s);
+
+ if (s->state == SWAP_MAINTENANCE)
+ swap_set_state(s, SWAP_DEAD);
+}
+
+static const char* const swap_state_table[_SWAP_STATE_MAX] = {
+ [SWAP_DEAD] = "dead",
+ [SWAP_ACTIVE] = "active",
+ [SWAP_MAINTENANCE] = "maintenance"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
+
const UnitVTable swap_vtable = {
.suffix = ".swap",
@@ -592,6 +601,8 @@ const UnitVTable swap_vtable = {
.bus_message_handler = bus_swap_message_handler,
+ .reset_maintenance = swap_reset_maintenance,
+
.enumerate = swap_enumerate,
.shutdown = swap_shutdown
};
diff --git a/src/systemctl.c b/src/systemctl.c
index 06b4caea5..acb89a5a8 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -2639,10 +2639,11 @@ static int clear_jobs(DBusConnection *bus, char **args, unsigned n) {
assert(arg_action == ACTION_SYSTEMCTL);
method =
- streq(args[0], "clear-jobs") ? "ClearJobs" :
- streq(args[0], "daemon-reload") ? "Reload" :
- streq(args[0], "daemon-reexec") ? "Reexecute" :
- "Exit";
+ streq(args[0], "clear-jobs") ? "ClearJobs" :
+ streq(args[0], "daemon-reload") ? "Reload" :
+ streq(args[0], "daemon-reexec") ? "Reexecute" :
+ streq(args[0], "reset-maintenance") ? "ResetMaintenance" :
+ "Exit";
}
if (!(m = dbus_message_new_method_call(
@@ -2682,6 +2683,63 @@ finish:
return r;
}
+static int reset_maintenance(DBusConnection *bus, char **args, unsigned n) {
+ DBusMessage *m = NULL, *reply = NULL;
+ unsigned i;
+ int r;
+ DBusError error;
+
+ assert(bus);
+ dbus_error_init(&error);
+
+ if (n <= 1)
+ return clear_jobs(bus, args, n);
+
+ for (i = 1; i < n; i++) {
+
+ if (!(m = dbus_message_new_method_call(
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "ResetMaintenanceUnit"))) {
+ log_error("Could not allocate message.");
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ if (!dbus_message_append_args(m,
+ DBUS_TYPE_STRING, args + i,
+ DBUS_TYPE_INVALID)) {
+ log_error("Could not append arguments to message.");
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
+ log_error("Failed to issue method call: %s", error.message);
+ r = -EIO;
+ goto finish;
+ }
+
+ dbus_message_unref(m);
+ dbus_message_unref(reply);
+ m = reply = NULL;
+ }
+
+ r = 0;
+
+finish:
+ if (m)
+ dbus_message_unref(m);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return r;
+}
+
static int show_enviroment(DBusConnection *bus, char **args, unsigned n) {
DBusMessage *m = NULL, *reply = NULL;
DBusError error;
@@ -2832,7 +2890,7 @@ finish:
static int systemctl_help(void) {
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
- "Send control commands to the systemd manager.\n\n"
+ "Send control commands to or query the systemd manager.\n\n"
" -h --help Show this help\n"
" -t --type=TYPE List only units of a particular type\n"
" -p --property=NAME Show only properties by this name\n"
@@ -2862,6 +2920,8 @@ static int systemctl_help(void) {
" status [NAME...] Show status of one or more units\n"
" show [NAME...|JOB...] Show properties of one or more\n"
" units/jobs/manager\n"
+ " reset-maintenance [NAME...] Reset maintenance state for all, one\n"
+ " or more units\n"
" load [NAME...] Load one or more units\n"
" list-jobs List jobs\n"
" cancel [JOB...] Cancel one or more jobs\n"
@@ -3579,6 +3639,7 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[]) {
{ "default", EQUAL, 1, start_special },
{ "rescue", EQUAL, 1, start_special },
{ "emergency", EQUAL, 1, start_special },
+ { "reset-maintenance", MORE, 1, reset_maintenance },
};
int left;
diff --git a/src/timer.c b/src/timer.c
index 158047894..cd6728a18 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -450,6 +450,17 @@ fail:
log_error("Failed find timer unit: %s", strerror(-r));
}
+static void timer_reset_maintenance(Unit *u) {
+ Timer *t = TIMER(u);
+
+ assert(t);
+
+ if (t->state == TIMER_MAINTENANCE)
+ timer_set_state(t, TIMER_DEAD);
+
+ t->failure = false;
+}
+
static const char* const timer_state_table[_TIMER_STATE_MAX] = {
[TIMER_DEAD] = "dead",
[TIMER_WAITING] = "waiting",
@@ -492,5 +503,7 @@ const UnitVTable timer_vtable = {
.timer_event = timer_timer_event,
+ .reset_maintenance = timer_reset_maintenance,
+
.bus_message_handler = bus_timer_message_handler
};
diff --git a/src/unit.c b/src/unit.c
index 348d13958..5807e4f4d 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -2071,6 +2071,13 @@ bool unit_need_daemon_reload(Unit *u) {
timespec_load(&st.st_mtim) != u->meta.fragment_mtime;
}
+void unit_reset_maintenance(Unit *u) {
+ assert(u);
+
+ if (UNIT_VTABLE(u)->reset_maintenance)
+ UNIT_VTABLE(u)->reset_maintenance(u);
+}
+
static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
[UNIT_SERVICE] = "service",
[UNIT_TIMER] = "timer",
diff --git a/src/unit.h b/src/unit.h
index cfad3ca53..1295d9ff5 100644
--- a/src/unit.h
+++ b/src/unit.h
@@ -290,6 +290,9 @@ struct UnitVTable {
void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
void (*timer_event)(Unit *u, uint64_t n_elapsed, Watch *w);
+ /* Reset maintenance state if we are in maintainance state */
+ void (*reset_maintenance)(Unit *u);
+
/* Called whenever any of the cgroups this unit watches for
* ran empty */
void (*cgroup_notify_empty)(Unit *u);
@@ -467,6 +470,8 @@ void unit_status_printf(Unit *u, const char *format, ...);
bool unit_need_daemon_reload(Unit *u);
+void unit_reset_maintenance(Unit *u);
+
const char *unit_type_to_string(UnitType i);
UnitType unit_type_from_string(const char *s);