diff options
Diffstat (limited to 'kernel/reboot.c')
| -rw-r--r-- | kernel/reboot.c | 53 | 
1 files changed, 48 insertions, 5 deletions
diff --git a/kernel/reboot.c b/kernel/reboot.c index 5925f5ae8dff..d20c85d9f8c0 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -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 (;;) {  |