How to cleanly unmount your filesystem on shutdowns
Posted: Sat 22 May 2010, 00:44
Hmmm .....
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.
2. Look for this code block at the end of rc.shutdown (this sample is from puppy412)
3. Add this code block right after the code block above:
4. Save it.
5. You must now manually fsck your savefile (or hdd) by either :
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 :
2. Modify /sbin/poweroff to :
3. Edit /etc/profile and look for alias vi=e3vi and add the 3 additional alias lines (fix for CLI shutdowns):
4. Edit ~/.bashrc (ie. /root/.bashrc) and add the unalias and alias lines after . /etc/profile line. (Applicable X & CLI fixes):
5. Edit /etc/rc.d/rc.shutdown :
- The first added block is at the beginning of the script, before the clear statement
- The next addition is at the end of the script, after the swapoff code block
- Everything past exec /cleanup can be commented or removed
6. Unpack initrd.gz and edit init script (at the end of the script):
7. You must now manually fsck your savefile (or hdd) before checking your filesystem status.
Rgds
._.
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
._.