aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c60
1 files changed, 34 insertions, 26 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index 81f56445fba9..0da73cf73e60 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -324,7 +324,6 @@ void kernel_restart_prepare(char *cmd)
324 system_state = SYSTEM_RESTART; 324 system_state = SYSTEM_RESTART;
325 usermodehelper_disable(); 325 usermodehelper_disable();
326 device_shutdown(); 326 device_shutdown();
327 syscore_shutdown();
328} 327}
329 328
330/** 329/**
@@ -370,6 +369,7 @@ void kernel_restart(char *cmd)
370{ 369{
371 kernel_restart_prepare(cmd); 370 kernel_restart_prepare(cmd);
372 disable_nonboot_cpus(); 371 disable_nonboot_cpus();
372 syscore_shutdown();
373 if (!cmd) 373 if (!cmd)
374 printk(KERN_EMERG "Restarting system.\n"); 374 printk(KERN_EMERG "Restarting system.\n");
375 else 375 else
@@ -395,6 +395,7 @@ static void kernel_shutdown_prepare(enum system_states state)
395void kernel_halt(void) 395void kernel_halt(void)
396{ 396{
397 kernel_shutdown_prepare(SYSTEM_HALT); 397 kernel_shutdown_prepare(SYSTEM_HALT);
398 disable_nonboot_cpus();
398 syscore_shutdown(); 399 syscore_shutdown();
399 printk(KERN_EMERG "System halted.\n"); 400 printk(KERN_EMERG "System halted.\n");
400 kmsg_dump(KMSG_DUMP_HALT); 401 kmsg_dump(KMSG_DUMP_HALT);
@@ -2185,9 +2186,8 @@ SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
2185 2186
2186char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff"; 2187char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
2187 2188
2188static int __orderly_poweroff(void) 2189static int __orderly_poweroff(bool force)
2189{ 2190{
2190 int argc;
2191 char **argv; 2191 char **argv;
2192 static char *envp[] = { 2192 static char *envp[] = {
2193 "HOME=/", 2193 "HOME=/",
@@ -2196,20 +2196,40 @@ static int __orderly_poweroff(void)
2196 }; 2196 };
2197 int ret; 2197 int ret;
2198 2198
2199 argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); 2199 argv = argv_split(GFP_KERNEL, poweroff_cmd, NULL);
2200 if (argv == NULL) { 2200 if (argv) {
2201 ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
2202 argv_free(argv);
2203 } else {
2201 printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", 2204 printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n",
2202 __func__, poweroff_cmd); 2205 __func__, poweroff_cmd);
2203 return -ENOMEM; 2206 ret = -ENOMEM;
2204 } 2207 }
2205 2208
2206 ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_WAIT_EXEC, 2209 if (ret && force) {
2207 NULL, NULL, NULL); 2210 printk(KERN_WARNING "Failed to start orderly shutdown: "
2208 argv_free(argv); 2211 "forcing the issue\n");
2212 /*
2213 * I guess this should try to kick off some daemon to sync and
2214 * poweroff asap. Or not even bother syncing if we're doing an
2215 * emergency shutdown?
2216 */
2217 emergency_sync();
2218 kernel_power_off();
2219 }
2209 2220
2210 return ret; 2221 return ret;
2211} 2222}
2212 2223
2224static bool poweroff_force;
2225
2226static void poweroff_work_func(struct work_struct *work)
2227{
2228 __orderly_poweroff(poweroff_force);
2229}
2230
2231static DECLARE_WORK(poweroff_work, poweroff_work_func);
2232
2213/** 2233/**
2214 * orderly_poweroff - Trigger an orderly system poweroff 2234 * orderly_poweroff - Trigger an orderly system poweroff
2215 * @force: force poweroff if command execution fails 2235 * @force: force poweroff if command execution fails
@@ -2219,21 +2239,9 @@ static int __orderly_poweroff(void)
2219 */ 2239 */
2220int orderly_poweroff(bool force) 2240int orderly_poweroff(bool force)
2221{ 2241{
2222 int ret = __orderly_poweroff(); 2242 if (force) /* do not override the pending "true" */
2223 2243 poweroff_force = true;
2224 if (ret && force) { 2244 schedule_work(&poweroff_work);
2225 printk(KERN_WARNING "Failed to start orderly shutdown: " 2245 return 0;
2226 "forcing the issue\n");
2227
2228 /*
2229 * I guess this should try to kick off some daemon to sync and
2230 * poweroff asap. Or not even bother syncing if we're doing an
2231 * emergency shutdown?
2232 */
2233 emergency_sync();
2234 kernel_power_off();
2235 }
2236
2237 return ret;
2238} 2246}
2239EXPORT_SYMBOL_GPL(orderly_poweroff); 2247EXPORT_SYMBOL_GPL(orderly_poweroff);