Skip to content

Commit a3c67d2

Browse files
iammattcolemanConan-Kudo
authored andcommitted
feat(dmsquash-live): add new dmsquash-live-autooverlay module
1 parent ef9ccd5 commit a3c67d2

13 files changed

+220
-8
lines changed

man/dracut.cmdline.7.asc

+4
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,10 @@ rd.live.overlay=/dev/sdb1:persistent-overlay.img
11711171
rd.live.overlay=UUID=99440c1f-8daa-41bf-b965-b7240a8996f4
11721172
--
11731173
1174+
**rd.live.overlay.cowfs=**__[btrfs|ext4|xfs]__::
1175+
Specifies the filesystem to use when formatting the overlay partition.
1176+
The default is ext4.
1177+
11741178
**rd.live.overlay.size=**__<size_MiB>__::
11751179
Specifies a non-persistent Device-mapper overlay size in MiB. The default is
11761180
_32768_.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/sh
2+
3+
# shellcheck disable=SC2154
4+
case "$root" in
5+
live:/dev/*)
6+
printf 'SYMLINK=="%s", RUN+="/sbin/initqueue --settled --onetime --unique /sbin/create-overlay %s"\n' \
7+
"${root#live:/dev/}" "${root#live:}" >> /etc/udev/rules.d/95-create-overlay.rules
8+
wait_for_dev -n "${root#live:}"
9+
;;
10+
esac
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/bin/sh
2+
3+
type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
4+
5+
if getargbool 0 rd.live.debug -n -y rdlivedebug; then
6+
exec > /tmp/create-overlay.$$.out
7+
exec 2>> /tmp/create-overlay.$$.out
8+
set -x
9+
fi
10+
11+
gatherData() {
12+
overlay=$(getarg rd.live.overlay)
13+
if [ -z "$overlay" ]; then
14+
info "Skipping overlay creation: kernel command line parameter 'rd.live.overlay' is not set"
15+
exit 0
16+
fi
17+
# shellcheck disable=SC2086
18+
if ! str_starts ${overlay} LABEL=; then
19+
die "Overlay creation failed: the partition must be set by LABEL in the 'rd.live.overlay' kernel parameter"
20+
fi
21+
22+
overlayLabel=${overlay#LABEL=}
23+
# shellcheck disable=SC2086
24+
if [ -b /dev/disk/by-label/${overlayLabel} ]; then
25+
info "Skipping overlay creation: overlay already exists"
26+
exit 0
27+
fi
28+
29+
filesystem=$(getarg rd.live.overlay.cowfs)
30+
[ -z "$filesystem" ] && filesystem="ext4"
31+
if [ "$filesystem" != "ext4" ] && [ "$filesystem" != "xfs" ] && [ "$filesystem" != "btrfs" ]; then
32+
die "Overlay creation failed: only ext4, xfs, and btrfs are supported in the 'rd.live.overlay.cowfs' kernel parameter"
33+
fi
34+
35+
live_dir=$(getarg rd.live.dir)
36+
[ -z "$live_dir" ] && live_dir="LiveOS"
37+
38+
[ -z "$1" ] && exit 1
39+
rootDevice=$1
40+
41+
# The kernel command line's 'root=' parameter was parsed into the $root variable by the dmsquash-live module.
42+
# $root contains the path to a symlink within /dev/disk/by-label, which points to a partition.
43+
# This script needs that partition's parent block device.
44+
# shellcheck disable=SC2046
45+
# shellcheck disable=SC2086
46+
rootDeviceAbsolutePath=$(readlink -f ${rootDevice})
47+
rootDeviceSysfsPath=/sys/class/block/${rootDeviceAbsolutePath##*/}
48+
if [ -f "${rootDeviceSysfsPath}/partition" ]; then
49+
# shellcheck disable=SC2086
50+
partition=$(cat ${rootDeviceSysfsPath}/partition)
51+
else
52+
partition=0
53+
fi
54+
# shellcheck disable=SC2086
55+
readonly=$(cat ${rootDeviceSysfsPath}/ro)
56+
# shellcheck disable=SC2086
57+
if [ "$partition" != "1" ] || [ "$readonly" != "0" ]; then
58+
info "Skipping overlay creation: unpartitioned or read-only media detected"
59+
exit 0
60+
fi
61+
# shellcheck disable=SC2046
62+
# shellcheck disable=SC2086
63+
fullDriveSysfsPath=$(readlink -f ${rootDeviceSysfsPath}/..)
64+
blockDevice=/dev/${fullDriveSysfsPath##*/}
65+
currentPartitionCount=$(grep --count -E "${blockDevice#/dev/}[0-9]+" /proc/partitions)
66+
67+
# shellcheck disable=SC2086
68+
freeSpaceStart=$(parted --script ${blockDevice} unit % print free \
69+
| awk -v x=${currentPartitionCount} '$1 == x {getline; print $1}')
70+
if [ -z "$freeSpaceStart" ]; then
71+
info "Skipping overlay creation: there is no free space after the last partition"
72+
exit 0
73+
fi
74+
partitionStart=$((${freeSpaceStart%.*} + 1))
75+
if [ $partitionStart -eq 100 ]; then
76+
info "Skipping overlay creation: there is not enough free space after the last partition"
77+
exit 0
78+
fi
79+
80+
overlayPartition=${blockDevice}$((currentPartitionCount + 1))
81+
82+
label=$(blkid --match-tag LABEL --output value "$rootDevice")
83+
uuid=$(blkid --match-tag UUID --output value "$rootDevice")
84+
if [ -z "$label" ] || [ -z "$uuid" ]; then
85+
die "Overlay creation failed: failed to look up root device label and UUID"
86+
fi
87+
}
88+
89+
createPartition() {
90+
# shellcheck disable=SC2086
91+
parted --script --align optimal ${blockDevice} mkpart primary ${partitionStart}% 100%
92+
}
93+
94+
createFilesystem() {
95+
# shellcheck disable=SC2086
96+
mkfs.${filesystem} -L ${overlayLabel} ${overlayPartition}
97+
98+
baseDir=/run/initramfs/create-overlayfs
99+
mkdir -p ${baseDir}
100+
# shellcheck disable=SC2086
101+
mount -t auto ${overlayPartition} ${baseDir}
102+
103+
mkdir -p ${baseDir}/${live_dir}/ovlwork
104+
# shellcheck disable=SC2086
105+
mkdir ${baseDir}/${live_dir}/overlay-${label}-${uuid}
106+
107+
umount ${baseDir}
108+
rm -r ${baseDir}
109+
}
110+
111+
main() {
112+
gatherData "$1"
113+
createPartition
114+
udevsettle
115+
createFilesystem
116+
udevsettle
117+
}
118+
119+
main "$1"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
3+
check() {
4+
# including a module dedicated to live environments in a host-only initrd doesn't make sense
5+
[[ $hostonly ]] && return 1
6+
return 255
7+
}
8+
9+
depends() {
10+
echo dmsquash-live
11+
return 0
12+
}
13+
14+
installkernel() {
15+
instmods btrfs ext4 xfs
16+
}
17+
18+
install() {
19+
inst_multiple awk blkid cat grep mkdir mount parted readlink rmdir tr umount
20+
inst_multiple -o mkfs.btrfs mkfs.ext4 mkfs.xfs
21+
# shellcheck disable=SC2154
22+
inst_hook pre-udev 25 "$moddir/create-overlay-genrules.sh"
23+
inst_script "$moddir/create-overlay.sh" "/sbin/create-overlay"
24+
dracut_need_initqueue
25+
}

