#!/bin/bash
#
# mount_scratch_overlay: Mounts the pS-Performance Toolkit scratch overlay
#
# chkconfig: 2345 0 99
# description:  The pS-Performance Toolkit LiveCD version mounts a file \
#               on disk to prevent I/O failures if ram fills up.
#

. /etc/rc.d/init.d/functions

start() {
#    # sanity check
#    echo "Are you sure you want to pivot_root?"
#    read VERIFY
#    if [ "$VERIFY" != "yes" ]; then
#    	exit
#    fi
    
	LOG_LOCATION=/var/log
	LOG_FILE=$LOG_LOCATION/"mount_scratch_overlay.log"
    STORE_LOCATION=/mnt/store
    TEMP_ROOT_LOCATION=/mnt/temp_root
    TEMP_ROOT_FILE=/opt/perfsonar_ps/toolkit/scripts/temp_root.img
    SCRATCH_FILE=$STORE_LOCATION/NPTools/scratch
    NUM_LOOPS=16

	date > $LOG_FILE
	uname -a >> $LOG_FILE
    echo -n $"Making more loop devices available... "
    /sbin/MAKEDEV -m $NUM_LOOPS loop &> /dev/null
    if [ -e "/dev/loop$(($NUM_LOOPS-1))" ]; then
        success && echo
    else
        failure
        echo
    fi

    echo -n $"Looking for backing store... "
	echo "Using blkid to find possible data store devices:" >> $LOG_FILE
    # Find any configured block device
    for dev in `blkid -o device -t TYPE='ext3'`; do
		echo "Mounting ext3 block device: $dev" >> $LOG_FILE
        mount -n -t ext3 $dev $STORE_LOCATION &> /dev/null
    
        if [ $? != 0 ]; then
			echo "Failed to mount ext3 block device: $dev" >> $LOG_FILE
            umount $STORE_LOCATION &> /dev/null
            continue
        fi
    
        if [  -d $STORE_LOCATION/NPTools ]; then
			echo "Found data store on: $dev" >> $LOG_FILE
            break
        fi
		
    	echo "Unmounting ext3 block device: $dev" >> $LOG_FILE
        umount $STORE_LOCATION &> /dev/null
    done
    
    if [ ! -d $STORE_LOCATION/NPTools ]; then
        # blkid (in the case of Brian Tierney's machine) was not outputing
        # /dev/sda even though /dev/sda was available, and ext3. To work around
        # this, we manually grot through /proc/partitions looking for ext3
        # devices that blkid didn't display.
		echo "Using /proc/partitions to find possible data store devices:" >> $LOG_FILE
        for dev in `cat /proc/partitions | awk '{ print $4 }'`; do
            if [ -e /dev/$dev ]; then
				echo "Mounting ext3 block device: $dev" >> $LOG_FILE
                mount -n -t ext3 /dev/$dev $STORE_LOCATION &> /dev/null
                if [ $? == 0 ]; then
                    if [  -d $STORE_LOCATION/NPTools ]; then
						echo "Found data store on: $dev" >> $LOG_FILE
                        break
                    fi
                fi
                umount $STORE_LOCATION &> /dev/null
				echo "Unmounting ext3 block device: $dev" >> $LOG_FILE
            fi
        done
    fi
    
    if [ -d $STORE_LOCATION/NPTools ]; then
    	success && echo
    else
    	failure
        echo
    fi

	if [ -d $STORE_LOCATION/NPTools ]; then
    	# mount root readwrite using scratch as the read-write aspect. Uses
	    # pivot_root since the scratch file needs to be mounted outside the
	    # directory tree it's being made read-write against (/).

	    # Create the scratch file if it doesn't already exist
	    if [ ! -f $SCRATCH_FILE ]; then
	        touch $SCRATCH_FILE
	    fi

	    # Resize the scratch file to 800M if it's less than that
	    ScratchSize=$(du -ks $SCRATCH_FILE | cut -f1)
	    if [ ${ScratchSize} -lt 800000 ]; then
	        echo -n $"Resizing scratch file: "
	        dd if=/dev/zero of=$SCRATCH_FILE bs=10M count=80 &> /dev/null
	        success && echo
	    fi

	    # Blow away whatever was in the scratch file
	    echo -n $"Clearing scratch file: "
	    mkfs.ext2 -F $SCRATCH_FILE &> /dev/null
	    success && echo

	    echo -n $"Setting up temporary root: "
	    # Mount the temporary root image
	    mount -n -t ext2 -o loop $TEMP_ROOT_FILE $TEMP_ROOT_LOCATION

	    # Mount scratch inside the temporary root
	    mount -n -t ext2 -o loop $SCRATCH_FILE $TEMP_ROOT_LOCATION/scratch
	    success && echo

	    # AUFS needs to be loaded before we do the pivot_root since that module
	    # isn't necessarily available in our temp root location.
	    modprobe aufs

	    # Swap to the temporary root
	    cd $TEMP_ROOT_LOCATION
	    /sbin/pivot_root . $TEMP_ROOT_LOCATION/sysroot

	    echo -n $"Creating overlay: "
	    # Create the aufs overlay of the old / and the scratch file
	    /bin/mount -t aufs -o br=/scratch:/sysroot=ro none /new_root
	    success && echo

	    echo -n $"Swapping to new root: "
	    # Swap to the overlay as the new root
	    cd /new_root
	    /bin/mkdir -p /new_root/old_temp_root
	    /sbin/pivot_root . /new_root/old_temp_root
	    success && echo

	    # Recreate all the various things that were mounted under the original
	    # root. 
	    echo -n $"Recreating /proc, /sys, /dev: "
	    mount -t proc proc /proc
	    mount -t sysfs sys /sys
	    mkdir -p /dev/shm
	    mount -t tmpfs shm /dev/shm
	    rm -f /dev/null
	    cp -Ra /old_temp_root/sysroot/dev/* /dev
	    mount -t devpts devpts /dev/pts
	    if [ -d /proc/sys/fs/binfmt_misc ]; then
	        mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
	    fi

	    success && echo

	    # These umounts will likely fail, but they clean up the view of 'df'.
	    echo -n $"Cleaning up df output: "
	    umount $TEMP_ROOT_LOCATION/scratch &> /dev/null
	    umount $TEMP_ROOT_LOCATION &> /dev/null
	    umount $STORE_LOCATION &> /dev/null
	    umount -l /old_temp_root &> /dev/null
	    rmdir /old_temp_root &> /dev/null
	    success && echo
	fi
}

# See how we were called.
case "$1" in
	start)
		start
		;;
	stop)
		stop
		;;
	*)
		echo $"Usage: $0 {start|stop}"
		;;
esac
exit $RETVAL
