]> git.ipfire.org Git - thirdparty/dracut.git/commitdiff
feat(dracut.sh): add "--enhanced-cpio" option for calling dracut-cpio
authorDavid Disseldorp <ddiss@suse.de>
Wed, 17 Feb 2021 00:05:37 +0000 (01:05 +0100)
committerHarald Hoyer <harald@hoyer.xyz>
Wed, 24 Nov 2021 10:14:54 +0000 (11:14 +0100)
The new dracut-cpio binary is capable of performing copy-on-write
optimized initramfs archive creation, but due to the rust dependency
isn't built / installed by default.
This change adds a new "--enhanced-cpio" parameter for dracut which
sees dracut-cpio called for archive creation instead of GNU cpio.

Signed-off-by: David Disseldorp <ddiss@suse.de>
dracut.sh
man/dracut.8.asc
shell-completion/bash/dracut

index 0f111e80cf06c07984ddd957acd4af27aed35459..867febe12bb760cd8f42e9d5d593aafcda64ee1e 100755 (executable)
--- a/dracut.sh
+++ b/dracut.sh
@@ -226,6 +226,7 @@ Creates initial ramdisk images for preloading modules
                          otherwise you will not be able to boot.
   --no-compress         Do not compress the generated initramfs.  This will
                          override any other compression options.
+  --enhanced-cpio       Attempt to reflink cpio file data using dracut-cpio.
   --list-modules        List all available dracut modules.
   -M, --show-modules    Print included module's name to standard output during
                          build.
@@ -412,6 +413,7 @@ rearrange_params() {
             --long zstd \
             --long no-compress \
             --long gzip \
+            --long enhanced-cpio \
             --long list-modules \
             --long show-modules \
             --long keep \
@@ -770,6 +772,7 @@ while :; do
         --zstd) compress_l="zstd" ;;
         --no-compress) _no_compress_l="cat" ;;
         --gzip) compress_l="gzip" ;;
+        --enhanced-cpio) enhanced_cpio_l="yes" ;;
         --list-modules) do_list="yes" ;;
         -M | --show-modules)
             show_modules_l="yes"
@@ -982,6 +985,7 @@ stdloglvl=$((stdloglvl + verbosity_mod_l))
 [[ $tmpdir ]] || tmpdir="$dracutsysrootdir"/var/tmp
 [[ $INITRD_COMPRESS ]] && compress=$INITRD_COMPRESS
 [[ $compress_l ]] && compress=$compress_l
+[[ $enhanced_cpio_l ]] && enhanced_cpio=$enhanced_cpio_l
 [[ $show_modules_l ]] && show_modules=$show_modules_l
 [[ $nofscks_l ]] && nofscks="yes"
 [[ $ro_mnt_l ]] && ro_mnt="yes"
@@ -1188,6 +1192,19 @@ else
     exit 1
 fi
 
+if [[ $enhanced_cpio == "yes" ]]; then
+    enhanced_cpio="$dracutbasedir/dracut-cpio"
+    if [[ -x $enhanced_cpio ]]; then
+        # align based on statfs optimal transfer size
+        cpio_align=$(stat --file-system -c "%s" -- "$initdir")
+    else
+        dinfo "--enhanced-cpio ignored due to lack of dracut-cpio"
+        unset enhanced_cpio
+    fi
+else
+    unset enhanced_cpio
+fi
+
 # shellcheck disable=SC2154
 if [[ $no_kernel != yes ]] && ! [[ -d $srcmods ]]; then
     printf "%s\n" "dracut: Cannot find module directory $srcmods" >&2
@@ -2252,6 +2269,8 @@ if dracut_module_included "squash"; then
 fi
 
 if [[ $do_strip == yes ]] && ! [[ $DRACUT_FIPS_MODE ]]; then
+    # stripping files negates (dedup) benefits of using reflink
+    [[ -n $enhanced_cpio ]] && ddebug "strip is enabled alongside cpio reflink"
     dinfo "*** Stripping files ***"
     find "$initdir" -type f \
         -executable -not -path '*/lib/modules/*.ko' -print0 \
@@ -2322,15 +2341,29 @@ if [[ $create_early_cpio == yes ]]; then
     fi
 
     # The microcode blob is _before_ the initramfs blob, not after
