# unionfs: running of ro mounted harddisk with ramdisk on top

## +O!

Hello there,

I need a system that allows me to cut the power at any moment without the filesystem getting corrupted.

A UPS is not the solution, in fact I want the exact opposite : I have to functionally test some boards, and if something goes wrong I need to cut the power immediately.  So : there is no data to lose, I just want to prevent having to restore an image because the filesystem is corrupted every couple of days.

In fact what I'm looking for is a live cd kind of solution : the root filesystem on a read-only medium with a ramdisk to store the things that really need to be rw.

So this is what I came up with : boot from an initrd, write an initialization script that mounts the root filesystem ro, create a union filesystem with ramdisk on top of "/".  After that the normal init is called.

It's working but I need some help to fine tune this :

There are 4 open issues :

1) What should I put in fstab for the root filesystem?  And anyway, is it important, I mean I have mounted the root filesystem myself ?

2) After my linurc ran, during normal init "Remounting root filesytem read-only (if necessary)…"  is marked with  "!!" instead of "ok".  Immediately after that during "Cheking root filesystem…" I get this warning :

```
/dev/hda8 is mounted.

WARNING!!! Running e2fsck on a mounted filesystem may cause SEVERE filesystem damage.

Do you really want to continue (y/n)?
```

Typing y or n doesn't make much difference here, the filesystem is ro anyway …

After that the system tries 

```
Remounting root filesystem read/write…
```

  Of course this fails too : 

```
Root filesystem could not be mounted read/write :( [!!]
```

After pressing Control-D init continues without any further warnings or errors.  Everything seems to work normally.  :Very Happy:  !

3) After "shutdown -h now"  the system doesn't power down after "Unmounting filesystems…".  Instead it displays this message "INIT: no more processes left in this runlevel".

OK, ok, I don't really need this since I'm planning to shutdown the power without doing the "shutdown -h now" but it would be nice to solve this one too, are at least understand why shutdown is behaving this way.

4) Really a minor issue is cleaning up the old root mount points : umount old-root/old-ram-root in linuxrc doesn't work : device busy.  Once the system is entirely booted this command doés work.  What's the trick to be able to umount old-root and old-ram-root ?  Some experiments with mount -o move did not yield the expected result …

This is my grub.conf :

```
default 0

timeout 2

splashimage=(hd0,5)/grub/splash.xpm.gz

title=Gentoo Linux 2.6.11-r4 - Ramdisk : Default for Functional testing.

root (hd0,5)

kernel (hd0,5)/kernel-2.6.11-gentoo-r4 root=/dev/ram0 ro init=/linuxrc vga=775

initrd (hd0,5)/initrd

title=Booting Debug

root (hd0,5)

kernel (hd0,5)/kernel-2.6.11-gentoo-r4 root=/dev/ram0 ro init=/bin/sh vga=775

initrd (hd0,5)/initrd

title=Gentoo Linux 2.6.11-r4 - No ramdisk : for system maintenance.

root (hd0,5)

kernel /kernel-2.6.11-gentoo-r4 root=/dev/hda8 vga=775

title=Gentoo Linux 2.6.9-r6 - Old Kernel

root(hd0,5)

kernel /kernel-2.6.9-gentoo-r6 root=/dev/hda8

title=Windows 2000 Pro

rootnoverify (hd0,0)

makeactive

chainloader +1
```

My linuxrc : 

```
#!/bin/sh 

 

# Get kernel CMDLINE 

/bin/mount -t proc none /proc 

CMDLINE=`cat /proc/cmdline` 

/bin/umount /proc 

# Mount the real root 

/bin/mount -t ext3 -r /dev/hda8 /real-root

  

# Pivot root into real root file system on Hard Disk

cd /real-root 

/bin/pivot_root . old-ram-root

# Make union = "/" with a ramdisk on top of it

/sbin/modprobe unionfs

/bin/mount -t tmpfs -o size=64m RootRamDisk /RootRamDisk

/bin/mount -t unionfs -o dirs=/RootRamDisk=rw:/=ro union /union

# Pivot root and start real init 

cd /union

/sbin/pivot_root . old-root

/bin/umount old-root/old-ram-root

exec /bin/chroot . /sbin/init ${CMDLINE} <dev/console >dev/console 2>&1 
```

I'm not sure what I shoul put in fstab for the root filesystem :

```
# /etc/fstab: static file system information.

# $Header: /home/cvsroot/gentoo-src/rc-scripts/etc/fstab,v 1.14 2003/10/13 20:03:38 azarah Exp $

#

# noatime turns off atimes for increased performance (atimes normally aren't

# needed; notail increases performance of ReiserFS (at the expense of storage

# efficiency).  It's safe to drop the noatime options if you want and to 

# switch between notail and tail freely.

# <fs>           <mountpoint>    <type>   <opts>        <dump/pass>

# NOTE: If your BOOT partition is ReiserFS, add the notail option to opts.

/dev/hda6 /boot  ext2 noauto,noatime  1 2

/dev/hda7 none  swap sw   0 0

/dev/hda8 /         ext3 noatime   0 1

/dev/hda9 /mnt/DataFAT vfat noauto,noatime,users 0 2

/dev/sda1 /mnt/SCSI_1 vfat noauto,noatime,users 0 2

/dev/sda2 /mnt/SCSI_2 vfat noauto,noatime,users 0 2

#/dev/sdb1 /mnt/UsbStick vfat noauto,noatime,users 0 0

/dev/hdb1 /mnt/CF  vfat noauto,noatime,users 0 0

none        /proc     proc    defaults             0 0

none        /dev/shm  tmpfs   nodev,nosuid,noexec  0 0

/dev/cdroms/cdrom0    /mnt/cdrom    auto      noauto,user    0 0

#none        /proc/bus/usb   usbfs         defaults      0 0
```

