28ab1c
From 5e4bc6e2d6b6829c45f4e25cce4d81661b798587 Mon Sep 17 00:00:00 2001
28ab1c
From: Lukas Nykryn <lnykryn@redhat.com>
28ab1c
Date: Thu, 29 Jul 2021 15:16:39 +0200
28ab1c
Subject: [PATCH] refactor(squash): structure in a cleaner way
28ab1c
28ab1c
Simplify the squash mount layout. Instead of overlay on each top
28ab1c
directory (/etc, /usr), just mount and switch_root into the squash
28ab1c
image, with a overlay on top of it.
28ab1c
28ab1c
Also install the binaries and setup scripts separately, so the squash
28ab1c
setup code and the squash image content is independent of each other,
28ab1c
all squash setup script and binaries can be deleted safely upon
28ab1c
switch_root.
28ab1c
28ab1c
With this change, previous squash clean up service and other tricky
28ab1c
implementations are all gone.
28ab1c
28ab1c
This commit depends on systemd commits from:
28ab1c
https://github.com/systemd/systemd/pull/18124
28ab1c
28ab1c
Previouly systemd doesn't recognize non-ramfs initramfs, now this is
28ab1c
doable with SYSTEMD_IN_INITRD=lenient
28ab1c
28ab1c
Signed-off-by: Kairui Song <kasong@redhat.com>
28ab1c
(cherry picked from commit 8f7c332e488f88e5845a3c7954af7934c2f1e37b)
28ab1c
28ab1c
Cherry-picked from: 8f7c332e
28ab1c
Resolves: #1959336
28ab1c
---
28ab1c
 dracut-initramfs-restore.sh                 |  4 +-
28ab1c
 dracut.sh                                   |  4 +-
28ab1c
 lsinitrd.sh                                 |  6 +--
28ab1c
 modules.d/99squash/clear-squash.sh          |  6 ---
28ab1c
 modules.d/99squash/init-squash.sh           | 70 ++++++++---------------------
28ab1c
 modules.d/99squash/module-setup.sh          | 56 ++++++++---------------
28ab1c
 modules.d/99squash/squash-mnt-clear.service | 17 -------
28ab1c
 7 files changed, 44 insertions(+), 119 deletions(-)
28ab1c
28ab1c
diff --git a/dracut-initramfs-restore.sh b/dracut-initramfs-restore.sh
28ab1c
index 67fc88fa..74a952c4 100644
28ab1c
--- a/dracut-initramfs-restore.sh
28ab1c
+++ b/dracut-initramfs-restore.sh
28ab1c
@@ -41,9 +41,9 @@ else
28ab1c
 fi
28ab1c
 
28ab1c
 if [[ -d squash ]]; then
28ab1c
-    unsquashfs -no-xattrs -f -d . squash/root.img >/dev/null
28ab1c
+    unsquashfs -no-xattrs -f -d . squash-root.img >/dev/null
28ab1c
     if [ $? -ne 0 ]; then
28ab1c
-        echo "Squash module is enabled for this initramfs but failed to unpack squash/root.img" >&2
28ab1c
+        echo "Squash module is enabled for this initramfs but failed to unpack squash-root.img" >&2
28ab1c
         rm -f -- /run/initramfs/shutdown
28ab1c
         exit 1
28ab1c
     fi
28ab1c
diff --git a/dracut.sh b/dracut.sh
28ab1c
index 1168fc16..b403f401 100755
28ab1c
--- a/dracut.sh
28ab1c
+++ b/dracut.sh
28ab1c
@@ -1758,8 +1758,8 @@ fi
28ab1c
 
28ab1c
 if dracut_module_included "squash"; then
28ab1c
     readonly squash_dir="$initdir/squash/root"
28ab1c
-    readonly squash_img="$initdir/squash/root.img"
28ab1c
-
28ab1c
+    readonly squash_img="$initdir/squash-root.img"
28ab1c
+    mkdir -p "$squash_dir"
28ab1c
     dinfo "*** Install squash loader ***"
28ab1c
     DRACUT_SQUASH_POST_INST=1 module_install "squash"
