]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - kernel/sys.c
mm: replace hardcoded 3% with admin_reserve_pages knob
[karo-tx-linux.git] / kernel / sys.c
index 81f56445fba949790b34b7bf3f97383555134672..0da73cf73e60937ba8eb65a77f20febcb8264c45 100644 (file)
@@ -324,7 +324,6 @@ void kernel_restart_prepare(char *cmd)
        system_state = SYSTEM_RESTART;
        usermodehelper_disable();
        device_shutdown();
-       syscore_shutdown();
 }
 
 /**
@@ -370,6 +369,7 @@ void kernel_restart(char *cmd)
 {
        kernel_restart_prepare(cmd);
        disable_nonboot_cpus();
+       syscore_shutdown();
        if (!cmd)
                printk(KERN_EMERG "Restarting system.\n");
        else
@@ -395,6 +395,7 @@ static void kernel_shutdown_prepare(enum system_states state)
 void kernel_halt(void)
 {
        kernel_shutdown_prepare(SYSTEM_HALT);
+       disable_nonboot_cpus();
        syscore_shutdown();
        printk(KERN_EMERG "System halted.\n");
        kmsg_dump(KMSG_DUMP_HALT);
@@ -2185,9 +2186,8 @@ SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
 
 char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
 
-static int __orderly_poweroff(void)
+static int __orderly_poweroff(bool force)
 {
-       int argc;
        char **argv;
        static char *envp[] = {
                "HOME=/",
@@ -2196,20 +2196,40 @@ static int __orderly_poweroff(void)
        };
        int ret;
 
-       argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc);
-       if (argv == NULL) {
+       argv = argv_split(GFP_KERNEL, poweroff_cmd, NULL);
+       if (argv) {
+               ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+               argv_free(argv);
+       } else {
                printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n",
-                      __func__, poweroff_cmd);
-               return -ENOMEM;
+                                        __func__, poweroff_cmd);
+               ret = -ENOMEM;
        }
 
-       ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_WAIT_EXEC,
-                                     NULL, NULL, NULL);
-       argv_free(argv);
+       if (ret && force) {
+               printk(KERN_WARNING "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
+                * emergency shutdown?
+                */
+               emergency_sync();
+               kernel_power_off();
+       }
 
        return ret;
 }
 
+static bool poweroff_force;
+
+static void poweroff_work_func(struct work_struct *work)
+{
+       __orderly_poweroff(poweroff_force);
+}
+
+static DECLARE_WORK(poweroff_work, poweroff_work_func);
+
 /**
  * orderly_poweroff - Trigger an orderly system poweroff
  * @force: force poweroff if command execution fails
@@ -2219,21 +2239,9 @@ static int __orderly_poweroff(void)
  */
 int orderly_poweroff(bool force)
 {
-       int ret = __orderly_poweroff();
-
-       if (ret && force) {
-               printk(KERN_WARNING "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
-                * emergency shutdown?
-                */
-               emergency_sync();
-               kernel_power_off();
-       }
-
-       return ret;
+       if (force) /* do not override the pending "true" */
+               poweroff_force = true;
+       schedule_work(&poweroff_work);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(orderly_poweroff);