This is a quick how-to for achieving a clean "filesystem" unmount on shutdowns (Updated 5-July-2010). Currently tested for full hdd installs (ext2, PUPMODE=2), frugal installs (ext2, PUPMODE=12) and frugal ataflash installs (ext2, PUPMODE=13) only.
Primary work was done on puppy412 and further tests were later done on puppy421 and puppy431. If you're using a different frugal install mode (CF/usb/etc) then I'm still keen to know your result.
There are now two (2) different method suitable for different needs:
1. If you're basically using full hdd installs or frugals on vfat then method 1 is sufficient. This is the easiest with minimal changes.
2. If you want a complete unmount then method 2 is what you need. This requires initrd.gz minor surgery and substantial changes to the shutdown script.
- -----------------------------------------------
METHOD 1 : HDD OR SAVEFILE UNMOUNT
-----------------------------------------------
2. Look for this code block at the end of rc.shutdown (this sample is from puppy412)
Code: Select all
#v2.13 menno suggests this improvement...
STRAYPARTD="`cat /proc/swaps | grep "/dev/" | cut -f 1 -d " " | tr "\n" " "`"
for ONESTRAY in $STRAYPARTD
do
echo "Swapoff $ONESTRAY"
swapoff $ONESTRAY
done
sync
Code: Select all
# Stop udev & loggers
killall udevd &>/dev/null
killall klogd &>/dev/null
killall syslogd &>/dev/null
# Patriot's lame "unmount of rootfs"
if [ $PUPMODE -ne 5 ]; then
case $PUPMODE in
2) pupFS=$(awk '/\/dev\/root/ {print $3}' /proc/mounts)
mount -o remount,ro -t $pupFS /dev/root /
sync
;;
*) uniFS=$(awk '/unionfs/ {print $3}' /proc/mounts)
pupFS=$(awk '/pup_rw/ {print $3}' /proc/mounts)
if [ "$uniFS" -a "$pupFS" != "tmpfs" ]; then
mkdir -p /tmp/unrootfs
sync
mount -o remount,prepend:/tmp/unrootfs,xino=/tmp/unrootfs/xino -t $uniFS / /
sync
fi
mount -o remount,ro /initrd${SAVE_LAYER}
sync
;;
esac
fi
5. You must now manually fsck your savefile (or hdd) by either :
- a) doing a pfix=fsck on your next reboot (for frugals)
b) boot puppy in ram (pfix=ram) and do a e2fsck of your savefile or hdd
c) whatever fsck method that you're comfy with
- ---------------------------------------------------------------------------
METHOD 2 : ROOTFS COMPLETE-THRU-THE-LAYERS UNMOUNT
---------------------------------------------------------------------------
This is a quick how-to for a complete-thru-the-layers clean unmount on shutdowns. I have done some confidence testing with these scripts but they have not gone through any rigorous testing cycle (confidence testing only includes booting with pup_x.sfs, pup_x.sfs+zdrv to pup_x.sfs+zdrv+devx+ksrc). I am using it now on my daily systems and I believe that the core logics are pretty stable by now.
The affected files are init in initrd.gz, /sbin/poweroff, /sbin/reboot, /etc/rc.d/rc.shutdown, /etc/profile, ~/.bashrc
Changelog:
06-June-2010: first published
11-June-2010: fix for stray process on puppyfs (thanks to gyro)
12-June-2010: improvements and fixes for command line interface (CLI).
15-June-2010: adjustments for fresh setup (PUPMODE=5)
05-July-2010: fix for loop device detach list (thanks to gyro)
1. Modify /sbin/reboot to :
Code: Select all
#!/bin/sh
[ "$PPID" = "1" ] && exec /etc/rc.d/rc.shutdown reboot
echo -e "\nTo reboot, select \e[0;36m[Reboot]\e[0m from the main menu or"
echo -e "use \e[0;36m'wmreboot'\e[0m from within a shell/script.\n"
Code: Select all
#!/bin/sh
[ "$PPID" = "1" ] && exec /etc/rc.d/rc.shutdown poweroff
echo -e "\nTo poweroff, select \e[0;36m[Poweroff]\e[0m from the main menu or"
echo -e "use \e[0;36m'wmpoweroff'\e[0m from within a shell/script.\n"
Code: Select all
#v4.00 run e3vi whenever vi excuted...
alias vi=e3vi
# Part of clean-unmount-on-shutdowns CLI requirement
alias poweroff="exec poweroff"
alias reboot="exec reboot"
alias xwin="exec xwin"
#v2.12
#xorgwizard creates this file, run once only...
if [ ! -f /tmp/bootcnt.txt ];then
[ -f /etc/resolutionfix ] && eval `cat /etc/resolutionfix`
fi
Code: Select all
. /etc/profile
# unalias for vt
unalias poweroff reboot
# Prevent X recursions in vt
alias X='echo -e "\nX-windows is \e[1;31malready running.\e[0m\n"'
alias Xorg=X
alias Xvesa=X
alias xwin=X
- The first added block is at the beginning of the script, before the clear statement
Code: Select all
...
...
...
if [ -z "$1" ]; then
exit 1
else
case $1 in
poweroff|reboot)
applet=$1
shtty=$(tty)
;;
*)
exit 2
;;
esac
fi
clear
exec 1>/dev/null 2>&1
echo "System is shutting down ..." >/dev/console
- Everything past exec /cleanup can be commented or removed
Code: Select all
...
...
...
#v2.13 menno suggests this improvement...
STRAYPARTD="`cat /proc/swaps | grep "/dev/" | cut -f 1 -d " " | tr "\n" " "`"
for ONESTRAY in $STRAYPARTD
do
echo "Swapoff $ONESTRAY"
swapoff $ONESTRAY
done
sync
# Stop udevd & logs daemon
killall udevd klogd syslogd &>/dev/null
# Unload modules
for ((i=1; i<=8; i++))
do
modlist=$(lsmod | awk '($3 == "0") {print $1}')
[ -z "$modlist" ] && break
for onemod in $modlist
do
rmmod $onemod
done
done
# Patriot's not too lame unmount of rootfs layers
if [ ! -d /initrd -o $PUPMODE -eq 2 ]; then
# Unmount code block for full hdd install
devFS=$(awk '/\/dev\/root/ {print $3}' /proc/mounts)
busybox mount -o remount,ro -t $devFS /dev/root /
sync
busybox umount -ar 2>/dev/null
exec /bin/busybox $applet
fi
# Setup unrootfs, if none
if [ $(df | grep -c ' /mnt/unrootfs$') -eq 0 ]; then
mkdir -p /mnt/unrootfs
busybox mount -t tmpfs tmpfs /mnt/unrootfs -o size=4m
sync
fi
# Preset, if fresh setup
[ -z "$SAVE_LAYER" ] && SAVE_LAYER="/pup_rw"
# aufs branch switcheroo ...
uniFS=$(awk '/unionfs / {print $3}' /proc/mounts)
busybox mount -o remount,prepend:/mnt/unrootfs=rw,noxino -t $uniFS / /
sync
busybox mount -o remount,ro /initrd${SAVE_LAYER}
sync
# Prep unrootfs
cd /mnt/unrootfs
rm -f init
mkdir -p bin dev etc lib mnt nroot proc sbin sys tmp var/run
sync
# Prep /bin
cp /bin/busybox /bin/grep /usr/bin/fuser bin/
bbApps=$(bin/busybox); bbApps=${bbApps##*functions:}
for bbLnk in $bbApps; do ln -s busybox bin/${bbLnk%,}; done
unset bbApps bbLnk
# Check for busybox umount option
loflag=$(bin/busybox umount 2>&1 | awk '/\t-d\t/ {print " "$1}')
# Prep /dev
cp -dR /dev/* dev/
# Prep /etc
ln -s /proc/mounts etc/mtab
cp /etc/passwd etc/
# Prep /lib
cp /lib/ld-linux.so.2 /lib/libc.so.6 /lib/libcrypt.so.1 /lib/libm.so.6 lib/
# Prep /sbin
ln -s /bin/busybox sbin/getty
sync
# Move recursions
function move_recursion()
{
mkdir $2
busybox mount -o move $1 $2
}
[ "$PUP_HOME" ] && move_recursion /initrd${PUP_HOME} mnt/mp1
[ "$SAVE_LAYER" ] && move_recursion /initrd${SAVE_LAYER} mnt/mp2
[ "$(grep '/mnt/tmpfs ' /proc/mounts)" ] && move_recursion /initrd/mnt/tmpfs mnt/mp3
[ "$(grep '/mnt/tmpfs2 ' /proc/mounts)" ] && move_recursion /initrd/mnt/tmpfs2 mnt/mp4
[ "$(grep ' /tmp ' /proc/mounts)" ] && busybox umount /tmp
busybox umount /dev/pts /proc/bus/usb
busybox mount -o move /proc proc
busybox mount -o move /sys sys
sync
# Switching to unrootfs
unset LANG
pivot_root . /mnt/unrootfs/nroot
sync
cd /
# Prep Cleanup
echo '#!/bin/sh
exec 0<'$shtty'
exec 1>'$shtty' 2>&1
# Terminate anything still on puppyfs
fuser -kms /nroot
# Find and unmount union branches
unibrs=$(mount | grep " aufs ")
if [ "$(echo $unibrs | grep dirs=)" ]; then
# AUFS1
unibrs=${unibrs##*dirs=}; unibrs=${unibrs%)*}; unibrs=${unibrs%%,*}
for i in $(echo $unibrs | tr ":" " ")
do
case $i in
/=*|/mnt/mp2=*) continue ;;
*) unilist="${i%%=*} $unilist" ;;
esac
done
else
# AUFS2
unibrs=${unibrs##*si=}; unibrs=${unibrs%)*}; unibrs="/sys/fs/aufs/si_"${unibrs%%,*}
for i in $(ls $unibrs/br*)
do
h=$(cat $i)
case $h in
/=*|/mnt/mp2=*) continue ;;
*) unilist="${h%%=*} $unilist" ;;
esac
done
fi
for onebrs in $unilist
do
mount -o remount,del:${onebrs} -t '$uniFS' /nroot /nroot
sync
umount'$loflag' $onebrs
sync
done
# Find and detach loop devices
for onelodev in $(grep "^/dev/loop" /proc/mounts | tr -s " " ":")
do
losetup -d ${onelodev%%:*} 2>/dev/null
sync
done
# Final cleanup and unmount boot partition
[ -d /mnt/mp4 ] && umount'$loflag' /mnt/mp4
sync
[ -d /mnt/mp3 ] && umount'$loflag' /mnt/mp3
sync
umount'$loflag' /nroot
sync
[ -d /mnt/mp2 ] && umount'$loflag' /mnt/mp2
sync
[ -d /mnt/mp1 ] && umount /mnt/mp1
umount -ar 2>/dev/null
exec /bin/busybox '$applet'
' >/cleanup
chmod 755 /cleanup
exec /cleanup
Code: Select all
sync
umount /proc/bus/usb
umount /sys
umount /proc
# Patriot: init from tmpfs
mkdir -p /pup_new/mnt/unrootfs
mount -t tmpfs tmpfs /pup_new/mnt/unrootfs -o size=4m
cp /bin/busybox /pup_new/mnt/unrootfs/init
if [ "$(readlink /pup_new/sbin/init)" != "/mnt/unrootfs/init" ]; then
ln -sf /mnt/unrootfs/init /pup_new/sbin/init
fi
sync
#now using cpio archive for initramfs 'initial ramdisk'...
#exec switch_root -c /dev/console /pup_new /bin/busybox init 3
exec switch_root /pup_new /sbin/init
###END###
Rgds
._.