Last modified: Mon Oct 6 15:45:46 EDT 2008
The goal is to set up a writable image of a read-only file system so that the changes (and only the changes) are saved in memory. The following was tested with mainline kernel version 2.6.26.5 and Slackware 12.1.
# Preconditions: # - There is an ext2 file system on /dev/sda1. # - Nothing else is trying to use /dev/sda1 concurrently. # - Kernel has RAM block device support enabled. DEV=/dev/sda1 SZ=`blockdev --getsz $DEV` dmsetup create sandbox --table "0 $SZ snapshot $DEV /dev/ram0 N 1" # /dev/ram0 = Copy-On-Write (COW) device # N = non-persistent # 1 = chunksize in 512 B sectors mount -t ext2 -o rw /dev/mapper/sandbox /mnt cd /mnt # Play in sandbox. If /dev/ram0 is exhausted, I/O operations start failing en masse. umount /mnt dmsetup remove sandbox # Postconditions: # - Sandbox goes poof. # - /dev/sda1 is unchanged.
This approach works at the raw device level. A similar thing can be accomplished at the file system level using unionfs if your kernel supports that. (It is not yet in the mainline kernel.)
A Live CD can work in at least four ways: initramfs, tmpfs, unionfs, or the device mapper. To demonstrate how a Live CD could be constructed using the device mapper, this section describes how to convert the initrd of a Slackware 12.1 install disk into a root file system that can run without loading entirely into memory.
As a starting point, we assume that you have the relevant parts of the Slackware 12.1 distribution in ~/CD.
The following commands convert the Slackware initrd into a 40 MiB ext2 image. Substitute the root file system of your choice.
dd if=/dev/zero of=~/CD/initrd-ext2 bs=1M count=40 DEV=`losetup -f -s ~/CD/initrd-ext2` mke2fs -m 0 $DEV mount -t ext2 $DEV /mnt cd /mnt gzip -dc ~/CD/isolinux/initrd.img | cpio -i -d -H newc --no-absolute-filenames cd umount /mnt
Now we need a new initrd. As a shortcut, we will modify one that is
constructed by mkinitrd.
cd mkinitrd -s temp-tree -o /dev/null
We are going to need the dmsetup program and an extra mount point.
cd temp-tree cp -a /sbin/dmsetup.static sbin mkdir mnt2
Then we need to modify the init script to mount initrd-ext2 and make it writable. Where init says this:
# Switch to real root partition: echo 0x0100 > /proc/sys/kernel/real-root-dev mount -o ro -t $ROOTFS $ROOTDEV /mnt
Change it to this:
# Switch to real root partition: echo 0x0100 > /proc/sys/kernel/real-root-dev mount -t iso9660 -o ro /dev/sr0 /mnt2 losetup /dev/loop0 /mnt2/initrd-ext2 /sbin/dmsetup.static create sandbox --table "0 81920 snapshot /dev/loop0 /dev/ram0 N 1" mount -t ext2 -o rw /dev/mapper/sandbox /mnt mkdir /mnt/mnt2 mount --move /mnt2 /mnt/mnt2
In the above syntax, /dev/sr0 is the device name that is assigned to the CD-ROM. With libata, you get /dev/sr0; with the old ATA/ATAPI/MFM/RLL drivers, you get /dev/hd? something instead. 81920 is just the size, in 512 B sectors, of the 40 MiB ext2 image we created earlier. Substitute the correct size for your root file system.
To avoid getting misleading messages during the boot process, change the contents of the file initrd-name from "null" to something more relevant (like "initrd").
Now replace the Slackware initrd with our new, smaller one:
find . | cpio -o -H newc | gzip -9c > ~/CD/isolinux/initrd.img
That's it. Wrap it up and burn it:
cd ~/CD mkisofs -o /root/slackware.iso \ -V "Slackware Install" -A "Slackware Install" \ -no-pad -iso-level 4 -r \ -no-emul-boot -boot-load-size 4 -boot-info-table \ -sort isolinux/iso.sort -b isolinux/isolinux.bin -c isolinux/isolinux.boot \ -hide isolinux/isolinux.boot \ . cdrecord -v dev=/dev/cdwriter -dao ~/slackware.iso
When you boot the CD, everything should look similar to any other Slackware install you ever did, except that when you log in as root you'll see that the installation CD is already mounted as /mnt2.
Note: Since the root file system is now running off of the CD instead of from memory, you cannot eject the CD, and you can only install what will fit on one disc.