From 2e44f115b936960b460242c2ce90d96cc6379790 Mon Sep 17 00:00:00 2001 From: Jeremy Katz Date: Wed, 22 Jul 2009 15:31:18 -0400 Subject: [PATCH] Add basic support for dmsquashed live images Fedora/Red Hat live images are implemented as an ext3fs inside of a squashfs. Writability is achieved with a device-mapper snapshot on top of that. This gives the basic support without a lot of things like persistent overlays, iso md5sum checking, etc and also with a new basic syntax that has to be specified as root=live:LABEL=... --- modules.d/90dmsquash-live/check | 12 ++ .../90dmsquash-live/dmsquash-live-genrules.sh | 13 ++ modules.d/90dmsquash-live/dmsquash-live-root | 164 +++++++++++++++++++++ modules.d/90dmsquash-live/install | 12 ++ modules.d/90dmsquash-live/parse-dmsquash-live.sh | 31 ++++ 5 files changed, 232 insertions(+) create mode 100755 modules.d/90dmsquash-live/check create mode 100644 modules.d/90dmsquash-live/dmsquash-live-genrules.sh create mode 100755 modules.d/90dmsquash-live/dmsquash-live-root create mode 100755 modules.d/90dmsquash-live/install create mode 100755 modules.d/90dmsquash-live/parse-dmsquash-live.sh diff --git a/modules.d/90dmsquash-live/check b/modules.d/90dmsquash-live/check new file mode 100755 index 0000000..54e5007 --- /dev/null +++ b/modules.d/90dmsquash-live/check @@ -0,0 +1,12 @@ +#!/bin/sh + +# if dmsetup is not installed, then we cannot support fedora/red hat +# style live images +which dmsetup >/dev/null 2>&1 || exit 1 + +# a live host-only image doesn't really make a lot of sense +if [ "$1" = "-h" ] ; then + exit 1 +fi + +exit 0 diff --git a/modules.d/90dmsquash-live/dmsquash-live-genrules.sh b/modules.d/90dmsquash-live/dmsquash-live-genrules.sh new file mode 100644 index 0000000..a3858e1 --- /dev/null +++ b/modules.d/90dmsquash-live/dmsquash-live-genrules.sh @@ -0,0 +1,13 @@ +if [ "${root%%:*}" = "live" ]; then + ( + printf 'KERNEL=="%s", SYMLINK+="live"\n' \ + ${root#live:/dev/} + printf 'SYMLINK=="%s", SYMLINK+="live"\n' \ + ${root#live:/dev/} + printf 'KERNEL=="%s", RUN+="/sbin/initqueue --onetime /sbin/dmsquash-live-root $env{DEVNAME}"\n' \ + ${root#live:/dev/} + printf 'SYMLINK=="%s", RUN+="/sbin/initqueue --onetime /sbin/dmsquash-live-root $env{DEVNAME}"\n' \ + ${root#live:/dev/} + + ) >> /etc/udev/rules.d/99-live-mount.rules +fi diff --git a/modules.d/90dmsquash-live/dmsquash-live-root b/modules.d/90dmsquash-live/dmsquash-live-root new file mode 100755 index 0000000..fcce65b --- /dev/null +++ b/modules.d/90dmsquash-live/dmsquash-live-root @@ -0,0 +1,164 @@ +#!/bin/sh + +. /lib/dracut-lib.sh +[ -f /tmp/root.info ] && . /tmp/root.info + +PATH=$PATH:/sbin:/usr/sbin + +if getarg rdlivedebug; then + exec > /tmp/liveroot.$$.out + exec 2>> /tmp/liveroot.$$.out + set -x +fi + +[ -z "$1" ] && exit 1 +livedev="$1" + +# FIXME: do cd check here + +getarg ro && liverw=ro +getarg rw && liverw=rw +[ -z "$liverw" ] && liverw=ro +# mount the backing of the live image first +mount -n -t $fstype -o $liverw $livedev $NEWROOT +RES=$? +if [ "$RES" != "0" ]; then + echo "Failed to mount block device of live image" + exit 1 +fi + +# need to handle parsing out some more pieces; keeping track of them here +overlay=off +live_dir="LiveOS" +live_ram=0 +reset_overlay=0 +check=0 + +# overlay setup helper function +do_live_overlay() { + # create a sparse file for the overlay + # overlay: if non-ram overlay searching is desired, do it, + # otherwise, create traditional overlay in ram + OVERLAY_LOOPDEV=$( losetup -f ) + + l=$(blkid -s LABEL -o value $livedev) || l="" + u=$(blkid -s UUID -o value $livedev) || u="" + + if ( echo $overlay | grep -q ":" ); then + # pathspec specified, extract + pathspec=$( echo $overlay | sed -e 's/^.*://' ) + elif [ "x${overlay}" != "xoff" ]; then + pathspec="/${live_dir}/overlay-$l-$u" + fi + + if [ -z "$pathspec" -o "$pathspec" == "auto" ]; then + pathspec="/${live_dir}/overlay-$l-$u" + fi + devspec=$( echo $overlay | sed -e 's/:.*$//' ) + + # need to know where to look for the overlay + setup="" + if [ -n "$devspec" -a -n "$pathspec" -a "${overlay}" != "off" ]; then + mkdir /overlayfs + mount -n -t auto $devspec /overlayfs || : + if [ -f /overlayfs$pathspec -a -w /overlayfs$pathspec ]; then + losetup $OVERLAY_LOOPDEV /overlayfs$pathspec + if [ -n "$reset_overlay" ]; then + dd if=/dev/zero of=$OVERLAY_LOOPDEV bs=64k count=1 2>/dev/null + fi + setup="yes" + fi + umount -l /overlayfs || : + fi + + if [ -z "$setup" ]; then + if [ -n "$devspec" -a -n "$pathspec" ]; then + echo "Unable to find persistent overlay; using temporary" + sleep 5 + fi + + dd if=/dev/null of=/overlay bs=1024 count=1 seek=$((512*1024)) 2> /dev/null + losetup $OVERLAY_LOOPDEV /overlay + fi + + # set up the snapshot + echo 0 `blockdev --getsize $BASE_LOOPDEV` snapshot $BASE_LOOPDEV $OVERLAY_LOOPDEV p 8 | dmsetup create live-rw +} + +# 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 $NEWROOT/${live_dir}/osmin.img ]; then + OSMINSQFS=$NEWROOT/${live_dir}/osmin.img +fi + +if [ -n "$OSMINSQFS" ]; then + # decompress the delta data + dd if=$OSMINSQFS of=/osmin.img 2> /dev/null + OSMIN_SQUASHED_LOOPDEV=$( losetup -f ) + losetup -r $OSMIN_SQUASHED_LOOPDEV /osmin.img + mkdir -p /squashfs.osmin + mount -n -t squashfs -o ro $OSMIN_SQUASHED_LOOPDEV /squashfs.osmin + OSMIN_LOOPDEV=$( losetup -f ) + losetup -r $OSMIN_LOOPDEV /squashfs.osmin/osmin + umount -l /squashfs.osmin +fi + +# we might have just an embedded ext3 to use as rootfs (uncompressed live) +if [ -e $NEWROOT/${live_dir}/ext3fs.img ]; then + EXT3FS="$NEWROOT/${live_dir}/ext3fs.img" +fi + +if [ -n "$EXT3FS" ] ; then + BASE_LOOPDEV=$( losetup -f ) + losetup -r $BASE_LOOPDEV $EXT3FS + umount -l $NEWROOT + + do_live_from_base_loop +fi + +# we might have an embedded ext3 on squashfs to use as rootfs (compressed live) +if [ -e $NEWROOT/${live_dir}/squashfs.img ]; then + SQUASHED="$NEWROOT/${live_dir}/squashfs.img" +fi + +if [ -e "$SQUASHED" ] ; then + if [ "$live_ram" == "1" ] ; then + echo "Copying live image to RAM..." + echo "(this may take a few minutes)" + dd if=$SQUASHED of=/squashed.img bs=512 2> /dev/null + umount -n $NEWROOT + echo "Done copying live image to RAM." + eject -p $livedev || : + SQUASHED="/squashed.img" + fi + + SQUASHED_LOOPDEV=$( losetup -f ) + losetup -r $SQUASHED_LOOPDEV $SQUASHED + mkdir -p /squashfs + mount -n -t squashfs -o ro $SQUASHED_LOOPDEV /squashfs + + BASE_LOOPDEV=$( losetup -f ) + losetup -r $BASE_LOOPDEV /squashfs/LiveOS/ext3fs.img + + umount -l /squashfs + if [ "$live_ram" == "0" ] ; then + umount -l $NEWROOT + fi + + do_live_from_base_loop +fi + +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 --getsize $BASE_LOOPDEV ) snapshot $BASE_LOOPDEV $OSMIN_LOOPDEV p 8" | dmsetup create --readonly live-osimg-min +fi + +ln -s /dev/mapper/live-rw /dev/root +printf '/bin/mount /dev/mapper/live-rw %s\n' "$NEWROOT" > /mount/01-$$-live.sh + +exit 0 diff --git a/modules.d/90dmsquash-live/install b/modules.d/90dmsquash-live/install new file mode 100755 index 0000000..ff60518 --- /dev/null +++ b/modules.d/90dmsquash-live/install @@ -0,0 +1,12 @@ +#!/bin/bash +inst dmsetup +inst blkid +inst dd +inst losetup +inst eject +inst blockdev +inst_hook cmdline 30 "$moddir/parse-dmsquash-live.sh" +inst_hook pre-udev 30 "$moddir/dmsquash-live-genrules.sh" +inst "$moddir/dmsquash-live-root" "/sbin/dmsquash-live-root" +# should probably just be generally included +inst_rules 60-cdrom_id.rules diff --git a/modules.d/90dmsquash-live/parse-dmsquash-live.sh b/modules.d/90dmsquash-live/parse-dmsquash-live.sh new file mode 100755 index 0000000..55de0a2 --- /dev/null +++ b/modules.d/90dmsquash-live/parse-dmsquash-live.sh @@ -0,0 +1,31 @@ +# live images are specified with +# root=live:backingdev + +echo "parsing for live" +[ -z "$root" ] && root=$(getarg root=) + +if [ "${root%%:*}" = "live" ] ; then + liveroot=$root +fi + +[ "${liveroot%%:*}" = "live" ] || return + +case "$liveroot" in + live:LABEL=*|LABEL=*) + root="${root#live:}" + root="$(echo $root | sed 's,/,\\x2f,g')" + root="live:/dev/disk/by-label/${root#LABEL=}" + rootok=1 ;; + live:UUID=*|UUID=*) + root="${root#live:}" + root="live:/dev/disk/by-uuid/${root#UUID=}" + rootok=1 ;; + /dev/*) + root="live:${root}" + rootok=1 ;; +esac +echo "root was $root, liveroot is now $liveroot" + + +# make sure that init doesn't complain +[ -z "$root" ] && root="live" -- 2.7.4