28ab1c
 fi
28ab1c
diff --git a/lsinitrd.sh b/lsinitrd.sh
28ab1c
index 0b42b9a4..04ce9e8b 100755
28ab1c
--- a/lsinitrd.sh
28ab1c
+++ b/lsinitrd.sh
28ab1c
@@ -162,9 +162,9 @@ list_files()
28ab1c
 
28ab1c
 list_squash_content()
28ab1c
 {
28ab1c
-    SQUASH_IMG="squash/root.img"
28ab1c
-    SQUASH_TMPFILE="$(mktemp -t --suffix=.root.sqsh lsinitrd.XXXXXX)"
28ab1c
-    trap "rm -f '$SQUASH_TMPFILE'" EXIT
28ab1c
+    SQUASH_IMG="squash-root.img"
28ab1c
+    SQUASH_TMPFILE="$TMPDIR/initrd.root.sqsh"
28ab1c
+
28ab1c
     $CAT "$image" 2>/dev/null | cpio --extract --verbose --quiet --to-stdout -- \
28ab1c
         $SQUASH_IMG > "$SQUASH_TMPFILE" 2>/dev/null
28ab1c
     if [[ -s $SQUASH_TMPFILE ]]; then
28ab1c
diff --git a/modules.d/99squash/clear-squash.sh b/modules.d/99squash/clear-squash.sh
28ab1c
deleted file mode 100755
28ab1c
index 4f357817..00000000
28ab1c
--- a/modules.d/99squash/clear-squash.sh
28ab1c
+++ /dev/null
28ab1c
@@ -1,6 +0,0 @@
28ab1c
-#!/bin/bash
28ab1c
-mnt="/squash/root"
28ab1c
-for dir in jsquash/root/*; do
28ab1c
-	mnt="$mnt ${dir#$SQUASH_MNT}"
28ab1c
-done
28ab1c
-umount --lazy -- $mnt
28ab1c
diff --git a/modules.d/99squash/init-squash.sh b/modules.d/99squash/init-squash.sh
28ab1c
index fee0105e..3de6f819 100755
28ab1c
--- a/modules.d/99squash/init-squash.sh
28ab1c
+++ b/modules.d/99squash/init-squash.sh
28ab1c
@@ -1,61 +1,29 @@
28ab1c
-#!/bin/bash
28ab1c
+#!/bin/sh
28ab1c
 PATH=/bin:/sbin
28ab1c
 
28ab1c
-SQUASH_IMG=/squash/root.img
28ab1c
-SQUASH_MNT=/squash/root
28ab1c
+# Basic mounts for mounting a squash image
28ab1c
+mkdir /proc /sys /dev /run
28ab1c
+mount -t proc -o nosuid,noexec,nodev proc /proc
28ab1c
+mount -t sysfs -o nosuid,noexec,nodev sysfs /sys
28ab1c
+mount -t devtmpfs -o mode=755,noexec,nosuid,strictatime devtmpfs /dev
28ab1c
+mount -t tmpfs -o mode=755,nodev,nosuid,strictatime tmpfs /run
28ab1c
 
28ab1c
-# Following mount points are neccessary for mounting a squash image
28ab1c
-
28ab1c
-[ ! -d /proc/self ] && \
28ab1c
-    mount -t proc -o nosuid,noexec,nodev proc /proc
28ab1c
-
28ab1c
-[ ! -d /sys/kernel ] && \
28ab1c
-    mount -t sysfs -o nosuid,noexec,nodev sysfs /sys
28ab1c
-
28ab1c
-[ ! -e /dev/loop-control ] && \
28ab1c
-    mount -t devtmpfs -o mode=0755,noexec,nosuid,strictatime devtmpfs /dev
28ab1c
-
28ab1c
-# Need a loop device backend, overlayfs, and squashfs module
28ab1c
+# Load required modules
28ab1c
 modprobe loop
28ab1c
-if [ $? != 0 ]; then
28ab1c
-    echo "Unable to setup loop module"
28ab1c
-fi
28ab1c
-
28ab1c
 modprobe squashfs
28ab1c
-if [ $? != 0 ]; then
28ab1c
-    echo "Unable to setup squashfs module"
28ab1c
-fi
28ab1c
-
28ab1c
 modprobe overlay
28ab1c
-if [ $? != 0 ]; then
28ab1c
-    echo "Unable to setup overlay module"
28ab1c
-fi
28ab1c
-
28ab1c
-[ ! -d "$SQUASH_MNT" ] && \
28ab1c
-	mkdir -m 0755 -p $SQUASH_MNT
28ab1c
-
28ab1c
-# Mount the squashfs image
28ab1c
-mount -t squashfs -o ro,loop $SQUASH_IMG $SQUASH_MNT
28ab1c
-
28ab1c
-if [ $? != 0 ]; then
28ab1c
-    echo "Unable to mount squashed initramfs image"
28ab1c
-fi
28ab1c
-
28ab1c
-for file in $SQUASH_MNT/*; do
28ab1c
-	file=${file#$SQUASH_MNT/}
28ab1c
-	lowerdir=$SQUASH_MNT/$file
28ab1c
-	workdir=/squash/overlay-work/$file
28ab1c
-	upperdir=/$file
28ab1c
-	mntdir=/$file
28ab1c
 
28ab1c
-	mkdir -m 0755 -p $workdir
28ab1c
-	mkdir -m 0755 -p $mntdir
28ab1c
+# Mount the squash image
28ab1c
+mount -t ramfs ramfs /squash
28ab1c
+mkdir -p /squash/root /squash/overlay/upper /squash/overlay/work
28ab1c
+mount -t squashfs -o ro,loop /squash-root.img /squash/root
28ab1c
 
28ab1c
-	mount -t overlay overlay -o\
28ab1c
-		lowerdir=$lowerdir,upperdir=$upperdir,workdir=$workdir $mntdir
28ab1c
-done
28ab1c
+# Setup new root overlay
28ab1c
+mkdir /newroot
28ab1c
+mount -t overlay overlay -o lowerdir=/squash/root,upperdir=/squash/overlay/upper,workdir=/squash/overlay/work/ /newroot/
28ab1c
 
28ab1c
-exec /init.orig
28ab1c
+# Move all mount points to new root to prepare chroot
28ab1c
+mount --move /squash /newroot/squash
28ab1c
 
28ab1c
-echo "Something went wrong when trying to exec original init!"
28ab1c
-exit 1
28ab1c
+# Jump to new root and clean setup files
28ab1c
+SYSTEMD_IN_INITRD=lenient exec switch_root /newroot /init
28ab1c
diff --git a/modules.d/99squash/module-setup.sh b/modules.d/99squash/module-setup.sh
28ab1c
index ad619176..50c92c31 100644
28ab1c
--- a/modules.d/99squash/module-setup.sh
28ab1c
+++ b/modules.d/99squash/module-setup.sh
28ab1c
@@ -19,56 +19,36 @@ depends() {
28ab1c
 }
28ab1c
 
28ab1c
 installpost() {
28ab1c
-    local squash_candidate=( "usr" "etc" )
28ab1c
-
28ab1c
-    # shellcheck disable=SC2174
28ab1c
-    mkdir -m 0755 -p "$squash_dir"
28ab1c
-    for folder in "${squash_candidate[@]}"; do
28ab1c
-        mv "$initdir/$folder" "$squash_dir/$folder"
28ab1c
+    # Move everything under $initdir except $squash_dir
28ab1c
+    # itself into squash image
28ab1c
+    for i in "$initdir"/*; do
28ab1c
+        [[ "$squash_dir" == "$i"/* ]] || mv "$i" "$squash_dir"/
28ab1c
     done
28ab1c
 
28ab1c
-    # Move some files out side of the squash image, including:
28ab1c
-    # - Files required to boot and mount the squashfs image
28ab1c
-    # - Files need to be accessible without mounting the squash image
28ab1c
-    # - Initramfs marker
28ab1c
-    for file in \
28ab1c
-        "$squash_dir"/usr/lib/dracut/* \
28ab1c
-        "$squash_dir"/etc/initrd-release
28ab1c
-    do
28ab1c
+    # Create mount points for squash loader
28ab1c
+    mkdir -p "$initdir"/squash/
28ab1c
+    mkdir -p "$squash_dir"/squash/
28ab1c
+
28ab1c
+    # Copy dracut spec files out side of the squash image
28ab1c
+    # so dracut rebuild and lsinitrd can work
28ab1c
+    for file in "$squash_dir"/usr/lib/dracut/*; do
28ab1c
         [[ -f $file ]] || continue
28ab1c
         DRACUT_RESOLVE_DEPS=1 dracutsysrootdir="$squash_dir" inst "${file#$squash_dir}"
28ab1c
-        rm "$file"
28ab1c
-    done
28ab1c
-
28ab1c
-    # Install required files for the squash image setup script.
28ab1c
-    inst_multiple modprobe mount mkdir ln echo rm
28ab1c
-
28ab1c
-    mv "$initdir"/init "$initdir"/init.orig
28ab1c
-    inst "$moddir"/init-squash.sh /init
28ab1c
-    inst "$moddir"/clear-squash.sh /squash/clear-squash.sh
28ab1c
-
28ab1c
-    # Keep systemctl outsite if we need switch root
28ab1c
-    if [[ ! -f "$initdir/lib/dracut/no-switch-root" ]]; then
28ab1c
-      inst "systemctl"
28ab1c
-    fi
28ab1c
-
28ab1c
-    # Remove duplicated files
28ab1c
-    for folder in "${squash_candidate[@]}"; do
28ab1c
-        find "$initdir/$folder/" -not -type d \
28ab1c
-            -exec bash -c 'mv -f "$squash_dir${1#$initdir}" "$1"' -- "{}" \;
28ab1c
     done
28ab1c
 
28ab1c
-    # Install required modules for the squash image init script.
28ab1c
+    # Install required modules and binaries for the squash image init script.
28ab1c
+    DRACUT_RESOLVE_DEPS=1 inst_multiple sh mount modprobe mkdir switch_root
28ab1c
     hostonly="" instmods "loop" "squashfs" "overlay"
28ab1c
     dracut_kernel_post
28ab1c
+
28ab1c
+    # Install squash image init script.
28ab1c
+    ln -sfn /usr/bin "$initdir/bin"
28ab1c
+    ln -sfn /usr/sbin "$initdir/sbin"
28ab1c
+    inst_simple "$moddir"/init-squash.sh /init
28ab1c
 }
28ab1c
 
28ab1c
 install() {
28ab1c
     if [[ $DRACUT_SQUASH_POST_INST ]]; then
28ab1c
         installpost
28ab1c
-        return
28ab1c
     fi
28ab1c
-
28ab1c
-    inst "$moddir/squash-mnt-clear.service" "$systemdsystemunitdir/squash-mnt-clear.service"
28ab1c
-    systemctl -q --root "$initdir" add-wants initrd-switch-root.target squash-mnt-clear.service
28ab1c
 }
28ab1c
diff --git a/modules.d/99squash/squash-mnt-clear.service b/modules.d/99squash/squash-mnt-clear.service
28ab1c
deleted file mode 100644
28ab1c
index 84441f60..00000000
28ab1c
--- a/modules.d/99squash/squash-mnt-clear.service
28ab1c
+++ /dev/null
28ab1c
@@ -1,17 +0,0 @@
28ab1c
-#  This file is part of dracut.
28ab1c
-#
28ab1c
-
28ab1c
-[Unit]
28ab1c
-Description=Cleanup squashfs mounts when switch root
28ab1c
-DefaultDependencies=no
28ab1c
-Before=initrd-switch-root.service
28ab1c
-After=initrd-switch-root.target
28ab1c
-ConditionPathExists=/squash/root
28ab1c
-
28ab1c
-[Service]
28ab1c
-Type=oneshot
28ab1c
-RemainAfterExit=no
28ab1c
-StandardInput=null
28ab1c
-StandardOutput=syslog+console
28ab1c
-StandardError=syslog+console
28ab1c
-ExecStart=/squash/clear-squash.sh
28ab1c