From 3e39d4e24b05bea7d679514728543fddf0ef69fb Mon Sep 17 00:00:00 2001 From: Alexey Gladkov Date: Thu, 16 Dec 2021 22:37:56 +0300 Subject: GENTOO: halt: do kexec instead of reboot if another kernel is loaded Link: https://gitweb.gentoo.org/repo/gentoo.git/tree/sys-apps/sysvinit/files/sysvinit-2.86-kexec.patch --- man/halt.8 | 3 +++ src/halt.c | 43 ++++++++++++++++++++++++++++++++++++++----- src/reboot.h | 3 +++ 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/man/halt.8 b/man/halt.8 index dc431f9..65a30cb 100644 --- a/man/halt.8 +++ b/man/halt.8 @@ -40,6 +40,7 @@ halt, reboot, poweroff \- stop the system. .RB [ \-d ] .RB [ \-f ] .RB [ \-i ] +.RB [ \-k ] .br .B /sbin/poweroff .RB [ \-n ] @@ -85,6 +86,8 @@ Put all hard drives on the system in stand-by mode just before halt or power-off .IP \fB\-p\fP When halting the system, switch off the power. This is the default when halt is called as \fBpoweroff\fP. +.IP \fB\-k\fP +Try to reboot using \fBkexec\fP, if kernel supports it. .\"}}} .\"{{{ Diagnostics .SH DIAGNOSTICS diff --git a/src/halt.c b/src/halt.c index 6e5f485..3b70573 100644 --- a/src/halt.c +++ b/src/halt.c @@ -8,7 +8,7 @@ * execute an "shutdown -r". This is for compatibility with * sysvinit 2.4. * - * Usage: halt [-n] [-w] [-d] [-f] [-h] [-i] [-p] + * Usage: halt [-n] [-w] [-d] [-f] [-h] [-i] [-p] [-k] * -n: don't sync before halting the system * -w: only write a wtmp reboot record and exit. * -d: don't write a wtmp record. @@ -16,6 +16,7 @@ * -h: put harddisks in standby mode * -i: shut down all network interfaces. * -p: power down the system (if possible, otherwise halt). + * -k: reboot the system using kexec. * * Reboot and halt are both this program. Reboot * is just a link to halt. Invoking the program @@ -77,8 +78,10 @@ extern void write_wtmp(char *user, char *id, int pid, int type, char *line); __attribute__((noreturn)) void usage(void) { - fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s\n", - progname, strcmp(progname, "halt") ? "" : " [-p]"); + fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s%s\n", + progname, + strcmp(progname, "halt") ? "" : " [-p]", + strcmp(progname, "reboot") ? "" : " [-k]"); fprintf(stderr, "\t-n: don't sync before halting the system\n"); fprintf(stderr, "\t-w: only write a wtmp reboot record and exit.\n"); fprintf(stderr, "\t-d: don't write a wtmp record.\n"); @@ -87,6 +90,8 @@ void usage(void) fprintf(stderr, "\t-i: shut down all network interfaces.\n"); if (!strcmp(progname, "halt")) fprintf(stderr, "\t-p: power down the system (if possible, otherwise halt).\n"); + if (!strcmp(progname, "reboot")) + fprintf(stderr, "\t-k: reboot the system using kexec.\n"); exit(1); } @@ -195,6 +200,7 @@ int main(int argc, char **argv) int do_ifdown = 0; int do_hddown = 0; int do_poweroff = 0; + int do_kexec = 0; int c; char *tm = NULL; @@ -211,7 +217,7 @@ int main(int argc, char **argv) /* * Get flags */ - while((c = getopt(argc, argv, ":ihdfnpwt:")) != EOF) { + while((c = getopt(argc, argv, ":ihdfnpwkt:")) != EOF) { switch(c) { case 'n': do_sync = 0; @@ -236,6 +242,9 @@ int main(int argc, char **argv) if (do_reboot) usage(); do_poweroff = 1; break; + case 'k': + do_kexec = 1; + break; case 't': tm = optarg; break; @@ -256,10 +265,24 @@ int main(int argc, char **argv) } if (!do_hard && !do_nothing) { + c = get_runlevel(); + + /* + * We can't reboot using kexec through this path. + */ + if (c != '6' && do_reboot && do_kexec) { + fprintf(stderr, "ERROR: using -k at this" + " runlevel requires also -f\n" + " (You probably want instead to reboot" + " normally and let your reboot\n" + " script, usually /etc/init.d/reboot," + " specify -k)\n"); + exit(1); + } + /* * See if we are in runlevel 0 or 6. */ - c = get_runlevel(); if (c != '0' && c != '6') do_shutdown(do_reboot ? "-r" : "-h", do_poweroff, tm, do_poweroff ? "-P" : (do_reboot ? NULL : "-H")); @@ -296,6 +319,16 @@ int main(int argc, char **argv) if (do_nothing) exit(0); if (do_reboot) { + /* + * kexec or reboot + */ + if (do_kexec) { + init_reboot(BMAGIC_KEXEC); + } + + /* + * Fall through if failed + */ init_reboot(BMAGIC_REBOOT); } else { /* diff --git a/src/reboot.h b/src/reboot.h index c7807ca..d2c73b6 100644 --- a/src/reboot.h +++ b/src/reboot.h @@ -47,5 +47,8 @@ # define BMAGIC_POWEROFF BMAGIC_HALT #endif +/* for kexec support */ +#define BMAGIC_KEXEC 0x45584543 + #define init_reboot(magic) reboot(magic) -- 2.25.4