On 11/06/2013 03:53 PM, Zbigniew Jędrzejewski-Szmek wrote: > On Wed, Nov 06, 2013 at 03:22:49PM +0900, WaLyong Cho wrote: >> >> >> On 09/12/2013 02:20 AM, Lennart Poettering wrote: >>> On Tue, 13.08.13 03:01, WaLyong Cho (fyd0...@gmail.com) wrote: >>> >>>> From: WaLyong Cho <walyong....@samsung.com> >>>> >>>> reboot syscall can be performed with additional argument. In some of >>>> system, this functionality can be useful to ask next boot mode to >>>> bootloader. >>> >>> Hmm, interesting stuff. >>> >>>> @@ -5200,9 +5204,19 @@ static int halt_parse_argv(int argc, char *argv[]) { >>>> } >>>> } >>>> >>> >>> Note that halt is not called during normal shutdown, but is only a >>> compat fallback for the old sysv "halt" command. If you want this to >>> work we probably need to come up with a way to pass the string from >>> systemctl to the final systemd-shutdown process. >>> >>> (A bit of background: systemctl normally will just tell PID 1 to >>> shutdown cleanly, via D-Bus. As last step of that PID 1 will execute the >>> special systemd-shutdown binary -- which will then also run as PID 1 -- >>> which will do some final shutdown steps and then invoke the reboot() >>> syscall -- see src/core/shutdown.c for details) >> >> Sorry for my long silence. >> >> You were right. Previous my patch did not pass the argument without >> force option. So I modified according to your opinion. But I think we >> have to keep some codes in systemctl for supporting forced reboot. >> >>> >>> So, before we continue with this, could you point me to some >>> docs/commits/code which explain a bit how the new reboot() syscall >>> semantics work? i.e. what the possible params are and such? >> >> There are not any params specified. Any string can be used. That string >> is used in kernel side. >> http://lxr.linux.no/linux+v3.4/kernel/sys.c#L486 >> >> Sorry, there are no visible commits for Tizen in the web. But, for >> simple example, fota, recovery, download and more are used in Tizen. >> fota is used when restart to enter fota updated mode. In the mobile, >> user can download firmware image by on air. And update device firmware >> to downloaded. During this, reboot is performed. See >> http://www.redbend.com/en/products-solutions/fota-updating for detail. >> recovery is used for detecting hacked kernel. I am not sure that I can >> explain more. >> download is used to enter download mode. As you may know, most of >> devices are downloaded(not installed) when the device is produced. At >> this time, special boot mode is used to flush device. >> >> I found similar codes in android. >> https://github.com/CyanogenMod/android_system_core/blob/gingerbread/toolbox/reboot.c >> https://github.com/CyanogenMod/android_system_core/blob/gingerbread/libreboot/reboot.c >> >>> >>> One way to implement this could be to add add a new parameter to >>> systemctl which is written to /run/systemd/reboot-param or so if >>> specified. systemd-shutdown would then look for that file and pass it to >>> the reboot() syscall. >> >> According to man page of reboot. They called this 'arg'. >> http://man7.org/linux/man-pages/man2/reboot.2.htm >> I'm not sure which is more suitable word between 'param' and 'arg'. You >> offered 'param', so I used also 'param'. Because, 'arg' can be confused >> with argc/argv. >> >>> >>>> - if (optind < argc) { >>>> - log_error("Too many arguments."); >>>> - return -EINVAL; >>>> + if (arg_action == ACTION_REBOOT) { >>>> + /* reboot allow just one argument for his command string >>>> */ >>>> + if (optind+1 == argc) >>>> + arg_reboot = strdup(argv[argc-1]); >>>> + else if (optind+1 < argc) { >>>> + log_error("Too many arguments."); >>>> + return -EINVAL; >>>> + } >>>> + } else { >>>> + if (optind < argc) { >>>> + log_error("Too many arguments."); >>>> + return -EINVAL; >>>> + } >>>> } >>>> >>>> return 1; >>>> @@ -5949,7 +5963,11 @@ static _noreturn_ void halt_now(enum action a) { >>>> >>>> case ACTION_REBOOT: >>>> log_info("Rebooting."); >>>> - reboot(RB_AUTOBOOT); >>>> + if (arg_reboot) >>>> + syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, >>>> LINUX_REBOOT_MAGIC2, >>>> + LINUX_REBOOT_CMD_RESTART2, arg_reboot); >>>> + else >>>> + reboot(RB_AUTOBOOT); >>>> break; >>>> >>>> default: >>> >>> >>> Lennart >>> >> >> WaLyong > >> From 3e68b25edab207cdeffb267368e24f6c3a5830ae Mon Sep 17 00:00:00 2001 >> From: WaLyong Cho <walyong....@samsung.com> >> Date: Tue, 5 Nov 2013 17:11:09 +0900 >> Subject: [PATCH] make reboot to support additional command >> >> reboot syscall can be performed with additional argument. In some of >> system, this functionality can be useful to ask next boot mode to >> bootloader. >> --- >> Makefile.am | 4 ++- >> src/core/shutdown.c | 15 +++++++--- >> src/shared/reboot-param.c | 68 >> +++++++++++++++++++++++++++++++++++++++++++++ >> src/shared/reboot-param.h | 28 +++++++++++++++++++ >> src/systemctl/systemctl.c | 43 +++++++++++++++++++++++++--- >> 5 files changed, 149 insertions(+), 9 deletions(-) >> create mode 100644 src/shared/reboot-param.c >> create mode 100644 src/shared/reboot-param.h >> >> diff --git a/Makefile.am b/Makefile.am >> index ed61884..db79069 100644 >> --- a/Makefile.am >> +++ b/Makefile.am >> @@ -752,7 +752,9 @@ libsystemd_shared_la_SOURCES = \ >> src/shared/ptyfwd.c \ >> src/shared/ptyfwd.h \ >> src/shared/net-util.c \ >> - src/shared/net-util.h >> + src/shared/net-util.h \ >> + src/shared/reboot-param.c \ >> + src/shared/reboot-param.h >> >> >> #------------------------------------------------------------------------------- >> noinst_LTLIBRARIES += \ >> diff --git a/src/core/shutdown.c b/src/core/shutdown.c >> index aa9548e..7f82446 100644 >> --- a/src/core/shutdown.c >> +++ b/src/core/shutdown.c >> @@ -47,6 +47,7 @@ >> #include "watchdog.h" >> #include "killall.h" >> #include "cgroup-util.h" >> +#include "reboot-param.h" >> >> #define FINALIZE_ATTEMPTS 50 >> >> @@ -133,9 +134,10 @@ static int pivot_to_new_root(void) { >> >> int main(int argc, char *argv[]) { >> bool need_umount = true, need_swapoff = true, need_loop_detach = >> true, need_dm_detach = true; >> - bool in_container, use_watchdog = false; >> + bool in_container, use_watchdog, with_param = false; > Why use_watchdog is changed? > >> _cleanup_free_ char *line = NULL, *cgroup = NULL; >> char *arguments[3]; >> + char param[LINE_MAX]; > Please no. > >> unsigned retries; >> int cmd, r; >> >> @@ -173,9 +175,11 @@ int main(int argc, char *argv[]) { >> >> in_container = detect_container(NULL) > 0; >> >> - if (streq(argv[1], "reboot")) >> + if (streq(argv[1], "reboot")) { >> cmd = RB_AUTOBOOT; >> - else if (streq(argv[1], "poweroff")) >> + if (reboot_get_param(param, sizeof(param)) > 0) >> + with_param = true; >> + } else if (streq(argv[1], "poweroff")) >> cmd = RB_POWER_OFF; >> else if (streq(argv[1], "halt")) >> cmd = RB_HALT_SYSTEM; >> @@ -337,7 +341,10 @@ int main(int argc, char *argv[]) { >> cmd = RB_AUTOBOOT; >> } >> >> - reboot(cmd); >> + if (with_param) >> + reboot_with_param(param); >> + else >> + reboot(cmd); >> >> if (errno == EPERM && in_container) { >> /* If we are in a container, and we lacked >> diff --git a/src/shared/reboot-param.c b/src/shared/reboot-param.c >> new file mode 100644 >> index 0000000..55f64dd >> --- /dev/null >> +++ b/src/shared/reboot-param.c >> @@ -0,0 +1,68 @@ >> +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ >> + >> +/*** >> + This file is part of systemd. >> + >> + Copyright 2013 Samsung Electronics >> + >> + Author: WaLyong Cho <walyong....@samsung.com> >> + >> + systemd is free software; you can redistribute it and/or modify it >> + under the terms of the GNU Lesser General Public License as published by >> + the Free Software Foundation; either version 2.1 of the License, or >> + (at your option) any later version. >> + >> + systemd is distributed in the hope that it will be useful, but >> + WITHOUT ANY WARRANTY; without even the implied warranty of >> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + Lesser General Public License for more details. >> + >> + You should have received a copy of the GNU Lesser General Public License >> + along with systemd; If not, see <http://www.gnu.org/licenses/>. >> +***/ >> + >> +#include <sys/reboot.h> >> +#include <linux/reboot.h> >> +#include <sys/syscall.h> >> + >> +#include "reboot-param.h" >> +#include "util.h" >> + >> +#define REBOOT_PARAM "/run/systemd/reboot-param" >> + >> +int reboot_set_param(const char *param) { >> + _cleanup_fclose_ FILE *f = NULL; >> + >> + f = fopen(REBOOT_PARAM, "w"); >> + if (!f) { >> + log_error("Failed to create %s: %m", REBOOT_PARAM); >> + return -errno; >> + } >> + fputs(param, f); >> + if (fflush(f)) { >> + log_error("Failed to flush %s: %m", REBOOT_PARAM); >> + return -errno; >> + } >> + >> + return 0; >> +} > Please use write_string_file instead. > >> + >> +int reboot_get_param(char *param, int len) { >> + _cleanup_fclose_ FILE *f = NULL; >> + >> + f = fopen(REBOOT_PARAM, "r"); >> + if (f == NULL ) >> + return 0; >> + >> + if (!fgets(param, len, f)) { >> + log_error("Failed to read reboot param: %m"); >> + return -errno; >> + } >> + >> + return 1; >> +} > Please use read_one_line_file instead. > > With those two functions gone, those two new files will not be necessary. > REBOOT_PARAM can live in defs.h. > >> + >> +long int reboot_with_param(const char *param) { >> + return syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, >> + LINUX_REBOOT_CMD_RESTART2, param); >> +} >> diff --git a/src/shared/reboot-param.h b/src/shared/reboot-param.h >> new file mode 100644 >> index 0000000..78dcd88 >> --- /dev/null >> +++ b/src/shared/reboot-param.h >> @@ -0,0 +1,28 @@ >> +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ >> + >> +#pragma once >> + >> +/*** >> + This file is part of systemd. >> + >> + Copyright 2013 Samsung Electronics >> + >> + Author: WaLyong Cho <walyong....@samsung.com> >> + >> + systemd is free software; you can redistribute it and/or modify it >> + under the terms of the GNU Lesser General Public License as published by >> + the Free Software Foundation; either version 2.1 of the License, or >> + (at your option) any later version. >> + >> + systemd is distributed in the hope that it will be useful, but >> + WITHOUT ANY WARRANTY; without even the implied warranty of >> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + Lesser General Public License for more details. >> + >> + You should have received a copy of the GNU Lesser General Public License >> + along with systemd; If not, see <http://www.gnu.org/licenses/>. >> +***/ >> + >> +int reboot_set_param(const char *param); >> +int reboot_get_param(char *param, int len); >> +long int reboot_with_param(const char *param); >> diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c >> index 9f5e273..6f5700f 100644 >> --- a/src/systemctl/systemctl.c >> +++ b/src/systemctl/systemctl.c >> @@ -67,6 +67,7 @@ >> #include "path-util.h" >> #include "socket-util.h" >> #include "fileio.h" >> +#include "reboot-param.h" >> >> static char **arg_types = NULL; >> static char **arg_states = NULL; >> @@ -4804,7 +4805,7 @@ static int systemctl_help(void) { >> " emergency Enter system emergency >> mode\n" >> " halt Shut down and halt the >> system\n" >> " poweroff Shut down and power-off >> the system\n" >> - " reboot Shut down and reboot the >> system\n" >> + " reboot [ARG] Shut down and reboot the >> system\n" >> " kexec Shut down and reboot the >> system with kexec\n" >> " exit Request user instance >> exit\n" >> " switch-root [ROOT] [INIT] Change to a different >> root file system\n" >> @@ -4818,7 +4819,7 @@ static int systemctl_help(void) { >> >> static int halt_help(void) { >> >> - printf("%s [OPTIONS...]\n\n" >> + printf("%s [OPTIONS...]%s\n\n" >> "%s the system.\n\n" >> " --help Show this help\n" >> " --halt Halt the machine\n" >> @@ -4829,6 +4830,7 @@ static int halt_help(void) { >> " -d --no-wtmp Don't write wtmp record\n" >> " --no-wall Don't send wall message before >> halt/power-off/reboot\n", >> program_invocation_short_name, >> + arg_action == ACTION_REBOOT ? " [ARG]" : "", >> arg_action == ACTION_REBOOT ? "Reboot" : >> arg_action == ACTION_POWEROFF ? "Power off" : >> "Halt"); >> @@ -5235,6 +5237,9 @@ static int systemctl_parse_argv(int argc, char >> *argv[]) { >> } >> >> static int halt_parse_argv(int argc, char *argv[]) { >> + _cleanup_fclose_ FILE *f = NULL; > Hm, where is f used? > >> + int r; >> + const char *param; >> >> enum { >> ARG_HELP = 0x100, >> @@ -5315,6 +5320,28 @@ static int halt_parse_argv(int argc, char *argv[]) { >> } >> } >> >> + param = argv[optind]; >> + >> + if (param != NULL) { >> + switch(arg_action) { >> + >> + case ACTION_REBOOT: >> + if (argc-optind != 1) >> + log_error("Too many arguments."); >> + else { >> + if ((r = reboot_set_param(param)) < 0) { >> + log_error("Failed to set reboot >> param '%s'.", param); >> + return r; >> + } >> + argc--; >> + } >> + break; >> + >> + default: >> + break; >> + } >> + } >> + >> if (optind < argc) { >> log_error("Too many arguments."); >> return -EINVAL; >> @@ -5953,6 +5980,9 @@ done: >> >> static _noreturn_ void halt_now(enum action a) { >> >> + _cleanup_fclose_ FILE *f = NULL; > Hm, where is f used? > >> + char param[LINE_MAX]; >> + >> /* Make sure C-A-D is handled by the kernel from this >> * point on... */ >> reboot(RB_ENABLE_CAD); >> @@ -5970,8 +6000,13 @@ static _noreturn_ void halt_now(enum action a) { >> break; >> >> case ACTION_REBOOT: >> - log_info("Rebooting."); >> - reboot(RB_AUTOBOOT); >> + if (reboot_get_param(param, sizeof(param)) > 0) { >> + log_info("Rebooting with arg '%s'.", param); >> + reboot_with_param(param); >> + } else { >> + log_info("Rebooting."); >> + reboot(RB_AUTOBOOT); >> + } >> break; >> >> default: > > Zbyszek >
There are some of my mistakes. I updated my patch. Thank you. WaLyong
>From 8d48a724f6b95aca04d7958893997613fb1b570f Mon Sep 17 00:00:00 2001 From: WaLyong Cho <walyong....@samsung.com> Date: Wed, 6 Nov 2013 17:02:41 +0900 Subject: [PATCH] make reboot to support additional command reboot syscall can be performed with additional argument. In some of system, this functionality can be useful to ask next boot mode to bootloader. --- src/core/shutdown.c | 17 ++++++++++++----- src/shared/def.h | 2 ++ src/systemctl/systemctl.c | 41 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/core/shutdown.c b/src/core/shutdown.c index aa9548e..49a0781 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -47,6 +47,7 @@ #include "watchdog.h" #include "killall.h" #include "cgroup-util.h" +#include "def.h" #define FINALIZE_ATTEMPTS 50 @@ -133,8 +134,8 @@ static int pivot_to_new_root(void) { int main(int argc, char *argv[]) { bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true; - bool in_container, use_watchdog = false; - _cleanup_free_ char *line = NULL, *cgroup = NULL; + bool in_container, use_watchdog = false, with_param = false; + _cleanup_free_ char *line = NULL, *cgroup = NULL, *param = NULL; char *arguments[3]; unsigned retries; int cmd, r; @@ -173,9 +174,11 @@ int main(int argc, char *argv[]) { in_container = detect_container(NULL) > 0; - if (streq(argv[1], "reboot")) + if (streq(argv[1], "reboot")) { cmd = RB_AUTOBOOT; - else if (streq(argv[1], "poweroff")) + if (read_one_line_file(REBOOT_PARAM, ¶m) >= 0) + with_param = true; + } else if (streq(argv[1], "poweroff")) cmd = RB_POWER_OFF; else if (streq(argv[1], "halt")) cmd = RB_HALT_SYSTEM; @@ -337,7 +340,11 @@ int main(int argc, char *argv[]) { cmd = RB_AUTOBOOT; } - reboot(cmd); + if (with_param) + syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, param); + else + reboot(cmd); if (errno == EPERM && in_container) { /* If we are in a container, and we lacked diff --git a/src/shared/def.h b/src/shared/def.h index edd0bcf..6929993 100644 --- a/src/shared/def.h +++ b/src/shared/def.h @@ -38,3 +38,5 @@ #define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz" #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS + +#define REBOOT_PARAM "/run/systemd/reboot-param" \ No newline at end of file diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 9f5e273..b58fd73 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -20,6 +20,8 @@ ***/ #include <sys/reboot.h> +#include <linux/reboot.h> +#include <sys/syscall.h> #include <stdio.h> #include <getopt.h> #include <locale.h> @@ -4804,7 +4806,7 @@ static int systemctl_help(void) { " emergency Enter system emergency mode\n" " halt Shut down and halt the system\n" " poweroff Shut down and power-off the system\n" - " reboot Shut down and reboot the system\n" + " reboot [ARG] Shut down and reboot the system\n" " kexec Shut down and reboot the system with kexec\n" " exit Request user instance exit\n" " switch-root [ROOT] [INIT] Change to a different root file system\n" @@ -4818,7 +4820,7 @@ static int systemctl_help(void) { static int halt_help(void) { - printf("%s [OPTIONS...]\n\n" + printf("%s [OPTIONS...]%s\n\n" "%s the system.\n\n" " --help Show this help\n" " --halt Halt the machine\n" @@ -4829,6 +4831,7 @@ static int halt_help(void) { " -d --no-wtmp Don't write wtmp record\n" " --no-wall Don't send wall message before halt/power-off/reboot\n", program_invocation_short_name, + arg_action == ACTION_REBOOT ? " [ARG]" : "", arg_action == ACTION_REBOOT ? "Reboot" : arg_action == ACTION_POWEROFF ? "Power off" : "Halt"); @@ -5235,6 +5238,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) { } static int halt_parse_argv(int argc, char *argv[]) { + int r; + const char *param; enum { ARG_HELP = 0x100, @@ -5315,6 +5320,26 @@ static int halt_parse_argv(int argc, char *argv[]) { } } + param = argv[optind]; + + if (param != NULL) { + switch(arg_action) { + + case ACTION_REBOOT: + if (argc-optind == 1) { + if ((r = write_string_file(REBOOT_PARAM, param)) < 0) { + log_error("Failed to set reboot param '%s'.", param); + return r; + } + argc--; + } + break; + + default: + break; + } + } + if (optind < argc) { log_error("Too many arguments."); return -EINVAL; @@ -5953,6 +5978,8 @@ done: static _noreturn_ void halt_now(enum action a) { + _cleanup_free_ char *param = NULL; + /* Make sure C-A-D is handled by the kernel from this * point on... */ reboot(RB_ENABLE_CAD); @@ -5970,8 +5997,14 @@ static _noreturn_ void halt_now(enum action a) { break; case ACTION_REBOOT: - log_info("Rebooting."); - reboot(RB_AUTOBOOT); + if (read_one_line_file(REBOOT_PARAM, ¶m) == 0) { + log_info("Rebooting with arg '%s'.", param); + syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, param); + } else { + log_info("Rebooting."); + reboot(RB_AUTOBOOT); + } break; default: -- 1.7.9.5
_______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel