1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
From: Benjamin Drung <benjamin.drung@canonical.com>
Date: Wed, 13 Aug 2025 13:47:35 +0200
Subject: feat(dracut): support 3cpio for creating initrds
`3cpio` is written in Rust and faster than `cpio`. Use `3cpio` in
`dracut.sh` in case it is available. `3cpio` supports
`SOURCE_DATE_EPOCH` and therefore clamping the files is not needed.
Forwarded: https://github.com/dracut-ng/dracut-ng/pull/1564
---
dracut.sh | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 94 insertions(+), 7 deletions(-)
diff --git a/dracut.sh b/dracut.sh
index 47cdc13..0b5e3e2 100755
--- a/dracut.sh
+++ b/dracut.sh
@@ -270,7 +270,7 @@ Creates initial ramdisk images for preloading modules
Specify the compressor and compressor specific options
used by mksquashfs if squash module is called when
building the initramfs.
- --enhanced-cpio Attempt to reflink cpio file data using dracut-cpio.
+ --enhanced-cpio Attempt to reflink cpio file data using 3cpio/dracut-cpio.
--list-modules List all available dracut modules.
-M, --show-modules Print included module's name to standard output during
build.
@@ -1333,6 +1333,7 @@ esac
if [[ $reproducible == yes ]] && [[ -z ${SOURCE_DATE_EPOCH-} ]]; then
SOURCE_DATE_EPOCH=$(stat -c %Y "$dracutbasedir/dracut-functions.sh")
+ export SOURCE_DATE_EPOCH
fi
if [[ -z $DRACUT_KMODDIR_OVERRIDE && -n $drivers_dir ]]; then
@@ -1393,6 +1394,7 @@ trap 'exit 1;' SIGINT
readonly initdir="${DRACUT_TMPDIR}/initramfs"
readonly squashdir="$initdir/squash_root"
+readonly manifest="${DRACUT_TMPDIR}/manifest"
mkdir -p "$initdir"
if [[ $early_microcode == yes ]] || { [[ $acpi_override == yes ]] && [[ -d $acpi_table_dir ]]; }; then
@@ -1436,13 +1438,22 @@ elif [[ -n $persistent_policy && ! -d "/dev/disk/${persistent_policy}" ]]; then
unset persistent_policy
fi
+CPIO=cpio
+if 3cpio --help 2> /dev/null | grep -q -- --create; then
+ CPIO=3cpio
+fi
+
if [[ $enhanced_cpio == "yes" ]]; then
enhanced_cpio="$dracutbasedir/dracut-cpio"
- if [[ -x $enhanced_cpio ]]; then
+ if 3cpio --help 2> /dev/null | grep -q -- --data-align; then
+ # align based on statfs optimal transfer size
+ cpio_align=$(stat --file-system -c "%s" -- "$initdir")
+ unset enhanced_cpio
+ elif [[ -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"
+ dinfo "--enhanced-cpio ignored due to lack of 3cpio >= 0.10 or dracut-cpio"
unset enhanced_cpio
fi
else
@@ -2290,7 +2301,11 @@ done
cpio_extract() {
local file="$1"
shift
- cpio --extract --file "$file" --quiet -- "$@"
+ if [[ $CPIO == 3cpio ]]; then
+ 3cpio --extract "$file" -- "$@"
+ else
+ cpio --extract --file "$file" --quiet -- "$@"
+ fi
}
if [[ $early_microcode == yes ]]; then
@@ -2465,7 +2480,7 @@ clamp_mtimes() {
| xargs -r -0 touch -h -m -c --date="@${SOURCE_DATE_EPOCH?}"
}
-if [[ ${SOURCE_DATE_EPOCH-} ]]; then
+if [[ ${SOURCE_DATE_EPOCH-} ]] && [[ $CPIO != 3cpio ]]; then
clamp_mtimes "$initdir"
if [[ "$(cpio --help)" == *--reproducible* ]]; then
@@ -2483,17 +2498,31 @@ if [[ $do_hardlink == yes ]] && command -v hardlink > /dev/null; then
# Hardlink itself breaks mtimes on directories as we may have added/removed
# dir entries. Fix those up.
- if [[ ${SOURCE_DATE_EPOCH-} ]]; then
+ if [[ ${SOURCE_DATE_EPOCH-} ]] && [[ $CPIO != 3cpio ]]; then
clamp_mtimes "$initdir" -type d
fi
fi
[[ $EUID != 0 ]] && cpio_owner="0:0"
+[[ $EUID == 0 ]] || owner_override="\t\t\t0\t0"
+path_to_manifest() {
+ local basedir="$1"
+ local relpath
+ while read -r path; do
+ if [[ $path == "$basedir" ]]; then
+ relpath=.
+ else
+ relpath="${path#"$basedir"/}"
+ fi
+ printf "%s\t%s${owner_override-}\n" "$path" "${relpath}"
+ done
+}
+
if [[ $create_early_cpio == yes ]]; then
echo 1 > "$early_cpio_dir/d/early_cpio"
- if [[ ${SOURCE_DATE_EPOCH-} ]]; then
+ if [[ ${SOURCE_DATE_EPOCH-} ]] && [[ $CPIO != 3cpio ]]; then
clamp_mtimes "$early_cpio_dir/d"
fi
@@ -2510,6 +2539,9 @@ if [[ $create_early_cpio == yes ]]; then
dfatal "dracut-cpio: creation of $outfile failed"
exit 1
fi
+ elif [[ $CPIO == 3cpio ]]; then
+ echo "#cpio" >> "$manifest"
+ find "$early_cpio_dir/d" | LANG=C sort | path_to_manifest "$early_cpio_dir/d" >> "$manifest"
else
if ! (
umask 077
@@ -2557,12 +2589,15 @@ case $compress in
else
compress="$DRACUT_COMPRESS_BZIP2 -9"
fi
+ compress_3cpio="bzip2 -9"
;;
lzma)
compress="$DRACUT_COMPRESS_LZMA -9 -T0"
+ compress_3cpio="lzma -9"
;;
xz)
compress="$DRACUT_COMPRESS_XZ --check=crc32 --lzma2=dict=1MiB -T0"
+ compress_3cpio=xz
;;
gzip | pigz)
if [[ $compress == pigz ]] || command -v "$DRACUT_COMPRESS_PIGZ" &> /dev/null; then
@@ -2572,18 +2607,59 @@ case $compress in
else
compress="$DRACUT_COMPRESS_GZIP -n -9"
fi
+ compress_3cpio="gzip -9"
;;
lzo | lzop)
compress="$DRACUT_COMPRESS_LZOP -9"
+ compress_3cpio="lzop -9"
;;
lz4)
compress="$DRACUT_COMPRESS_LZ4 -l -9"
+ compress_3cpio="lz4 -9"
;;
zstd)
compress="$DRACUT_COMPRESS_ZSTD -15 -q -T0"
+ compress_3cpio="zstd -15"
+ ;;
+ cat)
+ compress_3cpio=
;;
esac
+if [[ $CPIO == 3cpio ]] && ! [[ -v compress_3cpio ]]; then
+ case "${compress%% *}" in
+ "$DRACUT_COMPRESS_LBZIP2" | "$DRACUT_COMPRESS_BZIP2" | lbzip2 | bzip2 | */lbzip2 | */bzip2)
+ compress_3cpio="bzip2 -9"
+ ;;
+ "$DRACUT_COMPRESS_LZMA" | lzma | */lzma)
+ compress_3cpio="lzma -9"
+ ;;
+ "$DRACUT_COMPRESS_XZ" | xz | */xz)
+ compress_3cpio=xz
+ ;;
+ "$DRACUT_COMPRESS_PIGZ" | "$DRACUT_COMPRESS_GZIP" | pigz | gzip | */pigz | */gzip)
+ compress_3cpio="gzip -9"
+ ;;
+ "$DRACUT_COMPRESS_LZOP" | lzop | */lzop)
+ compress_3cpio="lzop -9"
+ ;;
+ "$DRACUT_COMPRESS_ZSTD" | zstd | */zstd)
+ compress_3cpio="zstd -15"
+ ;;
+ "$DRACUT_COMPRESS_LZ4" | lz4 | */lz4)
+ compress_3cpio="lz4 -9"
+ ;;
+ "$DRACUT_COMPRESS_CAT" | cat | */cat)
+ compress_3cpio=
+ ;;
+ *)
+ derror "custom compressor $1 not supported with 3cpio"
+ exit 1
+ ;;
+ esac
+ dwarn "custom compressor '${compres}' mapped to 3cpio config '${compress_3cpio}'"
+fi
+
if [[ -n $enhanced_cpio ]]; then
if [[ $compress == "cat" ]]; then
# dracut-cpio appends by default, so any ucode remains
@@ -2608,6 +2684,17 @@ if [[ -n $enhanced_cpio ]]; then
exit 1
fi
unset cpio_outfile
+elif [[ $CPIO == 3cpio ]]; then
+ if [[ -z $compress_3cpio ]]; then
+ echo "#cpio" >> "$manifest"
+ else
+ echo "#cpio: $compress_3cpio" >> "$manifest"
+ fi
+ find "$initdir" | LANG=C sort | path_to_manifest "$initdir" >> "$manifest"
+ if ! 3cpio --create ${cpio_align:+--data-align="${cpio_align}"} "${DRACUT_TMPDIR}/initramfs.img" < "$manifest"; then
+ dfatal "Creation of $outfile failed"
+ exit 1
+ fi
else
if ! (
umask 077
|