diff options
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 4d141ae3e802..aeded9ad66ce 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -2286,3 +2286,61 @@ asmlinkage long sys_getcpu(unsigned __user *cpup, unsigned __user *nodep, | |||
2286 | } | 2286 | } |
2287 | return err ? -EFAULT : 0; | 2287 | return err ? -EFAULT : 0; |
2288 | } | 2288 | } |
2289 | |||
2290 | char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff"; | ||
2291 | |||
2292 | static void argv_cleanup(char **argv, char **envp) | ||
2293 | { | ||
2294 | argv_free(argv); | ||
2295 | } | ||
2296 | |||
2297 | /** | ||
2298 | * orderly_poweroff - Trigger an orderly system poweroff | ||
2299 | * @force: force poweroff if command execution fails | ||
2300 | * | ||
2301 | * This may be called from any context to trigger a system shutdown. | ||
2302 | * If the orderly shutdown fails, it will force an immediate shutdown. | ||
2303 | */ | ||
2304 | int orderly_poweroff(bool force) | ||
2305 | { | ||
2306 | int argc; | ||
2307 | char **argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); | ||
2308 | static char *envp[] = { | ||
2309 | "HOME=/", | ||
2310 | "PATH=/sbin:/bin:/usr/sbin:/usr/bin", | ||
2311 | NULL | ||
2312 | }; | ||
2313 | int ret = -ENOMEM; | ||
2314 | struct subprocess_info *info; | ||
2315 | |||
2316 | if (argv == NULL) { | ||
2317 | printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", | ||
2318 | __func__, poweroff_cmd); | ||
2319 | goto out; | ||
2320 | } | ||
2321 | |||
2322 | info = call_usermodehelper_setup(argv[0], argv, envp); | ||
2323 | if (info == NULL) { | ||
2324 | argv_free(argv); | ||
2325 | goto out; | ||
2326 | } | ||
2327 | |||
2328 | call_usermodehelper_setcleanup(info, argv_cleanup); | ||
2329 | |||
2330 | ret = call_usermodehelper_exec(info, -1); | ||
2331 | |||
2332 | out: | ||
2333 | if (ret && force) { | ||
2334 | printk(KERN_WARNING "Failed to start orderly shutdown: " | ||
2335 | "forcing the issue\n"); | ||
2336 | |||
2337 | /* I guess this should try to kick off some daemon to | ||
2338 | sync and poweroff asap. Or not even bother syncing | ||
2339 | if we're doing an emergency shutdown? */ | ||
2340 | emergency_sync(); | ||
2341 | kernel_power_off(); | ||
2342 | } | ||
2343 | |||
2344 | return ret; | ||
2345 | } | ||
2346 | EXPORT_SYMBOL_GPL(orderly_poweroff); | ||