]> git.ipfire.org Git - thirdparty/dracut.git/commitdiff
Add basic support for dmsquashed live images
authorJeremy Katz <katzj@redhat.com>
Wed, 22 Jul 2009 19:31:18 +0000 (15:31 -0400)
committerHarald Hoyer <harald@redhat.com>
Tue, 4 Aug 2009 14:25:42 +0000 (16:25 +0200)
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 [new file with mode: 0755]
modules.d/90dmsquash-live/dmsquash-live-genrules.sh [new file with mode: 0644]
modules.d/90dmsquash-live/dmsquash-live-root [new file with mode: 0755]
modules.d/90dmsquash-live/install [new file with mode: 0755]
modules.d/90dmsquash-live/parse-dmsquash-live.sh [new file with mode: 0755]

diff --git a/modules.d/90dmsquash-live/check b/modules.d/90dmsquash-live/check
new file mode 100755 (executable)
index 0000000..54e5007
--- /dev/null
@@ -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 (file)
index 0000000..a3858e1
--- /dev/null
@@ -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 (executable)
index 0000000..fcce65b
--- /dev/null
@@ -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 (executable)
index 0000000..ff60518
--- /dev/null
@@ -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 (executable)
index 0000000..55de0a2
--- /dev/null
@@ -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"