fsck: atomically replace base.target by rescue.target/reboot.target when fsck fails

This commit is contained in:
Lennart Poettering 2010-10-19 21:53:19 +02:00
parent 3e33a44a01
commit 90bb85e140
2 changed files with 42 additions and 14 deletions

View file

@ -48,6 +48,12 @@
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"StartUnitReplace\">\n" \
" <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"StopUnit\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
@ -408,6 +414,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
job_type = JOB_START;
else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
job_type = JOB_START;
else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
job_type = JOB_STOP;
else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
@ -910,19 +918,40 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
return bus_default_message_handler(m, connection, message, NULL, properties);
if (job_type != _JOB_TYPE_INVALID) {
const char *name, *smode;
const char *name, *smode, *old_name = NULL;
JobMode mode;
Job *j;
Unit *u;
bool b;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &smode,
DBUS_TYPE_INVALID))
if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
b = dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &old_name,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &smode,
DBUS_TYPE_INVALID);
else
b = dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &smode,
DBUS_TYPE_INVALID);
if (!b)
return bus_send_error_reply(m, connection, message, &error, -EINVAL);
if (old_name)
if (!(u = manager_get_unit(m, old_name)) ||
!u->meta.job ||
u->meta.job->type != JOB_START) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
return bus_send_error_reply(m, connection, message, &error, -ENOENT);
}
if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
return bus_send_error_reply(m, connection, message, &error, -EINVAL);

View file

@ -38,7 +38,7 @@ static bool arg_force = false;
static void start_target(const char *target, bool isolate) {
DBusMessage *m = NULL, *reply = NULL;
DBusError error;
const char *mode;
const char *mode, *base_target = "base.target";
DBusConnection *bus = NULL;
assert(target);
@ -57,12 +57,15 @@ static void start_target(const char *target, bool isolate) {
log_debug("Running request %s/start/%s", target, mode);
if (!(m = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit"))) {
if (!(m = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnitReplace"))) {
log_error("Could not allocate message.");
goto finish;
}
/* Start these units only if we can replace base.target with it */
if (!dbus_message_append_args(m,
DBUS_TYPE_STRING, &base_target,
DBUS_TYPE_STRING, &target,
DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID)) {
@ -196,11 +199,7 @@ int main(int argc, char *argv[]) {
}
if (status.si_status & ~1) {
if (access("/dev/.systemd/late-fsck", F_OK) >= 0) {
log_error("fsck failed with error code %i.", status.si_status);
goto finish;
}
log_error("fsck failed with error code %i.", status.si_status);
if (status.si_status & 2)
/* System should be rebooted. */