Subject: bug#73992: closed (Re: bug#73992: [Shepherd PATCH] shepherd: Add support for rebooting using kexec)

From: [email-masked] (GNU bug Tracking System)
Date: Sun, 03 Nov 2024 14:47:02 +0000

Your bug report

#73992: [Shepherd PATCH] shepherd: Add support for rebooting using kexec

which was filed against the guix-patches package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
73992: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=73992
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#73992: [Shepherd PATCH] shepherd: Add support for rebooting using kexec
From: Ludovic Courtès <[email-masked]>
To: Jakob Kirsch <[email-masked]>
Cc: [email-masked]
Date: Sun, 03 Nov 2024 15:46:10 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

Hi Jakob,

Jakob Kirsch <[email-masked]> skribis:

> From 762fbee53fb890a7cf5e26abcc2dcfad03b1bab4 Mon Sep 17 00:00:00 2001
> From: Jakob Kirsch <[email-masked]>
> Date: Thu, 24 Oct 2024 19:45:31 +0200
> Subject: [PATCH v3] shepherd: Add support for rebooting using kexec
>
> ---
>  AUTHORS                             |  1 +
>  configure.ac                        |  4 ++++
>  doc/shepherd.texi                   |  9 +++++++++
>  modules/shepherd/scripts/reboot.scm | 12 ++++++++++--
>  modules/shepherd/service.scm        |  9 +++++++++
>  modules/shepherd/system.scm.in      | 10 ++++++++++
>  tests/status-sexp.sh                |  2 +-
>  7 files changed, 44 insertions(+), 3 deletions(-)

I applied it to the ‘devel’ branch after making the cosmetic changes
below (let me know if anything is amiss).  I also added a commit log
that follows the project’s conventions.

Thank you!

Ludo’.

diff --git a/doc/shepherd.texi b/doc/shepherd.texi
index faef6f1..b164fe8 100644
--- a/doc/shepherd.texi
+++ b/doc/shepherd.texi
@@ -516,12 +516,15 @@ Send commands to the socket special file @var{file}. If this option is
 not specified, @file{@var{localstatedir}/run/shepherd/socket} is taken.
 
 @item -k
-@itemx --do-kexec
-Reboot the system using kexec. The kernel that was previously loaded
-using @command{kexec -l @var{file}} is executed instead of rebooting
-into the BIOS in order to keep the down time to a minimum or to chainload
-another kernel. This feature is only available on Linux-based systems and will
-throw an exception on GNU/Hurd. This is also equivalent to running @command{herd kexec shepherd}.
+@itemx --kexec
+Reboot the system using Linux's kexec (this is equivalent to running
+@command{herd kexec root}).  The kernel that was previously loaded using
+the @command{kexec -l @var{file}} command is executed directly instead
+of rebooting into the BIOS, keeping the downtime to a minimum.  See the
+@uref{https://linux.die.net/man/8/kexec, @command{kexec} command
+documentation} for more information.
+
+This feature is only available on Linux-based systems.
 
 @end table
 
diff --git a/modules/shepherd/scripts/reboot.scm b/modules/shepherd/scripts/reboot.scm
index 4c2448e..0f3fc30 100644
--- a/modules/shepherd/scripts/reboot.scm
+++ b/modules/shepherd/scripts/reboot.scm
@@ -1,5 +1,6 @@
 ;; reboot.scm -- Reboot the system.
 ;; Copyright (C) 2013, 2014, 2015, 2016, 2018, 2023 Ludovic Courtès <[email-masked]>
+;; Copyright (C) 2024 Jakob Kirsch <[email-masked]>
 ;;
 ;; This file is part of the GNU Shepherd.
 ;;