-    if ! (
-        umask 077
-        cd "$early_cpio_dir/d"
-        find . -print0 | sort -z \
-            | cpio ${CPIO_REPRODUCIBLE:+--reproducible} --null \
-                ${cpio_owner:+-R "$cpio_owner"} -H newc -o --quiet > "${DRACUT_TMPDIR}/initramfs.img"
-    ); then
-        dfatal "dracut: creation of $outfile failed"
-        exit 1
+    if [[ -n $enhanced_cpio ]]; then
+        if ! (
+            umask 077
+            cd "$early_cpio_dir/d"
+            find . -print0 | sort -z \
+                | $enhanced_cpio --null ${cpio_owner:+--owner "$cpio_owner"} \
+                    --mtime 0 --data-align "$cpio_align" --truncate-existing \
+                    "${DRACUT_TMPDIR}/initramfs.img"
+        ); then
+            dfatal "dracut-cpio: creation of $outfile failed"
+            exit 1
+        fi
+    else
+        if ! (
+            umask 077
+            cd "$early_cpio_dir/d"
+            find . -print0 | sort -z \
+                | cpio ${CPIO_REPRODUCIBLE:+--reproducible} --null \
+                    ${cpio_owner:+-R "$cpio_owner"} -H newc -o --quiet > "${DRACUT_TMPDIR}/initramfs.img"
+        ); then
+            dfatal "dracut: creation of $outfile failed"
+            exit 1
+        fi
     fi
 fi
 
@@ -2386,15 +2419,41 @@ if [[ $compress == $DRACUT_COMPRESS_ZSTD* ]] && ! check_kernel_config CONFIG_RD_
     compress="cat"
 fi
 
-if ! (
-    umask 077
-    cd "$initdir"
-    find . -print0 | sort -z \
-        | cpio ${CPIO_REPRODUCIBLE:+--reproducible} --null ${cpio_owner:+-R "$cpio_owner"} -H newc -o --quiet \
-        | $compress >> "${DRACUT_TMPDIR}/initramfs.img"
-); then
-    dfatal "dracut: creation of $outfile failed"
-    exit 1
+if [[ -n $enhanced_cpio ]]; then
+    if [[ $compress == "cat" ]]; then
+        # dracut-cpio appends by default, so any ucode remains
+        cpio_outfile="${DRACUT_TMPDIR}/initramfs.img"
+    else
+        ddebug "$compress compression enabled alongside cpio reflink"
+        # dracut-cpio doesn't output to stdout, so stage for compression
+        cpio_outfile="${DRACUT_TMPDIR}/initramfs.img.uncompressed"
+    fi
+
+    if ! (
+        umask 077
+        cd "$initdir"
+        find . -print0 | sort -z \
+            | $enhanced_cpio --null ${cpio_owner:+--owner "$cpio_owner"} \
+                --mtime 0 --data-align "$cpio_align" "$cpio_outfile" || exit 1
+        [[ $compress == "cat" ]] && exit 0
+        $compress < "$cpio_outfile" >> "${DRACUT_TMPDIR}/initramfs.img" \
+            && rm "$cpio_outfile"
+    ); then
+        dfatal "dracut-cpio: creation of $outfile failed"
+        exit 1
+    fi
+    unset cpio_outfile
+else
+    if ! (
+        umask 077
+        cd "$initdir"
+        find . -print0 | sort -z \
+            | cpio ${CPIO_REPRODUCIBLE:+--reproducible} --null ${cpio_owner:+-R "$cpio_owner"} -H newc -o --quiet \
+            | $compress >> "${DRACUT_TMPDIR}/initramfs.img"
+    ); then
+        dfatal "dracut: creation of $outfile failed"
+        exit 1
+    fi
 fi
 
 # shellcheck disable=SC2154
index 515e32db88f02a42f71e4f9f6f8cbc72c23e9e2d..708166bdcacdec935b26be11979bf4822c5c05d3 100644 (file)
@@ -530,6 +530,15 @@ will not be able to boot.
     Specifies the kernel image, which to include in the UEFI executable. The default is
     _/lib/modules/<KERNEL-VERSION>/vmlinuz_ or _/boot/vmlinuz-<KERNEL-VERSION>_
 
+**--enhanced-cpio**::
+    Attempt to use the dracut-cpio binary, which optimizes archive creation for
+    copy-on-write filesystems by using the copy_file_range(2) syscall via Rust's
+    io::copy(). When specified, initramfs archives are also padded to ensure
+    optimal data alignment for extent sharing. To retain reflink data
+    deduplication benefits, this should be used alongside the **--no-compress**
+    and **--no-strip** parameters, with initramfs source files, **--tmpdir**
+    staging area and destination all on the same copy-on-write capable filesystem.
+
 ENVIRONMENT
 -----------
 
index 286fd1ceaeb8348690156035d0eda92845e1638d..d20b307fff72b7630559c249e85cc9c38e03d528 100644 (file)
@@ -32,7 +32,8 @@ _dracut() {
             --local --hostonly --no-hostonly --fstab --help --bzip2 --lzma
             --xz --zstd --no-compress --gzip --list-modules --show-modules --keep
             --printsize --regenerate-all --noimageifnotneeded --early-microcode
-            --no-early-microcode --print-cmdline --reproducible --uefi'
+            --no-early-microcode --print-cmdline --reproducible --uefi
+            --enhanced-cpio'
         [ARG]='-a -m -o -d -I -k -c -L --kver --add --force-add --add-drivers
             --omit-drivers --modules --omit --drivers --filesystems --install
             --fwdir --libdirs --fscks --add-fstab --mount --device --nofscks