diff --git a/dracut.cmdline.7.asc b/dracut.cmdline.7.asc index 36d5656106..087d0c0677 100644 --- a/dracut.cmdline.7.asc +++ b/dracut.cmdline.7.asc @@ -820,10 +820,12 @@ only filesystem from the SquashFS and apply a writable device-mapper snapshot over the read only filesystem. Using this method ensures a relatively fast boot and lower RAM usage. Users **must be careful** to avoid writing too many blocks to the snapshot volume. Once the blocks of the snapshot overlay are -exhausted, the root filesystem becomes unusable and requires a reboot. A -persistent overlay is marked Invalid, and requires a difficult recovery. -Non-persistent overlays default to 512 MiB in RAM, but the size can be adjusted -with the **rd.live.overlay.size=** kernel command line option. +exhausted, the root filesystem becomes read only and may cause application +failures. The overlay file is marked 'Overflow', and a difficult recovery is +required to repair and enlarge the overlay offline. Non-persistent overlays +are sparse files in RAM that only consume content space as required blocks are +allocated. They default to an apparent size of 32 GiB in RAM. The size can be +adjusted with the **rd.live.overlay.size=** kernel command line option. + The filesystem structure is expected to be: + @@ -832,7 +834,7 @@ The filesystem structure is expected to be: squashfs.img | Squashfs from LiveCD .iso downloaded via network !(mount) /LiveOS - |- ext3fs.img | Filesystem image to mount read-only + |- rootfs.img | Filesystem image to mount read-only !(mount) /bin | Live filesystem /boot | @@ -854,7 +856,7 @@ of the root filesystem. Uncompressed live filesystem image::: When the live system was installed with the '--skipcompress' option of the __livecd-iso-to-disk__ installation script for Live USB devices, the root -filesystem image, `ext3fs.img`, is expanded on installation and no SquashFS +filesystem image, `rootfs.img`, is expanded on installation and no SquashFS is involved during boot. + - If **rd.live.ram=1** is used in this situation, the full, uncompressed @@ -919,8 +921,8 @@ root=live:torrent://example.com/liveboot.img.torrent Enables debug output from the live boot process. **rd.live.dir=**____:: -Specifies the directory within the squashfs where the ext3fs.img or rootfs.img -can be found. By default, this is __LiveOS__. +Specifies the directory within the boot device where the squashfs.img or +rootfs.img can be found. By default, this is __LiveOS__. **rd.live.squashimg=**____:: Specifies the filename for a SquashFS image of the root filesystem. @@ -938,6 +940,8 @@ used to persist the changes made to the device specified by the **root=live:____** option. - _none_ specifies no overlay when an uncompressed live root filesystem is available. +If a persistent overlay is detected at the standard LiveOS path, the overlay & +overlay type detected (whether Device-mapper or OverlayFS) will be used. + [listing] .Example @@ -946,7 +950,7 @@ rd.live.overlay=/dev/sdb1:persistent-overlay.img -- **rd.live.overlay.size=**____:: -Specifies a non-persistent overlay size in MiB. The default is _512_. +Specifies a non-persistent overlay size in MiB. The default is _32768_. **rd.live.overlay.readonly=**1:: Specifies a non-persistent, writable snapshot overlay to be stacked over a @@ -963,6 +967,28 @@ blocks that are not claimed by the filesystem. In this use case, this means that memory is given back to the kernel when the filesystem does not claim it anymore. +**rd.live.overlay.overlayfs=**1:: +Enables the use of the **OverlayFS** kernel module, if available, to provide a +copy-on-write union directory for the root filesystem. OverlayFS overlays are +directories of the files that have changed on the read-only base (lower) +filesystem. The root filesystem is provided through a special overlay type +mount that merges the lower and upper directories. If an OverlayFS upper +directory is not present on the boot device, a tmpfs directory will be created +at /run/overlayfs to provide temporary storage. Persistent storage can be +provided on vfat or msdos formatted devices by supplying the OverlayFS upper +directory within an embedded filesystem that supports the creation of trusted.* +extended attributes and provides a valid d_type in readdir responses, such as +with ext4 and xfs. On non-vfat-formatted devices, a persistent OverlayFS +overlay can extend the available root filesystem storage up to the capacity of +the LiveOS device. + +If a persistent overlay is detected at the standard LiveOS path, the overlay & +overlay type detected (whether OverlayFS or Device-mapper) will be used. + +The **rd.live.overlay.readonly** option, which allows a persistent overlayfs to +be mounted read only through a higher level transient overlay directory, has +been implemented through the multiple lower layers feature of OverlayFS. + Plymouth Boot Splash ~~~~~~~~~~~~~~~~~~~~ diff --git a/modules.d/90dm/dm-shutdown.sh b/modules.d/90dm/dm-shutdown.sh index 04c89be9c6..7e4f4a586a 100755 --- a/modules.d/90dm/dm-shutdown.sh +++ b/modules.d/90dm/dm-shutdown.sh @@ -14,7 +14,8 @@ _do_dm_shutdown() { return $ret } -if command -v dmsetup >/dev/null; then +if command -v dmsetup >/dev/null && + [ "x$(dmsetup status)" != "xNo devices found" ]; then _do_dm_shutdown $1 else : diff --git a/modules.d/90dmsquash-live/apply-live-updates.sh b/modules.d/90dmsquash-live/apply-live-updates.sh index 6a1993bedb..bcca761b1b 100755 --- a/modules.d/90dmsquash-live/apply-live-updates.sh +++ b/modules.d/90dmsquash-live/apply-live-updates.sh @@ -1,6 +1,6 @@ #!/bin/sh -if [ -b /dev/mapper/live-rw ] && [ -d /run/initramfs/live/updates -o -d /updates ]; then +if [ -L /run/rootfsbase ] && [ -d /run/initramfs/live/updates -o -d /updates ]; then info "Applying updates to live image..." mount -o bind /run $NEWROOT/run # avoid overwriting symlinks (e.g. /lib -> /usr/lib) with directories diff --git a/modules.d/90dmsquash-live/dmsquash-generator.sh b/modules.d/90dmsquash-live/dmsquash-generator.sh index 85a359284b..a5bfbdf20d 100755 --- a/modules.d/90dmsquash-live/dmsquash-generator.sh +++ b/modules.d/90dmsquash-live/dmsquash-generator.sh @@ -52,21 +52,30 @@ esac GENERATOR_DIR="$2" [ -z "$GENERATOR_DIR" ] && exit 1 - [ -d "$GENERATOR_DIR" ] || mkdir "$GENERATOR_DIR" +getargbool 0 rd.live.overlay.overlayfs && overlayfs="yes" +[ -e /xor_overlayfs ] && xor_overlayfs="yes" ROOTFLAGS="$(getarg rootflags)" { echo "[Unit]" echo "Before=initrd-root-fs.target" echo "[Mount]" echo "Where=/sysroot" - echo "What=/dev/mapper/live-rw" - [ -n "$ROOTFLAGS" ] && echo "Options=${ROOTFLAGS}" + if [ "$overlayfs$xor_overlayfs" = "yes" ]; then + echo "What=LiveOS_rootfs" + echo "Options=${ROOTFLAGS},lowerdir=/run/rootfsbase,upperdir=/run/overlayfs,workdir=/run/ovlwork" + echo "Type=overlay" + _dev=LiveOS_rootfs + else + echo "What=/dev/mapper/live-rw" + [ -n "$ROOTFLAGS" ] && echo "Options=${ROOTFLAGS}" + _dev=dev-mapper-live\x2drw + fi } > "$GENERATOR_DIR"/sysroot.mount -mkdir -p "$GENERATOR_DIR/dev-mapper-live\x2drw.device.d" +mkdir -p "$GENERATOR_DIR/$_dev.device.d" { echo "[Unit]" echo "JobTimeoutSec=3000" -} > "$GENERATOR_DIR/dev-mapper-live\x2drw.device.d/timeout.conf" +} > "$GENERATOR_DIR/$_dev.device.d/timeout.conf" diff --git a/modules.d/90dmsquash-live/dmsquash-live-root.sh b/modules.d/90dmsquash-live/dmsquash-live-root.sh index e58d7c222c..c7526a43b1 100755 --- a/modules.d/90dmsquash-live/dmsquash-live-root.sh +++ b/modules.d/90dmsquash-live/dmsquash-live-root.sh @@ -28,9 +28,10 @@ getargbool 0 rd.live.overlay.readonly -d -y readonly_overlay && readonly_overlay overlay=$(getarg rd.live.overlay -d overlay) getargbool 0 rd.writable.fsimg -d -y writable_fsimg && writable_fsimg="yes" overlay_size=$(getarg rd.live.overlay.size=) -[ -z "$overlay_size" ] && overlay_size=512 +[ -z "$overlay_size" ] && overlay_size=32768 getargbool 0 rd.live.overlay.thin && thin_snapshot="yes" +getargbool 0 rd.live.overlay.overlayfs && overlayfs="yes" # CD/DVD media check [ -b $livedev ] && fs=$(blkid -s TYPE -o value $livedev) @@ -110,48 +111,94 @@ do_live_overlay() { setup="" if [ -n "$devspec" -a -n "$pathspec" -a -n "$overlay" ]; then mkdir -m 0755 /run/initramfs/overlayfs + opt='' + [ -n "$readonly_overlay" ] && opt=-r mount -n -t auto $devspec /run/initramfs/overlayfs || : if [ -f /run/initramfs/overlayfs$pathspec -a -w /run/initramfs/overlayfs$pathspec ]; then - losetup $OVERLAY_LOOPDEV /run/initramfs/overlayfs$pathspec - if [ -n "$reset_overlay" ]; then - dd if=/dev/zero of=$OVERLAY_LOOPDEV bs=64k count=1 conv=fsync 2>/dev/null + losetup $opt $OVERLAY_LOOPDEV /run/initramfs/overlayfs$pathspec + umount -l /run/initramfs/overlayfs || : + oltype=$(det_img_fs $OVERLAY_LOOPDEV) + if [ -z "$oltype" ] || [ "$oltype" = DM_snapshot_cow ]; then + if [ -n "$reset_overlay" ]; then + info "Resetting the Device-mapper overlay." + dd if=/dev/zero of=$OVERLAY_LOOPDEV bs=64k count=1 conv=fsync 2>/dev/null + fi + if [ -n "$overlayfs" ]; then + unset -v overlayfs + [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit="yes" + fi + setup="yes" + else + mount -n -t $oltype $opt $OVERLAY_LOOPDEV /run/initramfs/overlayfs + if [ -d /run/initramfs/overlayfs/overlayfs ] && + [ -d /run/initramfs/overlayfs/ovlwork ]; then + ln -s /run/initramfs/overlayfs/overlayfs /run/overlayfs$opt + ln -s /run/initramfs/overlayfs/ovlwork /run/ovlwork$opt + if [ -z "$overlayfs" ]; then + overlayfs="yes" + [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit="yes" + fi + setup="yes" + fi + fi + elif [ -d /run/initramfs/overlayfs$pathspec ] && + [ -d /run/initramfs/overlayfs$pathspec/../ovlwork ]; then + ln -s /run/initramfs/overlayfs$pathspec /run/overlayfs$opt + ln -s /run/initramfs/overlayfs$pathspec/../ovlwork /run/ovlwork$opt + if [ -z "$overlayfs" ]; then + overlayfs="yes" + [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit="yes" fi setup="yes" fi - umount -l /run/initramfs/overlayfs || : + fi + if [ -n "$overlayfs" ]; then + modprobe overlay + if [ $? != 0 ]; then + echo "OverlayFS is not available; using temporary Device-mapper overlay." > /dev/kmsg + unset -v overlayfs setup + [ -n "$reloadsysrootmountunit" ] && unset -v reloadsysrootmountunit + sleep 5 + fi fi if [ -z "$setup" -o -n "$readonly_overlay" ]; then if [ -n "$setup" ]; then warn "Using temporary overlay." elif [ -n "$devspec" -a -n "$pathspec" ]; then - warn "Unable to find persistent overlay; using temporary" + echo "Unable to find persistent overlay; using temporary." > /dev/kmsg sleep 5 fi - - dd if=/dev/null of=/overlay bs=1024 count=1 seek=$((overlay_size*1024)) 2> /dev/null - if [ -n "$setup" -a -n "$readonly_overlay" ]; then - RO_OVERLAY_LOOPDEV=$( losetup -f ) - losetup $RO_OVERLAY_LOOPDEV /overlay + if [ -n "$overlayfs" ]; then + mkdir -m 0755 /run/overlayfs + mkdir -m 0755 /run/ovlwork else - losetup $OVERLAY_LOOPDEV /overlay + dd if=/dev/null of=/overlay bs=1024 count=1 seek=$((overlay_size*1024)) 2> /dev/null + if [ -n "$setup" -a -n "$readonly_overlay" ]; then + RO_OVERLAY_LOOPDEV=$( losetup -f ) + losetup $RO_OVERLAY_LOOPDEV /overlay + else + losetup $OVERLAY_LOOPDEV /overlay + fi fi fi # set up the snapshot sz=$(blockdev --getsz $BASE_LOOPDEV) - if [ -n "$readonly_overlay" ]; then - echo 0 $sz snapshot $BASE_LOOPDEV $OVERLAY_LOOPDEV N 8 | dmsetup create --readonly live-ro - base="/dev/mapper/live-ro" - over=$RO_OVERLAY_LOOPDEV - else - base=$BASE_LOOPDEV - over=$OVERLAY_LOOPDEV + if [ -z "$overlayfs" ]; then + if [ -n "$readonly_overlay" ]; then + echo 0 $sz snapshot $BASE_LOOPDEV $OVERLAY_LOOPDEV P 8 | dmsetup create --readonly live-ro + base="/dev/mapper/live-ro" + over=$RO_OVERLAY_LOOPDEV + else + base=$BASE_LOOPDEV + over=$OVERLAY_LOOPDEV + fi fi if [ -n "$thin_snapshot" ]; then modprobe dm_thin_pool - mkdir /run/initramfs/thin-overlay + mkdir -m 0755 /run/initramfs/thin-overlay # In block units (512b) thin_data_sz=$(( $overlay_size * 1024 * 1024 / 512 )) @@ -170,7 +217,7 @@ do_live_overlay() { # Create a snapshot of the base image echo 0 $sz thin /dev/mapper/live-overlay-pool 0 $base | dmsetup create live-rw - else + elif [ -z "$overlayfs" ]; then echo 0 $sz snapshot $base $over PO 8 | dmsetup create live-rw fi @@ -178,17 +225,9 @@ do_live_overlay() { echo 0 $sz linear $BASE_LOOPDEV 0 | dmsetup create --readonly live-base } -# live cd helper function -do_live_from_base_loop() { - do_live_overlay -} - # we might have a genMinInstDelta delta file for anaconda to take advantage of if [ -e /run/initramfs/live/${live_dir}/osmin.img ]; then OSMINSQFS=/run/initramfs/live/${live_dir}/osmin.img -fi - -if [ -n "$OSMINSQFS" ]; then # decompress the delta data dd if=$OSMINSQFS of=/run/initramfs/osmin.img 2> /dev/null OSMIN_SQUASHED_LOOPDEV=$( losetup -f ) @@ -204,13 +243,12 @@ fi if [ -e /run/initramfs/live/${live_dir}/${squash_image} ]; then SQUASHED="/run/initramfs/live/${live_dir}/${squash_image}" fi - -if [ -e "$SQUASHED" ] ; then +if [ -e "$SQUASHED" ]; then if [ -n "$live_ram" ]; then - echo "Copying live image to RAM..." - echo "(this may take a few minutes)" + echo 'Copying live image to RAM...' > /dev/kmsg + echo ' (this may take a minute)' > /dev/kmsg dd if=$SQUASHED of=/run/initramfs/squashed.img bs=512 2> /dev/null - echo "Done copying live image to RAM." + echo 'Done copying live image to RAM.' > /dev/kmsg SQUASHED="/run/initramfs/squashed.img" fi @@ -219,23 +257,23 @@ if [ -e "$SQUASHED" ] ; then mkdir -m 0755 -p /run/initramfs/squashfs mount -n -t squashfs -o ro $SQUASHED_LOOPDEV /run/initramfs/squashfs - if [ -f /run/initramfs/squashfs/LiveOS/ext3fs.img ]; then - FSIMG="/run/initramfs/squashfs/LiveOS/ext3fs.img" - elif [ -f /run/initramfs/squashfs/LiveOS/rootfs.img ]; then + if [ -f /run/initramfs/squashfs/LiveOS/rootfs.img ]; then FSIMG="/run/initramfs/squashfs/LiveOS/rootfs.img" + elif [ -f /run/initramfs/squashfs/LiveOS/ext3fs.img ]; then + FSIMG="/run/initramfs/squashfs/LiveOS/ext3fs.img" fi else # we might have an embedded fs image to use as rootfs (uncompressed live) - if [ -e /run/initramfs/live/${live_dir}/ext3fs.img ]; then - FSIMG="/run/initramfs/live/${live_dir}/ext3fs.img" - elif [ -e /run/initramfs/live/${live_dir}/rootfs.img ]; then + if [ -e /run/initramfs/live/${live_dir}/rootfs.img ]; then FSIMG="/run/initramfs/live/${live_dir}/rootfs.img" + elif [ -e /run/initramfs/live/${live_dir}/ext3fs.img ]; then + FSIMG="/run/initramfs/live/${live_dir}/ext3fs.img" fi if [ -n "$live_ram" ]; then - echo 'Copying live image to RAM...' - echo '(this may take a few minutes)' + echo 'Copying live image to RAM...' > /dev/kmsg + echo ' (this may take a minute or so)' > /dev/kmsg dd if=$FSIMG of=/run/initramfs/rootfs.img bs=512 2> /dev/null - echo 'Done copying live image to RAM.' + echo 'Done copying live image to RAM.' > /dev/kmsg FSIMG='/run/initramfs/rootfs.img' fi fi @@ -245,8 +283,8 @@ if [ -n "$FSIMG" ] ; then if [ -n "$writable_fsimg" ] ; then # mount the provided filesystem read/write - echo "Unpacking live filesystem (may take some time)" - mkdir /run/initramfs/fsimg/ + echo "Unpacking live filesystem (may take some time)" > /dev/kmsg + mkdir -m 0755 /run/initramfs/fsimg/ if [ -n "$SQUASHED" ]; then cp -v $FSIMG /run/initramfs/fsimg/rootfs.img else @@ -254,35 +292,60 @@ if [ -n "$FSIMG" ] ; then fi FSIMG=/run/initramfs/fsimg/rootfs.img fi - if [ -n "$writable_fsimg" ] || [ -z "$SQUASHED" -a -n "$live_ram" ] || + if [ -n "$writable_fsimg" ] || [ -z "$SQUASHED" -a -n "$live_ram" -a -z "$overlayfs" ] || [ "$overlay" = none -o "$overlay" = None -o "$overlay" = NONE ]; then losetup $BASE_LOOPDEV $FSIMG sz=$(blockdev --getsz $BASE_LOOPDEV) echo 0 $sz linear $BASE_LOOPDEV 0 | dmsetup create live-rw else - # mount the filesystem read-only and add a dm snapshot for writes + # Attach the filesystem read-only and add a DM snapshot or OverlayFS for writes. losetup -r $BASE_LOOPDEV $FSIMG - do_live_from_base_loop + do_live_overlay fi fi -[ -e "$SQUASHED" ] && umount -l /run/initramfs/squashfs +[ -e "$SQUASHED" ] && [ -z "$overlayfs" ] && umount -l /run/initramfs/squashfs if [ -b "$OSMIN_LOOPDEV" ]; then # set up the devicemapper snapshot device, which will merge # the normal live fs image, and the delta, into a minimzied fs image - echo "0 $( blockdev --getsz $BASE_LOOPDEV ) snapshot $BASE_LOOPDEV $OSMIN_LOOPDEV N 8" | dmsetup create --readonly live-osimg-min + echo "0 $sz snapshot $BASE_LOOPDEV $OSMIN_LOOPDEV P 8" | dmsetup create --readonly live-osimg-min fi -ROOTFLAGS="$(getarg rootflags)" -if [ -n "$ROOTFLAGS" ]; then - ROOTFLAGS="-o $ROOTFLAGS" +if [ -n "$reloadsysrootmountunit" ]; then + > /xor_overlayfs + systemctl daemon-reload fi -ln -s /dev/mapper/live-rw /dev/root +ROOTFLAGS="$(getarg rootflags)" -if [ -z "$DRACUT_SYSTEMD" ]; then - printf 'mount %s /dev/mapper/live-rw %s\n' "$ROOTFLAGS" "$NEWROOT" > $hookdir/mount/01-$$-live.sh +if [ -n "$overlayfs" ]; then + mkdir -m 0755 /run/rootfsbase + if [ -n "$reset_overlay" ] && [ -L /run/overlayfs ]; then + ovlfs=$(readlink /run/overlayfs) + info "Resetting the OverlayFS overlay directory." + rm -r -- ${ovlfs}/* ${ovlfs}/.* >/dev/null 2>&1 + fi + if [ -n "$readonly_overlay" ]; then + mkdir -m 0755 /run/rootfsbase-r + mount -r $FSIMG /run/rootfsbase-r + mount -t overlay LiveOS_rootfs-r -oro,lowerdir=/run/overlayfs-r:/run/rootfsbase-r /run/rootfsbase + else + mount -r $FSIMG /run/rootfsbase + fi + if [ -z "$DRACUT_SYSTEMD" ]; then + #FIXME What to link to /dev/root? Is it even needed? + printf 'mount -t overlay LiveOS_rootfs -o%s,%s %s\n' "$ROOTFLAGS" \ + 'lowerdir=/run/rootfsbase,upperdir=/run/overlayfs,workdir=/run/ovlwork' \ + "$NEWROOT" > $hookdir/mount/01-$$-live.sh + fi +else + ln -s /dev/mapper/live-rw /dev/root + if [ -z "$DRACUT_SYSTEMD" ]; then + [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS" + printf 'mount %s /dev/mapper/live-rw %s\n' "$ROOTFLAGS" "$NEWROOT" > $hookdir/mount/01-$$-live.sh + fi + ln -s $BASE_LOOPDEV /run/rootfsbase fi need_shutdown diff --git a/modules.d/90dmsquash-live/module-setup.sh b/modules.d/90dmsquash-live/module-setup.sh index 19396a736b..48418a0686 100755 --- a/modules.d/90dmsquash-live/module-setup.sh +++ b/modules.d/90dmsquash-live/module-setup.sh @@ -17,7 +17,7 @@ depends() { # called by dracut installkernel() { - instmods squashfs loop iso9660 + instmods squashfs loop iso9660 overlay } # called by dracut diff --git a/modules.d/90dmsquash-live/parse-dmsquash-live.sh b/modules.d/90dmsquash-live/parse-dmsquash-live.sh index 0386d3427a..a9b78ab559 100755 --- a/modules.d/90dmsquash-live/parse-dmsquash-live.sh +++ b/modules.d/90dmsquash-live/parse-dmsquash-live.sh @@ -57,6 +57,6 @@ info "root was $liveroot, is now $root" # make sure that init doesn't complain [ -z "$root" ] && root="live" -wait_for_dev -n /dev/mapper/live-rw +wait_for_dev -n /run/rootfsbase return 0