Last modified: Sun Jun 2 10:53:14 EDT 2019
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 18.104.22.168 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, the following script converts the initrd of a Slackware 14.0 install disk into a root file system that can run without loading entirely into memory.
#!/bin/bash # 2013-10-18 Based on previous version of sandbox.html. # Convert /img/tmp/slack from initramfs to sandbox so that DFI486 can boot. # Caution. Lots of hardcoded and version-dependent stuff. # Change CDROM to /dev/sr0 or /dev/hdc, depending. CDROM=/dev/hdc ORIGF=/img/tmp/slack/isolinux/initrd.img OUTF=/img/tmp/slack/initrd-ext2.img set -e if [[ `whoami` != root ]]; then echo You must be root to run this script. exit fi # Convert original initrd to ext2. declare -i ORIGSZ=`gzip -dc $ORIGF | wc -c` echo "Original size = $ORIGSZ" # 5 MB is chewed up by internal fragmentation. declare -i EXT2SZ=(ORIGSZ+10000000)/512 echo "Expanded size = $EXT2SZ sectors" dd if=/dev/zero of=$OUTF bs=512 count=$EXT2SZ # losetup syntax breaking change: -s became --show DEV=`losetup -f --show $OUTF` mke2fs -m 0 $DEV mount -t ext2 $DEV /mnt pushd /mnt gzip -dc $ORIGF | cpio -i -d -H newc --no-absolute-filenames cd /tmp umount /mnt losetup -d $DEV echo "$OUTF is created." # Create new, much smaller initrd that mounts it using sandbox. mkinitrd -l ANSI-dvorak -s initrd -L -o stageleft # -L adds dmsetup. rm stageleft cd initrd cp -a /dev/loop0 dev # Add missing device. mkdir mnt2 # Add second mount point. # This patch works for mkinitrd 1.4.7 (Slackware 14.0). # Note that CDROM and EXT2SZ are pasted in. patch -s init <<EOF --- init.orig 2012-09-04 17:44:08.000000000 -0400 +++ init 2013-10-18 @@ -282,10 +282,16 @@ fi # Switch to real root partition: - /sbin/udevadm settle --timeout=10 + /sbin/udevadm settle echo 0x0100 > /proc/sys/kernel/real-root-dev - mount -o ro -t \$ROOTFS \$ROOTDEV /mnt - + mount -t iso9660 -o ro $CDROM /mnt2 + losetup /dev/loop0 /mnt2/initrd-ext2.img + /sbin/dmsetup create sandbox --table "0 $EXT2SZ snapshot /dev/loop0 /dev/ram0 N 1" + /sbin/udevadm settle + mount -t ext2 -o rw /dev/mapper/sandbox /mnt + mkdir /mnt/mnt2 + mount --move /mnt2 /mnt/mnt2 + if [ ! -r /mnt/sbin/init ]; then echo "ERROR: No /sbin/init found on rootdev (or not mounted). Trouble ahead." echo " You can try to fix it. Type 'exit' when things are done." EOF find . | cpio -o -H newc | gzip -9c > $ORIGF cd .. rm -rf initrd popd echo "$ORIGF is replaced."
When you boot the CD, everything should look similar to any other Slackware install except that the installation CD is already mounted as /mnt2. 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.