pkgbuild/dracut.spec

+2-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ Requires: %{name} >= %{version}-%{dist_free_release}
142142
Requires: %{name} = %{version}-%{release}
143143
%endif
144144
Requires: %{name}-network = %{version}-%{release}
145-
Requires: tar gzip coreutils bash device-mapper curl
145+
Requires: tar gzip coreutils bash device-mapper curl parted
146146
%if 0%{?fedora}
147147
Requires: fuse ntfs-3g
148148
%endif
@@ -466,6 +466,7 @@ echo 'dracut_rescue_image="yes"' > $RPM_BUILD_ROOT%{dracutlibdir}/dracut.conf.d/
466466
%files live
467467
%{dracutlibdir}/modules.d/99img-lib
468468
%{dracutlibdir}/modules.d/90dmsquash-live
469+
%{dracutlibdir}/modules.d/90dmsquash-live-autooverlay
469470
%{dracutlibdir}/modules.d/90dmsquash-live-ntfs
470471
%{dracutlibdir}/modules.d/90livenet
471472

test/TEST-16-DMSQUASH/create-root.sh

+10-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,17 @@ udevadm control --reload
1111
set -e
1212

1313
udevadm settle
14-
mkfs.ext4 -q -L dracut /dev/disk/by-id/ata-disk_root
14+
15+
# create a single partition using 50% of the capacity of the image file created by test_setup() in test.sh
16+
sfdisk /dev/disk/by-id/ata-disk_root << EOF
17+
2048,161792
18+
EOF
19+
20+
udevadm settle
21+
22+
mkfs.ext4 -q -L dracut /dev/disk/by-id/ata-disk_root-part1
1523
mkdir -p /root
16-
mount /dev/disk/by-id/ata-disk_root /root
24+
mount /dev/disk/by-id/ata-disk_root-part1 /root
1725
mkdir -p /root/run /root/testdir
1826
cp -a -t /root /source/*
1927
echo "Creating squashfs"

test/TEST-16-DMSQUASH/test-init.sh

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ exec > /dev/console 2>&1
99

1010
echo "dracut-root-block-success" | dd oflag=direct,dsync of=/dev/disk/by-id/ata-disk_marker
1111

12+
if grep -qF ' rd.live.overlay=LABEL=persist ' /proc/cmdline; then
13+
# Writing to a file in the root filesystem lets test_run() verify that the autooverlay module successfully created
14+
# and formatted the overlay partition and that the dmsquash-live module used it when setting up the rootfs overlay.
15+
echo "dracut-autooverlay-success" > /overlay-marker
16+
fi
17+
1218
export TERM=linux
1319
export PS1='initramfs-test:\w\$ '
1420
[ -f /etc/mtab ] || ln -sfn /proc/mounts /etc/mtab

test/TEST-16-DMSQUASH/test.sh

+35-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ TEST_DESCRIPTION="live root on a squash filesystem"
55

66
KVERSION="${KVERSION-$(uname -r)}"
77

8-
# Uncomment this to debug failures
9-
#DEBUGFAIL="rd.shell rd.debug loglevel=7"
8+
# Uncomment these to debug failures
9+
#DEBUGFAIL="rd.shell rd.debug rd.live.debug loglevel=7"
10+
#DEBUGTOOLS="setsid ls cat sfdisk"
1011

1112
test_run() {
1213
dd if=/dev/zero of="$TESTDIR"/marker.img bs=1MiB count=1
@@ -29,6 +30,27 @@ test_run() {
2930
-initrd "$TESTDIR"/initramfs.testing
3031

3132
grep -U --binary-files=binary -F -m 1 -q dracut-root-block-success -- "$TESTDIR"/marker.img || return 1
33+
34+
rootPartitions=$(sfdisk -d "$TESTDIR"/root.img | grep -c 'root\.img[0-9]')
35+
[ "$rootPartitions" -eq 1 ] || return 1
36+
37+
"$testdir"/run-qemu \
38+
"${disk_args[@]}" \
39+
-boot order=d \
40+
-append "rd.live.image rd.live.overlay.overlayfs=1 rd.live.overlay=LABEL=persist rd.live.dir=testdir root=LABEL=dracut console=ttyS0,115200n81 quiet selinux=0 rd.info rd.shell=0 panic=1 oops=panic softlockup_panic=1 $DEBUGFAIL" \
41+
-initrd "$TESTDIR"/initramfs.testing-autooverlay
42+
43+
rootPartitions=$(sfdisk -d "$TESTDIR"/root.img | grep -c 'root\.img[0-9]')
44+
[ "$rootPartitions" -eq 2 ] || return 1
45+
46+
(
47+
# Ensure that this test works when run with the `V=1` parameter, which runs the script with `set -o pipefail`.
48+
set +o pipefail
49+
50+
# Verify that the string "dracut-autooverlay-success" occurs in the second partition in the image file.
51+
dd if="$TESTDIR"/root.img bs=1MiB skip=80 status=none \
52+
| grep -U --binary-files=binary -F -m 1 -q dracut-autooverlay-success
53+
) || return 1
3254
}
3355

3456
test_setup() {
@@ -55,7 +77,7 @@ test_setup() {
5577
ln -s dracut-util "${initdir}/usr/bin/dracut-getarg"
5678
ln -s dracut-util "${initdir}/usr/bin/dracut-getargs"
5779

58-
inst_multiple mkdir ln dd stty mount poweroff
80+
inst_multiple mkdir ln dd stty mount poweroff grep "$DEBUGTOOLS"
5981

6082
cp -a -- /etc/ld.so.conf* "$initdir"/etc
6183
ldconfig -r "$initdir"
@@ -121,6 +143,16 @@ test_setup() {
121143
--force "$TESTDIR"/initramfs.testing "$KVERSION" || return 1
122144

123145
ls -sh "$TESTDIR"/initramfs.testing
146+
147+
"$basedir"/dracut.sh -l -i "$TESTDIR"/overlay / \
148+
--modules "dmsquash-live-autooverlay qemu" \
149+
--omit "rngd" \
150+
--drivers "ext4 sd_mod" \
151+
--no-hostonly --no-hostonly-cmdline \
152+
--force "$TESTDIR"/initramfs.testing-autooverlay "$KVERSION" || return 1
153+
154+
ls -sh "$TESTDIR"/initramfs.testing-autooverlay
155+
124156
rm -rf -- "$TESTDIR"/overlay
125157
}
126158

test/container/Dockerfile-Arch

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ RUN pacman --noconfirm -Sy \
1212
linux dash strace dhclient asciidoc cpio pigz squashfs-tools \
1313
qemu btrfs-progs mdadm dmraid nfs-utils nfsidmap lvm2 nbd \
1414
dhcp networkmanager multipath-tools vi tcpdump open-iscsi \
15-
git shfmt shellcheck astyle which base-devel glibc && yes | pacman -Scc
15+
git shfmt shellcheck astyle which base-devel glibc parted && yes | pacman -Scc
1616

1717
RUN useradd -m build
1818
RUN su build -c 'cd && git clone https://aur.archlinux.org/perl-config-general.git && cd perl-config-general && makepkg -s --noconfirm'

test/container/Dockerfile-Debian

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ RUN apt-get update -y -qq && apt-get upgrade -y -qq && DEBIAN_FRONTEND=nonintera
4444
network-manager \
4545
nfs-kernel-server \
4646
open-iscsi \
47+
parted \
4748
pigz \
4849
pkg-config \
4950
procps \

test/container/Dockerfile-Fedora-latest

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ RUN dnf -y install --setopt=install_weak_deps=False \
4949
which \
5050
ShellCheck \
5151
shfmt \
52+
parted \
5253
&& dnf -y update && dnf clean all
5354

5455
# Set default command

test/container/Dockerfile-Gentoo

+5
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,18 @@ LABEL RUN="docker run -it --name NAME --privileged --ipc=host --net=host --pid=h
1717

1818
RUN echo 'export DRACUT_NO_XATTR=1 KVERSION=$(cd /lib/modules; ls -1 | tail -1)' > /etc/profile.d/dracut-test.sh
1919

20+
# Only install `dmsetup`: attempting to install all of lvm2 fails due to missing kernel headers.
21+
RUN echo 'sys-fs/lvm2 device-mapper-only -thin' > /etc/portage/package.use/lvm2
22+
2023
# Install needed packages for the dracut CI container
2124
RUN emerge -qv \
2225
app-arch/cpio \
2326
app-emulation/qemu \
2427
app-shells/dash \
2528
sys-apps/busybox \
29+
sys-block/parted \
2630
sys-fs/btrfs-progs \
31+
sys-fs/lvm2 \
2732
sys-fs/squashfs-tools \
2833
&& rm -rf /var/cache/* /usr/share/doc/* /usr/share/man/* /var/db/repos/gentoo
2934

test/container/Dockerfile-OpenSuse-latest

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ RUN dnf -y install --setopt=install_weak_deps=False \
1313
strace libkmod-devel gcc bzip2 xz tar wget rpm-build make git bash-completion \
1414
sudo kernel dhcp-client qemu-kvm /usr/bin/qemu-system-$(uname -m) e2fsprogs \
1515
tcpdump iproute iputils kbd NetworkManager btrfsprogs tgt dbus-broker \
16-
iscsiuio open-iscsi which ShellCheck procps pigz \
16+
iscsiuio open-iscsi which ShellCheck procps pigz parted squashfs \
1717
&& dnf -y update && dnf clean all
1818

1919
RUN shfmt_version=3.2.4; wget "https://github.com/mvdan/sh/releases/download/v${shfmt_version}/shfmt_v${shfmt_version}_linux_amd64" -O /usr/local/bin/shfmt \

0 commit comments

Comments
 (0)