diff options
Diffstat (limited to 'modules.d/90dmsquash-live-autooverlay')
3 files changed, 152 insertions, 0 deletions
diff --git a/modules.d/90dmsquash-live-autooverlay/create-overlay-genrules.sh b/modules.d/90dmsquash-live-autooverlay/create-overlay-genrules.sh new file mode 100755 index 0000000..8372b50 --- /dev/null +++ b/modules.d/90dmsquash-live-autooverlay/create-overlay-genrules.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +case "$root" in + live:/dev/*) + printf 'SYMLINK=="%s", RUN+="/sbin/initqueue --settled --onetime --unique /sbin/create-overlay %s"\n' \ + "${root#live:/dev/}" "${root#live:}" >> /etc/udev/rules.d/95-create-overlay.rules + wait_for_dev -n "${root#live:}" + ;; +esac diff --git a/modules.d/90dmsquash-live-autooverlay/create-overlay.sh b/modules.d/90dmsquash-live-autooverlay/create-overlay.sh new file mode 100755 index 0000000..10e8ea5 --- /dev/null +++ b/modules.d/90dmsquash-live-autooverlay/create-overlay.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh + +if getargbool 0 rd.live.debug -n -y rdlivedebug; then + exec > /tmp/create-overlay.$$.out + exec 2>> /tmp/create-overlay.$$.out + set -x +fi + +gatherData() { + overlay=$(getarg rd.live.overlay) + if [ -z "$overlay" ]; then + info "Skipping overlay creation: kernel command line parameter 'rd.live.overlay' is not set" + exit 0 + fi + # shellcheck disable=SC2086 + if ! str_starts ${overlay} LABEL=; then + die "Overlay creation failed: the partition must be set by LABEL in the 'rd.live.overlay' kernel parameter" + fi + + overlayLabel=${overlay#LABEL=} + # shellcheck disable=SC2086 + if [ -b /dev/disk/by-label/${overlayLabel} ]; then + info "Skipping overlay creation: overlay already exists" + exit 0 + fi + + filesystem=$(getarg rd.live.overlay.cowfs) + [ -z "$filesystem" ] && filesystem="ext4" + if [ "$filesystem" != "ext4" ] && [ "$filesystem" != "xfs" ] && [ "$filesystem" != "btrfs" ]; then + die "Overlay creation failed: only ext4, xfs, and btrfs are supported in the 'rd.live.overlay.cowfs' kernel parameter" + fi + + live_dir=$(getarg rd.live.dir) + [ -z "$live_dir" ] && live_dir="LiveOS" + + [ -z "$1" ] && exit 1 + rootDevice=$1 + + # The kernel command line's 'root=' parameter was parsed into the $root variable by the dmsquash-live module. + # $root contains the path to a symlink within /dev/disk/by-label, which points to a partition. + # This script needs that partition's parent block device. + # shellcheck disable=SC2046 + # shellcheck disable=SC2086 + rootDeviceAbsolutePath=$(readlink -f ${rootDevice}) + rootDeviceSysfsPath=/sys/class/block/${rootDeviceAbsolutePath##*/} + if [ -f "${rootDeviceSysfsPath}/partition" ]; then + # shellcheck disable=SC2086 + read -r partition < ${rootDeviceSysfsPath}/partition + else + partition=0 + fi + # shellcheck disable=SC2086 + read -r readonly < ${rootDeviceSysfsPath}/ro + # shellcheck disable=SC2086 + if [ "$partition" != "1" ] || [ "$readonly" != "0" ]; then + info "Skipping overlay creation: unpartitioned or read-only media detected" + exit 0 + fi + # shellcheck disable=SC2046 + # shellcheck disable=SC2086 + fullDriveSysfsPath=$(readlink -f ${rootDeviceSysfsPath}/..) + blockDevice=/dev/${fullDriveSysfsPath##*/} + currentPartitionCount=$(grep --count -E "${blockDevice#/dev/}[0-9]+" /proc/partitions) + + # shellcheck disable=SC2086 + freeSpaceStart=$(parted --script ${blockDevice} unit % print free \ + | awk -v x=${currentPartitionCount} '$1 == x {getline; print $1}') + if [ -z "$freeSpaceStart" ]; then + info "Skipping overlay creation: there is no free space after the last partition" + exit 0 + fi + partitionStart=$((${freeSpaceStart%.*} + 1)) + if [ $partitionStart -eq 100 ]; then + info "Skipping overlay creation: there is not enough free space after the last partition" + exit 0 + fi + + overlayPartition=${blockDevice}$((currentPartitionCount + 1)) + + label=$(blkid --match-tag LABEL --output value "$rootDevice") + uuid=$(blkid --match-tag UUID --output value "$rootDevice") + if [ -z "$label" ] || [ -z "$uuid" ]; then + die "Overlay creation failed: failed to look up root device label and UUID" + fi +} + +createPartition() { + # shellcheck disable=SC2086 + parted --script --align optimal ${blockDevice} mkpart primary ${partitionStart}% 100% +} + +createFilesystem() { + # shellcheck disable=SC2086 + mkfs.${filesystem} -L ${overlayLabel} ${overlayPartition} + + baseDir=/run/initramfs/create-overlayfs + mkdir -p ${baseDir} + # shellcheck disable=SC2086 + mount -t ${filesystem} ${overlayPartition} ${baseDir} + + mkdir -p ${baseDir}/${live_dir}/ovlwork + # shellcheck disable=SC2086 + mkdir ${baseDir}/${live_dir}/overlay-${label}-${uuid} + + umount ${baseDir} + rm -r ${baseDir} +} + +main() { + gatherData "$1" + createPartition + udevsettle + createFilesystem + udevsettle +} + +main "$1" diff --git a/modules.d/90dmsquash-live-autooverlay/module-setup.sh b/modules.d/90dmsquash-live-autooverlay/module-setup.sh new file mode 100755 index 0000000..a97ca5a --- /dev/null +++ b/modules.d/90dmsquash-live-autooverlay/module-setup.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +check() { + # including a module dedicated to live environments in a host-only initrd doesn't make sense + [[ $hostonly ]] && return 1 + return 255 +} + +depends() { + echo dmsquash-live + return 0 +} + +installkernel() { + instmods btrfs ext4 xfs +} + +install() { + inst_multiple awk blkid cat grep mkdir mount parted readlink rmdir tr umount + inst_multiple -o mkfs.btrfs mkfs.ext4 mkfs.xfs + inst_hook pre-udev 25 "$moddir/create-overlay-genrules.sh" + inst_script "$moddir/create-overlay.sh" "/sbin/create-overlay" + dracut_need_initqueue +} |