```
bash-2.05b# mount

/dev/hda8 on / type ext3 (rw,noatime)

/dev/root on /old-root/old-ram-root type ext2 (ro)

/dev/hda8 on /old-root type ext3 (ro)

RootRamDisk on /old-root/RootRamDisk type tmpfs (rw)

none on /proc type proc (rw)

none on /sys type sysfs (rw)

none on /dev type ramfs (rw)

none on /dev/pts type devpts (rw)

none on /dev/shm type tmpfs (rw,noexec,nosuid,nodev)

none on /proc/bus/usb type usbfs (rw)
```

This is after I've been working on the system for like an hour (kde, surving, copy/pasting, editing files in kate ...)

```
Filesystem            Size  Used Avail Use% Mounted on

/dev/hda8             3.8G  2.8G  796M  79% /

/dev/root             3.9M  2.2M  1.6M  58% /old-root/old-ram-root

/dev/hda8             3.7G  2.8G  753M  79% /old-root

RootRamDisk            64M   21M   44M  33% /old-root/RootRamDisk

none                  247M     0  247M   0% /dev/shm

```

----------

## +O!

 :Embarassed:  ^ UP ^  :Embarassed: 

Nobody ?  Really need some help to get this working ...

Greetz, positivo!

----------

## janwolff

Hello +O!

1) Dont include a line for your root partition in fstab. This helps me for discless clients that get / mounted via nfs.

2,3) Pass the parameter cdboot to the kernel on startup. This makes the gentoo-init scripts to omit unnecessary stuff like rootfs checking on startup.

Another Possibility is to create a file named fastboot in /.

/etc/conf.d/local.start:

```
touch /fastboot
```

The problem on shutdown is that the root fs gets unmounted before shutdown is complete. The same can happen to a discless client at netmount stop.

4) Dont know exactly about this one. Perhaps try sync before or use fuser to find the process accessing the fs.

What is in pivot_root ?

Hope this helps.

-Jan

----------

## +O!

I didn't have a chance to try you're suggestions until this morning   :Embarassed: 

But my system is booting whitout any errors now.  Thanks a bunch   :Razz: 

I had some problems with passing the CDBOOT parameter.  I had just put CDBOOT on the command line, this had no effect.  I noticed in the init scripts that they checked on the size of CDBOOT like this: -s "${CDBOOT}".  I tried echo $"{CDBOOT}" in a shell, CDBOOT seemed to be empty.  So I tried to assign a value to CDBOOT.  echo $"{CDBOOT}" still comes back empty but now at least the init scripts behave as expected, the filesystems are no longer checked.

However there was still one problem : the init script checkroot tries to remount the root filesystem in rw mode.  Unionfs doesn't seem to support remount and the init script stopped with a "Root filesystem could not be mounted read/write  :Sad: ".  Since the filesystem IS already mounted r/w I decided to edit checkroot (I have no time left to look for a better sollution that doesn't imply changing an init script    :Sad: 

```
#!/sbin/runscript

# Copyright 1999-2005 Gentoo Foundation

# Distributed under the terms of the GNU General Public License v2

depend() {

        before *

}

start() {

        local retval=0

        if [[ ! -f /fastboot && -z ${CDBOOT} ]] && ! is_net_fs / ; then

                if touch -c / >& /dev/null ; then

                        ebegin "Remounting root filesystem read-only"

                        mount -n -o remount,ro /

                        eend $?

                fi

                if [[ -f /forcefsck ]] || get_bootparam "forcefsck" ; then

                        ebegin "Checking root filesystem (full fsck forced)"

                        fsck -C -a -f /

                        # /forcefsck isn't deleted because checkfs needs it.

                        # it'll be deleted in that script.

                        retval=$?

                (..)

#        fi           I removed this and ...

        # Should we mount root rw ?

        if mount -vf -o remount / 2> /dev/null | \

           awk '{ if ($6 ~ /rw/) exit 0; else exit 1; }'

        then

                ebegin "Remounting root filesystem read/write"

                mount -n -o remount,rw / &> /dev/null

                if [[ $? -ne 0 ]] ; then

                        eend 2 "Root filesystem could not be mounted read/write :("

                        if [[ ${RC_FORCE_AUTO} != "yes" ]] ; then

                                /sbin/sulogin ${CONSOLE}

                        fi

                else

                        eend 0

                fi

        fi

fi   #   ... added this => When booting with ramdisk and / ro the remount will not be executed.

    #    when booted in maintenance mode everything behaves as before.

(..)

}

# vim:ts=4

```

-> Where can I find more info on what boot parameters are allowed and how to use them ???

Grtz, +O!

p.s. : I left fstab unchanged as the system seems to be working OK.

----------

## janwolff

The cdboot kernel parameter is parsed in the file livecd-functions.sh from the livecd-tools package.

I found it to be easier to replace the checkroot script with a fake one.

```

#!/sbin/runscript

#jw, faking succesful operation for readonly diskless client

depend() {

        before *

}

start() {

        return 0

}

```

As everything what checkroot does is useless in a "readonly /" scenario, this approach solves all problems with the dependancies of other init-scripts.

Your initrd-script should try to create a valid /etc/mtab or replace /etc/mtab by a symbolic link to /proc/mounts.

I think you can not unmount the initial ramdisk, because the /bin/sh that is interpreting your /linuxrc is still running in this directory.

You can unmount the initial ramdisk with the following construction.

```

exec chroot . /bin/sh -c 'umount -n old-root/old-ram-root ; exec /sbin/init' ${CMDLINE} <dev/console >dev/console 2>&1

```

----------

