Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: improve initramfs image performance and efficiency via cpio reflinks #1148

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ manpages = $(man1pages) $(man5pages) $(man7pages) $(man8pages)

.PHONY: install clean archive rpm srpm testimage test all check AUTHORS CONTRIBUTORS doc dracut-version.sh

all: dracut-version.sh dracut.pc dracut-install skipcpio/skipcpio dracut-util
all: dracut-version.sh dracut.pc dracut-install skipcpio/skipcpio skipcpio/padcpio dracut-util

%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(KMOD_CFLAGS) $< -o $@
Expand Down Expand Up @@ -85,6 +85,9 @@ SKIPCPIO_OBJECTS = skipcpio/skipcpio.o
skipcpio/skipcpio.o: skipcpio/skipcpio.c
skipcpio/skipcpio: $(SKIPCPIO_OBJECTS)

skipcpio/padcpio.o: skipcpio/padcpio.c
skipcpio/padcpio: skipcpio/padcpio.o

UTIL_OBJECTS = util/util.o
util/util.o: util/util.c
util/util: $(UTIL_OBJECTS)
Expand Down Expand Up @@ -193,6 +196,9 @@ endif
if [ -f skipcpio/skipcpio ]; then \
install -m 0755 skipcpio/skipcpio $(DESTDIR)$(pkglibdir)/skipcpio; \
fi
if [ -f skipcpio/padcpio ]; then \
install -m 0755 skipcpio/padcpio $(DESTDIR)$(pkglibdir)/padcpio; \
fi
if [ -f dracut-util ]; then \
install -m 0755 dracut-util $(DESTDIR)$(pkglibdir)/dracut-util; \
fi
Expand All @@ -218,7 +224,7 @@ clean:
$(RM) dracut-*.rpm dracut-*.tar.bz2 dracut-*.tar.xz
$(RM) dracut-version.sh
$(RM) dracut-install install/dracut-install $(DRACUT_INSTALL_OBJECTS)
$(RM) skipcpio/skipcpio $(SKIPCPIO_OBJECTS)
$(RM) skipcpio/skipcpio $(SKIPCPIO_OBJECTS) skipcpio/padcpio skipcpio/padcpio.o
$(RM) dracut-util util/util $(UTIL_OBJECTS)
$(RM) $(manpages) dracut.html
$(RM) dracut.pc
Expand Down
3 changes: 2 additions & 1 deletion dracut-bash-completion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
--cpio-reflink'
[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
Expand Down
9 changes: 9 additions & 0 deletions dracut.8.asc
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,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>_

**--cpio-reflink**::
Attempt to use the GNU cpio --reflink option, which optimizes archive creation for
copy-on-write filesystems by using the copy_file_range(2) syscall. 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
-----------

Expand Down
94 changes: 76 additions & 18 deletions dracut.sh
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,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.
--cpio-reflink Request that cpio perform reflinks for file data.
ddiss marked this conversation as resolved.
Show resolved Hide resolved
--list-modules List all available dracut modules.
-M, --show-modules Print included module's name to standard output during
build.
Expand Down Expand Up @@ -414,6 +415,7 @@ rearrange_params() {
--long zstd \
--long no-compress \
--long gzip \
--long cpio-reflink \
--long list-modules \
--long show-modules \
--long keep \
Expand Down Expand Up @@ -772,6 +774,7 @@ while :; do
--zstd) compress_l="zstd" ;;
--no-compress) _no_compress_l="cat" ;;
--gzip) compress_l="gzip" ;;
--cpio-reflink) cpio_reflink="yes" ;;
--list-modules) do_list="yes" ;;
-M | --show-modules)
show_modules_l="yes"
Expand Down Expand Up @@ -1147,6 +1150,28 @@ trap 'exit 1;' SIGINT
readonly initdir="${DRACUT_TMPDIR}/initramfs"
mkdir -p "$initdir"

if [[ $cpio_reflink == "yes" ]]; then
if [[ "$(cpio --help)" == *--reflink* ]]; then
# both XFS and Btrfs require data to be FS block-size aligned for proper
# extent sharing / reflinks. padcpio ensures this.
if [[ -d "$dracutbasedir/skipcpio" ]]; then
padcpio="$dracutbasedir/skipcpio/padcpio"
else
padcpio="$dracutbasedir/padcpio"
fi
if [[ -x "$padcpio" ]]; then
# align based on statfs optimal transfer size
padcpio_align=$(stat --file-system -c "%s" -- "$initdir")
else
dinfo "cpio-reflink ignored due to lack of padcpio"
unset cpio_reflink
fi
else
dinfo "cpio-reflink ignored due to lack of support in $(which cpio)"
unset cpio_reflink
fi
fi

# shellcheck disable=SC2154
if [[ $early_microcode == yes ]] || { [[ $acpi_override == yes ]] && [[ -d $acpi_table_dir ]]; }; then
readonly early_cpio_dir="${DRACUT_TMPDIR}/earlycpio"
Expand Down Expand Up @@ -2196,6 +2221,8 @@ if dracut_module_included "squash"; then
fi

if [[ $do_strip == yes ]] && ! [[ $DRACUT_FIPS_MODE ]]; then
# warn that stripping files negates (dedup) benefits of using reflink
[ -n "$cpio_reflink" ] && dinfo "inefficient: strip is enabled alongside cpio reflink"
dinfo "*** Stripping files ***"
find "$initdir" -type f \
-executable -not -path '*/lib/modules/*.ko' -print0 \
Expand Down Expand Up @@ -2266,15 +2293,28 @@ 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 "$cpio_reflink" ]]; then
if ! (
umask 077
cd "$early_cpio_dir/d"
find . -print0 | sort -z | "$padcpio" --min "$padcpio_align" --align "$padcpio_align" \
| cpio ${CPIO_REPRODUCIBLE:+--reproducible} --null \
${cpio_owner:+-R "$cpio_owner"} -H newc -o --quiet --reflink -O "${DRACUT_TMPDIR}/initramfs.img"
); then
dfatal "dracut: creation of reflinked $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

Expand Down Expand Up @@ -2325,15 +2365,33 @@ case $compress in
;;
esac

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 "$cpio_reflink" && "$compress" == "cat" ]]; then
# determine padding offset if we're appending to microcode
i=$(stat -c "%s" -- "${DRACUT_TMPDIR}/initramfs.img" 2>/dev/null)
if ! (
umask 077
cd "$initdir"
find . -print0 | sort -z \
| "$padcpio" --min "$padcpio_align" --align "$padcpio_align" ${i:+--offset "$i"} \
| cpio ${CPIO_REPRODUCIBLE:+--reproducible} --null \
${cpio_owner:+-R "$cpio_owner"} -H newc -o --quiet --reflink ${i:+--chain} \
-O "${DRACUT_TMPDIR}/initramfs.img"
); then
dfatal "dracut: creation of reflinked $outfile failed"
exit 1
fi
else
[ -n "$cpio_reflink" ] && dinfo "cpio-reflink ignored due to compression"
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
Expand Down
1 change: 1 addition & 0 deletions dracut.spec
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ echo 'dracut_rescue_image="yes"' > $RPM_BUILD_ROOT%{dracutlibdir}/dracut.conf.d/
%{dracutlibdir}/dracut-install
%{dracutlibdir}/dracut-util
%{dracutlibdir}/skipcpio
%{dracutlibdir}/padcpio
%config(noreplace) %{_sysconfdir}/dracut.conf
%if 0%{?fedora} || 0%{?suse_version} || 0%{?rhel}
%{dracutlibdir}/dracut.conf.d/01-dist.conf
Expand Down
Loading