From: Lennart Poettering Date: Wed, 21 Feb 2018 17:48:49 +0000 (+0100) Subject: reboot-util: unify reboot with parameter in a single implementation X-Git-Tag: v238~71^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c01dcddf803a009dd9118dee0873cb9dd1dd02ce;p=thirdparty%2Fsystemd.git reboot-util: unify reboot with parameter in a single implementation So far, we had two implementations of reboot-with-parameter doing pretty much the same. Let's unify that in a generic implementation used by both. This is particulary nice as it unifies all /run/systemd/reboot-param handling in a single .c file. --- diff --git a/src/basic/reboot-util.c b/src/basic/reboot-util.c index 68910a6a34e..ca40159b966 100644 --- a/src/basic/reboot-util.c +++ b/src/basic/reboot-util.c @@ -3,11 +3,14 @@ #include #include +#include "alloc-util.h" #include "fileio.h" #include "log.h" +#include "raw-reboot.h" #include "reboot-util.h" #include "string-util.h" #include "umask-util.h" +#include "virt.h" int update_reboot_parameter_and_warn(const char *parameter) { int r; @@ -32,3 +35,49 @@ int update_reboot_parameter_and_warn(const char *parameter) { return 0; } + +int reboot_with_parameter(RebootFlags flags) { + int r; + + /* Reboots the system with a parameter that is read from /run/systemd/reboot-param. Returns 0 if REBOOT_DRY_RUN + * was set and the actual reboot operation was hence skipped. If REBOOT_FALLBACK is set and the reboot with + * parameter doesn't work out a fallback to classic reboot() is attempted. If REBOOT_FALLBACK is not set, 0 is + * returned instead, which should be considered indication for the caller to fall back to reboot() on its own, + * or somehow else deal with this. If REBOOT_LOG is specified will log about what it is going to do, as well as + * all errors. */ + + if (detect_container() == 0) { + _cleanup_free_ char *parameter = NULL; + + r = read_one_line_file("/run/systemd/reboot-param", ¶meter); + if (r < 0 && r != -ENOENT) + log_full_errno(flags & REBOOT_LOG ? LOG_WARNING : LOG_DEBUG, r, + "Failed to read reboot parameter file, ignoring: %m"); + + if (!isempty(parameter)) { + + log_full(flags & REBOOT_LOG ? LOG_INFO : LOG_DEBUG, + "Rebooting with argument '%s'.", parameter); + + if (flags & REBOOT_DRY_RUN) + return 0; + + (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, parameter); + + log_full_errno(flags & REBOOT_LOG ? LOG_WARNING : LOG_DEBUG, errno, + "Failed to reboot with parameter, retrying without: %m"); + } + } + + if (!(flags & REBOOT_FALLBACK)) + return 0; + + log_full(flags & REBOOT_LOG ? LOG_INFO : LOG_DEBUG, "Rebooting."); + + if (flags & REBOOT_DRY_RUN) + return 0; + + (void) reboot(RB_AUTOBOOT); + + return log_full_errno(flags & REBOOT_LOG ? LOG_ERR : LOG_DEBUG, errno, "Failed to reboot: %m"); +} diff --git a/src/basic/reboot-util.h b/src/basic/reboot-util.h index 6f1d24c1f5e..d4aa4412906 100644 --- a/src/basic/reboot-util.h +++ b/src/basic/reboot-util.h @@ -2,3 +2,11 @@ #pragma once int update_reboot_parameter_and_warn(const char *parameter); + +typedef enum RebootFlags { + REBOOT_LOG = 1U << 0, /* log about what we are going to do and all errors */ + REBOOT_DRY_RUN = 1U << 1, /* return 0 right before actually doing the reboot */ + REBOOT_FALLBACK = 1U << 2, /* fallback to plain reboot() if argument-based reboot doesn't work, isn't configured or doesn't apply otherwise */ +} RebootFlags; + +int reboot_with_parameter(RebootFlags flags); diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 33751c5ff55..de689aea311 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -41,7 +42,7 @@ #include "missing.h" #include "parse-util.h" #include "process-util.h" -#include "raw-reboot.h" +#include "reboot-util.h" #include "signal-util.h" #include "string-util.h" #include "switch-root.h" @@ -517,22 +518,9 @@ int main(int argc, char *argv[]) { cmd = RB_AUTOBOOT; _fallthrough_; - case RB_AUTOBOOT: - - if (!in_container) { - _cleanup_free_ char *param = NULL; - - r = read_one_line_file("/run/systemd/reboot-param", ¶m); - if (r < 0 && r != -ENOENT) - log_warning_errno(r, "Failed to read reboot parameter file: %m"); - - if (!isempty(param)) { - log_info("Rebooting with argument '%s'.", param); - (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, param); - log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m"); - } - } + case RB_AUTOBOOT: + (void) reboot_with_parameter(REBOOT_LOG); log_info("Rebooting."); break; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 0d3d0d0daa5..6eec0171c6b 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -72,7 +72,6 @@ #include "path-lookup.h" #include "path-util.h" #include "process-util.h" -#include "raw-reboot.h" #include "reboot-util.h" #include "rlimit-util.h" #include "set.h" @@ -8473,11 +8472,9 @@ static int start_with_fallback(void) { } static int halt_now(enum action a) { - int r; - /* The kernel will automaticall flush ATA disks and suchlike - * on reboot(), but the file systems need to be synce'd - * explicitly in advance. */ + /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be + * synce'd explicitly in advance. */ if (!arg_no_sync && !arg_dry_run) (void) sync(); @@ -8504,29 +8501,10 @@ static int halt_now(enum action a) { return -errno; case ACTION_KEXEC: - case ACTION_REBOOT: { - _cleanup_free_ char *param = NULL; - - r = read_one_line_file("/run/systemd/reboot-param", ¶m); - if (r < 0 && r != -ENOENT) - log_warning_errno(r, "Failed to read reboot parameter file: %m"); - - if (!isempty(param)) { - if (!arg_quiet) - log_info("Rebooting with argument '%s'.", param); - if (!arg_dry_run) { - (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, param); - log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m"); - } - } - - if (!arg_quiet) - log_info("Rebooting."); - if (arg_dry_run) - return 0; - (void) reboot(RB_AUTOBOOT); - return -errno; - } + case ACTION_REBOOT: + return reboot_with_parameter(REBOOT_FALLBACK | + (arg_quiet ? 0 : REBOOT_LOG) | + (arg_dry_run ? REBOOT_DRY_RUN : 0)); default: assert_not_reached("Unknown action.");