* debian deadlock when partition auf noauto is.
-* maintenance units müssen vergessen werden
-
* fingerprint.target, wireless.target, gps.target
* fix merging of device units
* pahole
+* color aus bei stdout auf !tty
+
External:
* default.target must be %ghosted...
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>
<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>,
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",
.fd_event = automount_fd_event,
+ .reset_maintenance = automount_reset_maintenance,
+
.bus_message_handler = bus_automount_message_handler,
.shutdown = automount_shutdown
" <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" \
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;
} else
return bus_default_message_handler(m, connection, message, NULL, properties);
-
if (job_type != _JOB_TYPE_INVALID) {
const char *name, *smode;
JobMode mode;
} 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
" <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" \
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"
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);
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",
.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,
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",
.fd_event = path_fd_event,
+ .reset_maintenance = path_reset_maintenance,
+
.bus_message_handler = bus_path_message_handler
};
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",
.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,
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",
.sigchld_event = socket_sigchld_event,
.timer_event = socket_timer_event,
+ .reset_maintenance = socket_reset_maintenance,
+
.bus_message_handler = bus_socket_message_handler
};
}
}
-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);
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",
.bus_message_handler = bus_swap_message_handler,
+ .reset_maintenance = swap_reset_maintenance,
+
.enumerate = swap_enumerate,
.shutdown = swap_shutdown
};
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(
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;
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"
" 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"
{ "default", EQUAL, 1, start_special },
{ "rescue", EQUAL, 1, start_special },
{ "emergency", EQUAL, 1, start_special },
+ { "reset-maintenance", MORE, 1, reset_maintenance },
};
int left;
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",
.timer_event = timer_timer_event,
+ .reset_maintenance = timer_reset_maintenance,
+
.bus_message_handler = bus_timer_message_handler
};
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",
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);
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);