Blob Blame History Raw
From 0f4ea4aee6e404dfbd6e3c4bbfb4f805e4e257f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 19 Jan 2022 12:20:22 +0100
Subject: [PATCH] kernel-install: add "$KERNEL_INSTALL_STAGING_AREA" directory

The general approach of kernel-install was that each plugin would drop in some
files into the entry directory. But this doesn't scale well, because if we have
multiple initrd generators, or multiple initrds, each generator would need to
recreate the logic to put the generated files in the right place.

Also, effective cleanup is impossible if anything goes wrong on the way, so we
could end up with unused files in $BOOT.

So let's invert the process: plugins drop files into $KERNEL_INSTALL_STAGING_AREA,
and at the end 90-loaderentry.install DTRT with those files.

This allow new plugins like 50-mkosi-initrd.install to be significantly simpler.

(cherry picked from commit 367165a4069ac0c04882a05a8a80f6afb1e42760)

Related: #2065061
---
 man/kernel-install.xml                    |  4 ++++
 src/kernel-install/90-loaderentry.install | 13 ++++++++++---
 src/kernel-install/kernel-install         | 10 ++++++++++
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/man/kernel-install.xml b/man/kernel-install.xml
index bb76074d2e..685617863e 100644
--- a/man/kernel-install.xml
+++ b/man/kernel-install.xml
@@ -180,6 +180,10 @@
     This should be configured as <varname>initrd_generator=</varname> in <filename>install.conf</filename>.
     </para>
 
+    <para><varname>KERNEL_INSTALL_STAGING_AREA=...</varname> is set for plugins to a path to a directory.
+    Plugins may drop files in that directory, and they will be installed as part of the loader entry, based
+    on the file name and extension.</para>
+
     <variablelist>
       <varlistentry>
         <term>bls</term>
diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install
index 6a396910cb..0888c260e2 100644
--- a/src/kernel-install/90-loaderentry.install
+++ b/src/kernel-install/90-loaderentry.install
@@ -18,6 +18,8 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with systemd; If not, see <http://www.gnu.org/licenses/>.
 
+shopt -s nullglob
+
 COMMAND="$1"
 KERNEL_VERSION="$2"
 ENTRY_DIR_ABS="$3"
@@ -88,7 +90,8 @@ install -g root -o root -m 0644 "$KERNEL_IMAGE" "$ENTRY_DIR_ABS/linux" || {
 }
 
 shift "$INITRD_OPTIONS_SHIFT"
-for initrd; do
+# All files listed as arguments, and staged files called "initrd*" are installed as initrds.
+for initrd in "$@" "${KERNEL_INSTALL_STAGING_AREA}"/initrd*; do
     [ -f "$initrd" ] || {
         echo "Error: initrd '$initrd' not a file." >&2
         exit 1
@@ -114,11 +117,15 @@ mkdir -p "${LOADER_ENTRY%/*}" || {
     echo "machine-id $MACHINE_ID"
     echo "options    $BOOT_OPTIONS"
     echo "linux      $ENTRY_DIR/linux"
-    for initrd; do
+
+    have_initrd=
+    for initrd in "${@}" "${KERNEL_INSTALL_STAGING_AREA}"/initrd*; do
         echo "initrd     $ENTRY_DIR/${initrd##*/}"
+        have_initrd=yes
     done
+
     # Try "initrd", generated by dracut in its kernel-install hook, if no initrds were supplied
-    [ $# -eq 0 ] && [ -f "$ENTRY_DIR_ABS/initrd" ] && echo "initrd     $ENTRY_DIR/initrd"
+    [ -z "$have_initrd" ] && [ -f "$ENTRY_DIR_ABS/initrd" ] && echo "initrd     $ENTRY_DIR/initrd"
     :
 } >"$LOADER_ENTRY" || {
     echo "Error: could not create loader entry '$LOADER_ENTRY'." >&2
diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install
index a73a205d79..8cfef3208d 100755
--- a/src/kernel-install/kernel-install
+++ b/src/kernel-install/kernel-install
@@ -128,10 +128,20 @@ fi
 
 ENTRY_DIR_ABS="$BOOT_ROOT/$MACHINE_ID/$KERNEL_VERSION"
 
+# Provide a directory where to store generated initrds
+cleanup() {
+    [ -n "$KERNEL_INSTALL_STAGING_AREA" ] && rm -rf "$KERNEL_INSTALL_STAGING_AREA"
+}
+
+trap cleanup EXIT
+
+KERNEL_INSTALL_STAGING_AREA="$(mktemp -d -t -p /tmp kernel-install.staging.XXXXXXX)"
+
 export KERNEL_INSTALL_MACHINE_ID="$MACHINE_ID"
 export KERNEL_INSTALL_BOOT_ROOT="$BOOT_ROOT"
 export KERNEL_INSTALL_LAYOUT="$layout"
 export KERNEL_INSTALL_INITRD_GENERATOR="$initrd_generator"
+export KERNEL_INSTALL_STAGING_AREA
 
 [ "$layout" = "bls" ]
 MAKE_ENTRY_DIR_ABS=$?