@@ -48,11 +49,11 @@
                       #:action (lambda (file)
                                  (set! socket-file file)))
                     (option
-                      #:long-name "do-kexec" #:short-name #\k
+                      #:long-name "kexec" #:short-name #\k
                       #:takes-argument? #f
                       #:description "reboot using kexec"
-                      #:action (lambda () (set! action 'kexec))
-                    ))
+                      #:action (lambda ()
+                                 (set! action 'kexec))))
 
       (set! command-args (reverse command-args))
       (with-system-error-handling
diff --git a/modules/shepherd/service.scm b/modules/shepherd/service.scm
index 6a5e112..08a9df2 100644
--- a/modules/shepherd/service.scm
+++ b/modules/shepherd/service.scm
@@ -2709,13 +2709,14 @@ Clients such as 'herd' can read it and format it in a human-readable way."
             (power-off)))))
 
      (kexec
-       "Reboot the system and run kexec."
-       (lambda (running)
+      "Reboot the system and run kexec."
+      (lambda (running)
         (catch 'quit
-          (cut stop root-service)
+          (cut stop-service root-service)
           (lambda (key)
             (local-output (l10n "Rebooting with kexec..."))
             (reboot-kexec)))))
+
      ;; Evaluate arbitrary code.
      (load
       "Load the Scheme code from FILE into shepherd.  This is potentially
diff --git a/modules/shepherd/system.scm.in b/modules/shepherd/system.scm.in
index 1168c15..46f1848 100644
--- a/modules/shepherd/system.scm.in
+++ b/modules/shepherd/system.scm.in
@@ -2,6 +2,7 @@
 ;; Copyright (C) 2013-2014, 2016, 2018, 2020, 2022-2024 Ludovic Courtès <[email-masked]>
 ;; Copyright (C) 2018 Carlo Zancanaro <[email-masked]>
 ;; Copyright (C) 2020 Jan (janneke) Nieuwenhuizen <[email-masked]>
+;; Copyright (C) 2024 Jakob Kirsch <[email-masked]>
 ;;
 ;; This file is part of the GNU Shepherd.
 ;;
@@ -98,12 +99,13 @@ ctrlaltdel(8) and see kernel/reboot.c in Linux."
   (%libc-reboot RB_AUTOBOOT))
 
 (define (reboot-kexec)
-  "Execute kernel loaded with 'kexec -l' now. Kexec is a feature of the
+  "Execute kernel loaded with 'kexec -l' now.  Kexec is a feature of the
 Linux kernel that allows you to instantly reboot into a new kernel while skipping
 the BIOS phase.  Return #f on failure or throw an exception on non-Linux systems."
   (if RB_KEXEC
-    (%libc-reboot RB_KEXEC)
-    (throw 'system-error 'kexec  "~A" (list (strerror ENOSYS)) (list ENOSYS))))
+      (%libc-reboot RB_KEXEC)
+      (throw 'system-error 'kexec  "~A" (list (strerror ENOSYS))
+             (list ENOSYS))))
 
 (define (halt)
   "Halt the system.  Return #f on failure."

Subject: [Shepherd PATCH] shepherd: Add support for rebooting using kexec
From: Jakob Kirsch <[email-masked]>
To: [email-masked]
Date: Thu, 24 Oct 2024 20:04:14 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

This is my improved patch for using kexec with shepherd as I sent the last one to the wrong address (someone should update the description of the shepherd project to link to the correct patch submission list).
From 762fbee53fb890a7cf5e26abcc2dcfad03b1bab4 Mon Sep 17 00:00:00 2001
From: Jakob Kirsch <[email-masked]>
Date: Thu, 24 Oct 2024 19:45:31 +0200
Subject: [PATCH v3] shepherd: Add support for rebooting using kexec

---
 AUTHORS                             |  1 +
 configure.ac                        |  4 ++++
 doc/shepherd.texi                   |  9 +++++++++
 modules/shepherd/scripts/reboot.scm | 12 ++++++++++--
 modules/shepherd/service.scm        |  9 +++++++++
 modules/shepherd/system.scm.in      | 10 ++++++++++
 tests/status-sexp.sh                |  2 +-
 7 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 19132a7..6642bdc 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -10,3 +10,4 @@ when it was known as GNU dmd.  Others have since contributed:
              Alex Sassmannshausen <[email-masked]>
             David Thompson <[email-masked]>
              Andy Wingo <[email-masked]>
+            Jakob Kirsch <[email-masked]>
diff --git a/configure.ac b/configure.ac
index bcfef13..db1dc95 100644
--- a/configure.ac
+++ b/configure.ac
@@ -124,6 +124,7 @@ case "$host_os" in
     AC_COMPUTE_INT([RB_DISABLE_CAD], [RB_DISABLE_CAD], [#include <sys/reboot.h>])
     AC_COMPUTE_INT([RB_POWER_OFF], [RB_POWER_OFF], [#include <sys/reboot.h>])
     AC_COMPUTE_INT([RB_SW_SUSPEND], [RB_SW_SUSPEND], [#include <sys/reboot.h>])
+    AC_COMPUTE_INT([RB_KEXEC], [RB_KEXEC], [#include <sys/reboot.h>])
     ;;
   gnu*)
     # On GNU/Hurd, the Mach-derived reboot.h uses different names, and
@@ -131,6 +132,7 @@ case "$host_os" in
     AC_COMPUTE_INT([RB_HALT_SYSTEM], [RB_HALT], [#include <sys/reboot.h>])
     AC_COMPUTE_INT([RB_POWER_OFF], [RB_HALT], [#include <sys/reboot.h>])
     RB_DISABLE_CAD="#f"
+    RB_KEXEC="#f"
     ;;
   *)
     # What is this?  GNU/kFreeBSD?
@@ -138,6 +140,7 @@ case "$host_os" in
     AC_COMPUTE_INT([RB_HALT_SYSTEM], [RB_HALT_SYSTEM], [#include <sys/reboot.h>])
     AC_COMPUTE_INT([RB_POWER_OFF], [RB_HALT_SYSTEM], [#include <sys/reboot.h>])
     RB_DISABLE_CAD="#f"
+    RB_KEXEC="#f"
     ;;
 esac

@@ -145,6 +148,7 @@ AC_SUBST([RB_DISABLE_CAD])
 AC_SUBST([RB_AUTOBOOT])
 AC_SUBST([RB_HALT_SYSTEM])
 AC_SUBST([RB_POWER_OFF])
+AC_SUBST([RB_KEXEC])
 AC_MSG_RESULT([done])

 AC_MSG_CHECKING([<sys/prctl.h> constants])
diff --git a/doc/shepherd.texi b/doc/shepherd.texi
index 0e627b3..921bf40 100644
--- a/doc/shepherd.texi
+++ b/doc/shepherd.texi
@@ -14,6 +14,7 @@ Copyright @copyright{} @value{NEW-YEARS} Ludovic Courtès@*
 Copyright @copyright{} 2020 Brice Waegeneire@*
 Copyright @copyright{} 2020 Oleg Pykhalov@*
 Copyright @copyright{} 2020, 2023 Jan (janneke) Nieuwenhuizen@*
+Copyright @copyright{} 2024 Jakob Kirsch@*

 Permission is granted to copy, distribute and/or modify this document
 under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -600,6 +601,14 @@ It is equivalent to running @command{herd stop shepherd}.  The
 Send commands to the socket special file @var{file}. If this option is
 not specified, @file{@var{localstatedir}/run/shepherd/socket} is taken.

+@item -k
+@itemx --do-kexec
+Reboot the system using kexec. The kernel that was previously loaded
+using @command{kexec -l @var{file}} is executed instead of rebooting
+into the BIOS in order to keep the down time to a minimum or to chainload
+another kernel. This feature is only available on Linux-based systems and will
+throw an exception on GNU/Hurd. This is also equivalent to running @command{herd kexec shepherd}.
+
 @end table

 @c @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
diff --git a/modules/shepherd/scripts/reboot.scm b/modules/shepherd/scripts/reboot.scm
index 6be5414..4c2448e 100644
--- a/modules/shepherd/scripts/reboot.scm
+++ b/modules/shepherd/scripts/reboot.scm
@@ -30,6 +30,8 @@
 (define (main . args)
   (initialize-cli)

+  (define action 'stop)
+
   (parameterize ((program-name "reboot"))
     (let ((socket-file %system-socket-file)
           (command-args '()))
@@ -44,13 +46,19 @@
                       #:argument-name "FILE"
                       #:description "send commands to FILE"
                       #:action (lambda (file)
-                                 (set! socket-file file))))
+                                 (set! socket-file file)))
+                    (option
+                      #:long-name "do-kexec" #:short-name #\k
+                      #:takes-argument? #f
+                      #:description "reboot using kexec"
+                      #:action (lambda () (set! action 'kexec))
+                    ))

       (set! command-args (reverse command-args))
       (with-system-error-handling
        (let ((sock (open-connection socket-file)))
          ;; Send the command without further ado.
-         (write-command (shepherd-command 'stop 'root) sock)
+         (write-command (shepherd-command action 'root) sock)

          ;; Receive output if we're not already dead.
          (match (read sock)
diff --git a/modules/shepherd/service.scm b/modules/shepherd/service.scm
index 5942b0a..6a5e112 100644
--- a/modules/shepherd/service.scm
+++ b/modules/shepherd/service.scm
@@ -2707,6 +2707,15 @@ Clients such as 'herd' can read it and format it in a human-readable way."
           (lambda (key)
             (local-output (l10n "Shutting down..."))
             (power-off)))))
+
+     (kexec
+       "Reboot the system and run kexec."
+       (lambda (running)
+        (catch 'quit
+          (cut stop root-service)
+          (lambda (key)
+            (local-output (l10n "Rebooting with kexec..."))
+            (reboot-kexec)))))
      ;; Evaluate arbitrary code.
      (load
       "Load the Scheme code from FILE into shepherd.  This is potentially
diff --git a/modules/shepherd/system.scm.in b/modules/shepherd/system.scm.in
index 4c83175..1168c15 100644
--- a/modules/shepherd/system.scm.in
+++ b/modules/shepherd/system.scm.in
@@ -26,6 +26,7 @@
   #:use-module (srfi srfi-26)
   #:export (disable-reboot-on-ctrl-alt-del
             reboot
+            reboot-kexec
             halt
             power-off
             max-file-descriptors
@@ -51,6 +52,7 @@
 (define RB_HALT_SYSTEM @RB_HALT_SYSTEM@)
 (define RB_POWER_OFF @RB_POWER_OFF@)
 (define RB_DISABLE_CAD @RB_DISABLE_CAD@)          ; integer | #f
+(define RB_KEXEC @RB_KEXEC@)                      ; integer | #f

 (define (syscall->procedure return-type name argument-types)
   "Return a procedure that wraps the C function NAME using the dynamic FFI,
@@ -95,6 +97,14 @@ ctrlaltdel(8) and see kernel/reboot.c in Linux."
   "Perform a hard reset of the system now.  Return #f on failure."
   (%libc-reboot RB_AUTOBOOT))

+(define (reboot-kexec)
+  "Execute kernel loaded with 'kexec -l' now. Kexec is a feature of the
+Linux kernel that allows you to instantly reboot into a new kernel while skipping
+the BIOS phase.  Return #f on failure or throw an exception on non-Linux systems."
+  (if RB_KEXEC
+    (%libc-reboot RB_KEXEC)
+    (throw 'system-error 'kexec  "~A" (list (strerror ENOSYS)) (list ENOSYS))))
+
 (define (halt)
   "Halt the system.  Return #f on failure."
   (%libc-reboot RB_HALT_SYSTEM))
diff --git a/tests/status-sexp.sh b/tests/status-sexp.sh
index 14b1e72..3fa0283 100644
--- a/tests/status-sexp.sh
+++ b/tests/status-sexp.sh
@@ -91,7 +91,7 @@ root_service_sexp="
       (transient? #f)
       (respawn-limit (5 . 7))
       (respawn-delay 0.1)
-      (actions (help status halt power-off load eval unload reload daemonize restart))
+      (actions (help status halt power-off kexec load eval unload reload daemonize restart))
       (exit-statuses ())
       (recent-messages ())
       (log-files (\"$PWD/$log\"))
--
2.46.0