I have a virtual machine (VMM is Xen 3.3) equipped with two IDE HDD's (/dev/hda and /dev/hdb). The root file system is in /dev/hda1, where Scientific Linux 5.4 is installed. /dev/hdb contains an empty ext2 file system.

I want to protect the root file system from writes by the VM by using aufs (AnotherUnionFS) to layer a writable file system on top of the root file system. The changes to / will be written to the file system located on /dev/hdb. (Furthermore, outside the VM, the file backing the /dev/hda will also be set to read-only permissions, so the VMM should also prevent the VM from modifying at that level.) (The purpose of this setup: be able to corrupt a virtual machine using software-implemented fault injection but preserve the file system image in order to quickly reboot the VM to a fault-free state.)

How do I get an initrd init script to do the necessary mounts to create the union file system?

I've tried 2 approaches:

  1. I've tried modifying the nash script that mkinitrd creates, but I don't know what setuproot and switchroot do and how to make them use my aufs as the new root. Apparently, nobody else here knows either. (EDIT: I take that back.)

  2. I've tried building a LiveCD (using linux-live-6.3.0) and then modifying the Bash /linuxrc script from the generated initrd, and I got the mounts correct, but the final /sbin/init complains about /dev/initctl.

Specifically, my /linuxrc mounts the aufs at /union. The last few lines of /linuxrc effectively do the following:

cd /union
mkdir -p mnt/live
pivot_root . mnt/live
exec sbin/chroot . sbin/init </dev/console >/dev/console 2>&1

When init starts, it outputs something like init: /dev/initctl: No such file or directory. What is supposed to create this FIFO? I found no such filename in the original linuxrc and liblinuxlive scripts.

I tried creating it via "mkfifo /dev/initctl", but then init complained about a timeout opening or writing to the FIFO.

Would appreciate any help or pointers. Thanks.


If you're already using a virtualization solution, why are you going through all this trouble? The simplest solution would be to use something like LVM on your host, which already has snapshot support, and present a snapshot to your VM. That is:

  • Create a logical volume (LV) that will hold your root filesystem.
  • Create a snapshot of this LV
  • Configure your VM to boot from the snapshot.

If you want to revert back to the clean filesystem, delete the snapshot and recreate it. Easy, and no fiddling about with initrd or aufs -- in fact, it doesn't require any modifications to the guest OS.


As phresus answered, init creates /dev/initctl.

The problem I was having was that my /linuxrc script was not running with PID 1. Thus, when it executed init, it also was not running with PID 1. init not running as PID 1 behaves as telinit.

To get /linuxrc to run with PID 1, I needed the following on the kernel boot line: root=/dev/ram0 rw init=/linuxrc, as described in this forum.

Now it's all working. With the VM booted, the output of mount is

aufs on / type aufs (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)

Yay! BTW, is it kosher to mark my own answer as "the answer"?

  • Go for it! It's your question, after all, and none of us got you all the way there.
    – phresus
    Dec 18 '09 at 13:01

Init itself generally creates initctl. However, you need the following:

/etc/inittab must contain an entry for initdefault. Secondly, send SIGUSR1 to init after /dev is remounted on the proper root, which will force init to reread the configuration.

  • there is an initdefault entry in my /etc/inittab. I just discovered by running ash within /linuxrc just before the pivot_root that /linuxrc is not running as PID 1 (its PID was 300). That's odd. Doesn't this mean that when it exec's init, init will behave as telinit, since its PID is not 1? Frustrating. Dec 16 '09 at 23:29
  • You can either pass init=/linuxrc or rename /linuxrc to /sbin/init (which is just a shell script in the initrd).
    – phresus
    Dec 17 '09 at 12:40
  • I tried adding init=/linuxrc and it still didn't run with PID 1. Apparently I also needed root=/dev/ram0 rw. I have no idea why this would make a difference. Any enlightenment would be appreciated! Dec 17 '09 at 23:06
  • The initrd is pulled out to a ramdisk, and that's treated as your root until switchroot or pivot_root. Why it's necessary for linuxrc to get PID 1, I'm not sure about
    – phresus
    Dec 18 '09 at 13:00

The right solution is to use ZFS for virtual machine. Before you do experiment, make a snapshot. Only takes less than a second and one short line command: zfs snapshot (your volume) snapshotname. Then you can do whatever, even format the volume. Now you want to restore. One short line command: zfs rollback thesnapshotname. If you really formatted the volume, it takes a while to rollback, otherwise, few seconds to finish the rollback operation. All change after the snapshot will disappear.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.