|
@@ -387,8 +387,9 @@ void ctrl_alt_del(void)
|
|
|
}
|
|
|
|
|
|
char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
|
|
|
+static const char reboot_cmd[] = "/sbin/reboot";
|
|
|
|
|
|
-static int __orderly_poweroff(bool force)
|
|
|
+static int run_cmd(const char *cmd)
|
|
|
{
|
|
|
char **argv;
|
|
|
static char *envp[] = {
|
|
@@ -397,8 +398,7 @@ static int __orderly_poweroff(bool force)
|
|
|
NULL
|
|
|
};
|
|
|
int ret;
|
|
|
-
|
|
|
- argv = argv_split(GFP_KERNEL, poweroff_cmd, NULL);
|
|
|
+ argv = argv_split(GFP_KERNEL, cmd, NULL);
|
|
|
if (argv) {
|
|
|
ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
|
|
|
argv_free(argv);
|
|
@@ -406,8 +406,33 @@ static int __orderly_poweroff(bool force)
|
|
|
ret = -ENOMEM;
|
|
|
}
|
|
|
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int __orderly_reboot(void)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = run_cmd(reboot_cmd);
|
|
|
+
|
|
|
+ if (ret) {
|
|
|
+ pr_warn("Failed to start orderly reboot: forcing the issue\n");
|
|
|
+ emergency_sync();
|
|
|
+ kernel_restart(NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int __orderly_poweroff(bool force)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = run_cmd(poweroff_cmd);
|
|
|
+
|
|
|
if (ret && force) {
|
|
|
pr_warn("Failed to start orderly shutdown: forcing the issue\n");
|
|
|
+
|
|
|
/*
|
|
|
* I guess this should try to kick off some daemon to sync and
|
|
|
* poweroff asap. Or not even bother syncing if we're doing an
|
|
@@ -436,15 +461,33 @@ static DECLARE_WORK(poweroff_work, poweroff_work_func);
|
|
|
* This may be called from any context to trigger a system shutdown.
|
|
|
* If the orderly shutdown fails, it will force an immediate shutdown.
|
|
|
*/
|
|
|
-int orderly_poweroff(bool force)
|
|
|
+void orderly_poweroff(bool force)
|
|
|
{
|
|
|
if (force) /* do not override the pending "true" */
|
|
|
poweroff_force = true;
|
|
|
schedule_work(&poweroff_work);
|
|
|
- return 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(orderly_poweroff);
|
|
|
|
|
|
+static void reboot_work_func(struct work_struct *work)
|
|
|
+{
|
|
|
+ __orderly_reboot();
|
|
|
+}
|
|
|
+
|
|
|
+static DECLARE_WORK(reboot_work, reboot_work_func);
|
|
|
+
|
|
|
+/**
|
|
|
+ * orderly_reboot - Trigger an orderly system reboot
|
|
|
+ *
|
|
|
+ * This may be called from any context to trigger a system reboot.
|
|
|
+ * If the orderly reboot fails, it will force an immediate reboot.
|
|
|
+ */
|
|
|
+void orderly_reboot(void)
|
|
|
+{
|
|
|
+ schedule_work(&reboot_work);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(orderly_reboot);
|
|
|
+
|
|
|
static int __init reboot_setup(char *str)
|
|
|
{
|
|
|
for (;;) {
|