Linux Archive

Linux Archive (http://www.linux-archive.org/)
-   ArchLinux General Discussion (http://www.linux-archive.org/archlinux-general-discussion/)
-   -   Make umounting filesystems much more paranoid. (http://www.linux-archive.org/archlinux-general-discussion/397707-make-umounting-filesystems-much-more-paranoid.html)

Victor Lowther 07-11-2010 03:22 PM

Make umounting filesystems much more paranoid.
 
In addition to just umounting filesystems, we also try to tear down volume groups,
crypt mappings, and loopback devices. We skip /, /proc, /sys, and /dev when
umounting filesystems.

We do all of the above in a loop, escalating how forcible we are in umounting
filesystems up to the point where we give up and try to just remount
filesystems read-only. We do not escalate how forcible we are until we stop making
progress in umounting filesystems.

This patch does not print anything when tearing down crypt devices, deactivating
volume groups, or tearing down loopback devices. It does this because root on lvm
and root on dm_crypt are fairly common cases, and figuring out which of these
is the case and avoiding that volume group or dm_crypt mapping is tricky.

We also no longer rely on /etc/crypttab at all for shutdown to tear down
dm_crypt mappings.

---
rc.shutdown | 112 +++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 90 insertions(+), 22 deletions(-)

diff --git a/rc.shutdown b/rc.shutdown
index 2a561e4..d430dce 100755
--- a/rc.shutdown
+++ b/rc.shutdown
@@ -64,30 +64,98 @@ stat_busy "Deactivating Swap"
/sbin/swapoff -a
stat_done

-stat_busy "Unmounting Filesystems"
-/bin/umount -a -r -t noramfs,notmpfs,nosysfs,noproc,nodevtmpfs -O no_netdev
-stat_done
+# reverse an array
+reverse() {
+ res=()
+ [[ $1 ]] || return 0
+ local i=("$@") j=0
+ for ((j=${#i[@]}-1; j>=0; j--)); do
+ res+=("${i[j]}")
+ done
+}

-# Kill non-root encrypted partition mappings
-if [[ -f /etc/crypttab && $CS ]]; then
- stat_busy "Deactivating encrypted volumes:"
- do_lock() {
- stat_append "${1}.."
- if $CS remove "$1" >/dev/null 2>&1; then
- stat_append "ok "
- else
- stat_append "failed "
- fi
- }
- read_crypttab do_lock
- stat_done
-fi
+# Get mounted filesystems
+fs=()
+ignore_re='^/(proc|sys|dev)?$'
+while read dev mntpt rest; do
+ [[ $mntpt =~ $ignore_re ]] && continue
+ fs+=("$mntpt")
+done < /proc/self/mounts
+# reverse list of filesystems to let us umount them in reverse order
+reverse "${fs[@]}"
+fs=("${res[@]}")
+
+# get volume groups
+vg=()
+which lvm >/dev/null 2>&1 &&
+ vg=($(lvm vgs --unbuffered --noheadings -o vg_name))
+# reverse list of volume groups to grab more of them at once.
+reverse "${vg[@]}"
+vg=("${res[@]}")
+
+# get crypto devices
+crypt=()
+[[ $CS ]] && {
+ for dev in /dev/mapper/*; do
+ "$CS" status "${dev##*/}" >/dev/null 2>&1 || continue
+ crypt+=(${dev##*/})
+ done
+}
+# don't bother reversing crypt, it is in no defined order anyways.
+
+# get loopback devices in use
+loops=()
+which losetup >/dev/null 2>&1 && {
+ while read dev rest; do
+ loops+=("${dev%:}")
+ done < <(losetup -a)
+}
+reverse "${loops[@]}"
+loops=("${res[@]}")
+
+do_umount() {
+ local ret=0 i j pass=$1 umountopts=' last
+ # do not umount anything that matches this regex
+ case $pass in
+ 2) umountopts='-f';; #next try forcing the umount
+ 3) umountopts='-r'; last=true;; #next try remounting readonly
+ esac
+
+ # first, try umounting filesystems.
+ for i in "${!fs[@]}"; do
+ if status "Unmounting ${fs[i]} (pass $pass)" /bin/umount -d $umountopts
+ "${fs[i]}"; then
+ unset fs[$i]
+ else
+ ((ret++))
+ fi
+ done
+
+ # Second, deactivate any LVM groups that we can free up
+ for i in "${!vg[@]}"; do
+ /sbin/lvm vgchange --sysinit -an "${vg[i]}" >/dev/null 2>&1 &&
+ unset vg[$i]
+ done
+
+ # Third, tear down as many cryptsetup devices as we can.
+ for i in "${!crypt[@]}"; do
+ $CS remove "${crypt[i]}" >/dev/null 2>&1 && unset crypt[$i]
+ done
+
+ # Last, tear down as many loop devices as we can
+ for i in "${!loops[@]}"; do
+ losetup -d "${loops[i]}" >/dev/null 2>&1 && unset loops[$i]
+ done
+ [[ $last = true ]] && return 0
+ return $ret
+}

-if [[ $USELVM =~ yes|YES && -x /sbin/lvm && -d /sys/block ]]; then
- stat_busy "Deactivating LVM2 groups"
- /sbin/lvm vgchange --ignorelockingfailure -an >/dev/null 2>&1
- stat_done
-fi
+# Loop and try to umount filesystems
+for ((pass=1,fses=${#fs[@]}; ;fses=${#fs[@]})); do
+ do_umount $pass && break; # if we umounted all the filesystems, break.
+ # only escalate if we did not make progress unmounting filesystems.
+ ((fses == ${#fs[@]})) && ((pass++))
+done

stat_busy "Remounting Root Filesystem Read-only"
/bin/mount -n -o remount,ro /
--
1.7.1.1

Victor Lowther 07-11-2010 05:20 PM

Make umounting filesystems much more paranoid.
 
On Jul 11, 2010, at 10:34 AM, Dieter Plaetinck <dieter@plaetinck.be>
wrote:



fwiw in AIF I do something similar (see
http://github.com/Dieterbe/aif/blob/master/src/core/libs/lib-blockdevices-filesystems.sh#L457
)

(but there i use a text file containing all mountpoints)

The interesting thing is, to find the order in which you should mount
or (or umount) blockdevices can be found by doing a normal alpabetical
(reverse) sorting of the mountpoints, so i just use the sort tool.


How so? Filesystems are not mounted in any particular order, and /proc/
self/mounts lists the filesystems in the order they were mounted.
Using the sort command would screw up the mount ordering, which means
I would have to do more passes to properly umount things.



Dieter


All times are GMT. The time now is 06:08 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.