diff --git a/dracut/50rdcore/module-setup.sh b/dracut/50rdcore/module-setup.sh index c065851..2d689d9 100755 --- a/dracut/50rdcore/module-setup.sh +++ b/dracut/50rdcore/module-setup.sh @@ -14,6 +14,48 @@ install() { inst_multiple gpg-agent inst_multiple gpg-connect-agent + inst_multiple \ + realpath \ + basename \ + blkid \ + cat \ + dirname \ + findmnt \ + growpart \ + realpath \ + resize2fs \ + tail \ + tune2fs \ + touch \ + xfs_admin \ + xfs_growfs \ + wc \ + lsblk \ + wipefs + + inst_multiple \ + awk \ + cat \ + dd \ + grep \ + mktemp \ + partx \ + rm \ + sed \ + sfdisk \ + sgdisk \ + find + + inst_multiple -o \ + clevis-encrypt-sss \ + clevis-encrypt-tang \ + clevis-encrypt-tpm2 \ + clevis-luks-bind \ + clevis-luks-common-functions \ + clevis-luks-unlock \ + pwmake \ + tpm2_create + inst_simple "$moddir/rdcore" "/usr/bin/rdcore" inst_simple "$moddir/coreos-installer" "/usr/bin/coreos-installer" @@ -33,19 +75,8 @@ install() { install_and_enable_unit "coreos-installer-reboot.service" \ "default.target" -# install_and_enable_unit "coreos-installer-noreboot.service" \ -# "basic.target" -# inst_simple "$moddir/coreos-installer-reboot.service" \ -# "$systemdsystemunitdir/coreos-installer-reboot.service" -# inst_simple "$moddir/coreos-installer-noreboot.service" \ -# "$systemdsystemunitdir/coreos-installer-noreboot.service" -# -# inst_simple "$moddir/coreos-installer.target" \ -# "$systemdsystemunitdir/coreos-installer.target" -# -# inst_simple "$moddir/coreos-installer-pre.target" \ -# "$systemdsystemunitdir/coreos-installer-pre.target" -# -# inst_simple "$moddir/coreos-installer-post.target" \ -# "$systemdsystemunitdir/coreos-installer-post.target" + install_and_enable_unit "growfs.service" \ + "default.target" + inst_script "$moddir/growfs" \ + /usr/sbin/growfs } diff --git a/scripts/growfs b/scripts/growfs new file mode 100644 index 0000000..45c495c --- /dev/null +++ b/scripts/growfs @@ -0,0 +1,100 @@ +#!/bin/bash +set -euo pipefail + +# This script grows the root + +sleep 5 +udevadm settle +TYPE=$(lsblk --output FSTYPE /dev/disk/by-label/root | tail -n1) +echo ${TYPE} +dev=$(realpath /dev/disk/by-label/root) + +mount -t ${TYPE} /dev/disk/by-label/root /sysroot + +# We run after the rootfs is mounted at /sysroot +path=/sysroot + +# The use of tail is to avoid errors from duplicate mounts; +# this shouldn't happen for us but we're being conservative. +src=$(findmnt -nvr -o SOURCE "$path" | tail -n1) + +partition=$(realpath /dev/disk/by-label/root) + +# Go through each blockdev in the hierarchy and verify we know how to grow them +lsblk -no TYPE "${partition}" | while read dev; do + case "${dev}" in + part|crypt) ;; + *) echo "error: Unsupported blockdev type ${dev}" 1>&2; exit 1 ;; + esac +done + +# Get the filesystem type before extending the partition. This matters +# because the partition, once extended, might include leftover superblocks +# from the previous contents of the disk (notably ZFS), causing blkid to +eval $(blkid -o export "${src}") + +ROOTFS_TYPE=${TYPE:-} +case "${ROOTFS_TYPE}" in + xfs|ext4|btrfs) ;; + *) echo "error: Unsupported filesystem for ${path}: '${ROOTFS_TYPE}'" 1>&2; exit 1 ;; +esac + +# Now, go through the hierarchy, growing everything. Note we go one device at a +# time using --nodeps, because ordering is buggy in el8: +# https://bugzilla.redhat.com/show_bug.cgi?id=1940607 +current_blkdev=${partition} +while true; do + eval "$(lsblk --paths --nodeps --pairs -o NAME,TYPE,PKNAME "${current_blkdev}")" + MAJMIN=$(echo $(lsblk -dno MAJ:MIN "${NAME}")) + case "${TYPE}" in + part) + eval $(udevadm info --query property --export "${current_blkdev}" | grep ^DM_ || :) + if [ -n "${DM_MPATH:-}" ]; then + # Since growpart does not understand device mapper, we have to use sfdisk. + echo ", +" | sfdisk --no-reread --no-tell-kernel --force -N "${DM_PART}" "/dev/mapper/${DM_MPATH}" + udevadm settle # Wait for udev-triggered kpartx to update mappings + else + partnum=$(cat "/sys/dev/block/${MAJMIN}/partition") + # XXX: ideally this'd be idempotent and we wouldn't `|| :` + growpart "${PKNAME}" "${partnum}" || : + fi + ;; + crypt) + # XXX: yuck... we need to expose this sanely in clevis + (. /usr/bin/clevis-luks-common-functions + eval $(udevadm info --query=property --export "${NAME}") + # lsblk doesn't print PKNAME of crypt devices with --nodeps + PKNAME=/dev/$(ls "/sys/dev/block/${MAJMIN}/slaves") + clevis_luks_unlock_device "${PKNAME}" | cryptsetup resize -d- "${DM_NAME}" + ) + ;; + # already checked + *) echo "unreachable" 1>&2; exit 1 ;; + esac + holders="/sys/dev/block/${MAJMIN}/holders" + [ -d "${holders}" ] || break + nholders="$(ls "${holders}" | wc -l)" + if [ "${nholders}" -eq 0 ]; then + break + elif [ "${nholders}" -gt 1 ]; then + # this shouldn't happen since we've checked the partition types already + echo "error: Unsupported block device with multiple children: ${NAME}" 1>&2 + exit 1 + fi + current_blkdev=/dev/$(ls "${holders}") +done + +# Wipe any filesystem signatures from the extended partition that don't +# correspond to the FS type we detected earlier. +wipefs -af -t "no${ROOTFS_TYPE}" "${src}" + +# TODO: Add XFS to https://github.com/systemd/systemd/blob/master/src/partition/growfs.c +# and use it instead. +case "${ROOTFS_TYPE}" in + xfs) xfs_growfs "${path}" ;; + ext4) resize2fs "${src}" ;; + btrfs) btrfs filesystem resize max ${path} ;; +esac + +# this is useful for tests +touch /run/growfs.stamp \ No newline at end of file diff --git a/src/blockdev.rs b/src/blockdev.rs index f9701b9..2fdd6f0 100644 --- a/src/blockdev.rs +++ b/src/blockdev.rs @@ -970,7 +970,7 @@ pub fn udev_settle() -> Result<()> { // udevd hasn't yet received updates from the kernel, settle will return // immediately, and lsblk won't pick up partition labels. Try to sleep // our way out of this. - sleep(Duration::from_millis(200)); + sleep(Duration::from_millis(500)); runcmd!("udevadm", "settle")?; Ok(()) diff --git a/systemd/coreos-installer-reboot.service b/systemd/coreos-installer-reboot.service index ad79614..f9ba80e 100644 --- a/systemd/coreos-installer-reboot.service +++ b/systemd/coreos-installer-reboot.service @@ -1,6 +1,5 @@ [Unit] Description=Reboot after CoreOS Installer -#Requires=coreos-installer.target After=coreos-installer.service OnFailure=emergency.target OnFailureJobMode=replace-irreversibly diff --git a/systemd/coreos-installer.service b/systemd/coreos-installer.service index 716b783..e8199a9 100644 --- a/systemd/coreos-installer.service +++ b/systemd/coreos-installer.service @@ -1,13 +1,5 @@ [Unit] Description=CoreOS Installer -#Before=coreos-installer.target -#After=nm-run.service -#After=network-online.target -#Wants=network-online.target -# Until we retry HTTP requests let's wait here until -# systemd-resolved comes up if enabled. -# https://github.com/coreos/coreos-installer/issues/283 -#After=systemd-resolved.service After=basic.target # Network is enabled here diff --git a/systemd/growfs.service b/systemd/growfs.service new file mode 100644 index 0000000..6d77aaa --- /dev/null +++ b/systemd/growfs.service @@ -0,0 +1,13 @@ +[Unit] +Description=Grow root filesystem +DefaultDependencies=false + +After=coreos-installer.service +Before=coreos-installer-reboot.service +Requires=dev-disk-by\x2dlabel-root.device +After=dev-disk-by\x2dlabel-root.device + +[Service] +Type=oneshot +ExecStart=/usr/sbin/growfs +RemainAfterExit=yes \ No newline at end of file