commit f76a355fd021c1a6c47409577861dee665d15e42
parent 4d4d69cd4d7ca4e0b915c935f5cfc452f97644af
Author: (A)nathema <anathema@anche.no>
Date: Thu, 18 Aug 2011 09:49:38 -0700
Merge pull request #24 from davinerd/feat_issue_21
Feat issue 21
Diffstat:
M | src/tomb | | | 183 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
1 file changed, 118 insertions(+), 65 deletions(-)
diff --git a/src/tomb b/src/tomb
@@ -757,40 +757,101 @@ exec_safe_post_hooks() {
fi
}
+kill_tomb() {
+ # $1 = pids to kill
+ # $2 = type of kill
+ local e p
+ # substitute the \n with space
+ e=${1//$'\n'/ }
+ # split the string at space delim
+ # so we can get a for loop honestly
+ e=(${(s: :)e})
+ for p in $e; do
+ func "killing PID $p..."
+ if [[ "$2" == "soft" ]]; then
+ kill -USR1 $p
+ elif [[ "$2" == "hard" ]]; then
+ kill -TERM $p
+ elif [[ "$2" == "must die" ]]; then
+ kill -KILL $p
+ fi
+ done
+}
+
+slam_tomb() {
+ # $1 = tomb mount point
+ local pidk
+
+ pidk=`lsof -t "$1"`
+ if [[ ! -z "$pidk" ]]; then
+ kill_tomb "$pidk" "soft"
+ else
+ return 0
+ fi
+
+ # if there are remaining pids
+ # we need to play hard
+ pidk=`lsof -t "$1"`
+ if [[ -z "$pidk" ]]; then
+ return 0
+ fi
+
+ # if we set the -f (force) option
+ # don't wait, just kill
+ option_is_set -f || sleep 3
+ kill_tomb "$pidk" "hard"
+ pidk=`lsof -t "$1"`
+ if [[ -z "$pidk" ]]; then
+ return 0
+ fi
+
+ # if there are still some pids around
+ # we have to kill 'em all
+ option_is_set -f || sleep 3
+ kill_tomb "$pidk" "must die"
+ pidk=`lsof -t "$1"`
+ if [[ -z "$pidk" ]]; then
+ return 0
+ fi
+
+ # what PITA!
+ return 1
+}
+
umount_tomb() {
local tombs how_many_tombs
local pathmap mapper tombname tombmount loopdev
local ans pidk pname
if ! [ $1 ]; then
- tombs=`find /dev/mapper -name 'tomb.*'`
- how_many_tombs=`wc -w <<< "$tombs"`
- if [ "$how_many_tombs" = "0" ]; then
- error "There is no open tomb to be closed"
- return 1
- elif [ "$how_many_tombs" = "1" ]; then
- #mapper=`find /dev/mapper -name 'tomb.*'`
- func "closing mapper $tombs"
- umount_tomb ${tombs}
- return 1
- else
- error "Too many tombs mounted, please specify which to unmount:"
- ls /dev/mapper/tomb.*
- error "or issue the command 'tomb close all' to clos'em all."
- return 1
- fi
+ tombs=`find /dev/mapper -name 'tomb.*'`
+ how_many_tombs=`wc -w <<< "$tombs"`
+ if [[ "$how_many_tombs" == "0" ]]; then
+ error "There is no open tomb to be closed"
+ return 1
+ elif [[ "$how_many_tombs" == "1" ]]; then
+ #mapper=`find /dev/mapper -name 'tomb.*'`
+ func "closing mapper $tombs"
+ umount_tomb ${tombs}
+ return 1
+ else
+ error "Too many tombs mounted, please specify which to unmount:"
+ ls /dev/mapper/tomb.*
+ error "or issue the command 'tomb close all' to clos'em all."
+ return 1
+ fi
fi
if [ "$1" = "all" ]; then
- tombs=`find /dev/mapper -name 'tomb.*'`
- if ! [ $tombs ]; then
- notice "Tombs are all closed, cemetery is quiet."
+ tombs=`find /dev/mapper -name 'tomb.*'`
+ if ! [ $tombs ]; then
+ notice "Tombs are all closed, cemetery is quiet."
+ return 0
+ fi
+ for t in ${(f)tombs}; do
+ umount_tomb ${t}
+ done
return 0
- fi
- for t in ${(f)tombs}; do
- umount_tomb ${t}
- done
- return 0
fi
@@ -798,26 +859,20 @@ umount_tomb() {
pathmap=`dirname "$1"`
if [ "${pathmap}" = "/dev/mapper" ]; then
-
- mapper="$1" # argument is the mapper (or none which autofills mapper)
- tombname="`print $mapper | cut -d. -f2`"
- tombmount=`mount -l | \
+ mapper="$1" # argument is the mapper (or none which autofills mapper)
+ tombname="`print $mapper | cut -d. -f2`"
+ tombmount=`mount -l | \
awk -vtomb="[$tombname]" '/^\/dev\/mapper\/tomb/ { if($7==tomb) print $3 } '`
-
elif [ "$pathmap" = "." ]; then
-
- tombname="$1" # argument is the name
- mapper=`mount -l | \
+ tombname="$1" # argument is the name
+ mapper=`mount -l | \
awk -vtomb="[$tombname]" '/^\/dev\/mapper\/tomb/ { if($7==tomb) print $1 } '`
- tombmount=`mount -l | \
+ tombmount=`mount -l | \
awk -vtomb="[$tombname]" '/^\/dev\/mapper\/tomb/ { if($7==tomb) print $3 } '`
-
else
-
- tombmount="$1" # argument should be the mount
+ tombmount="$1" # argument should be the mount
mapper=`mount | awk -vmnt="$tombmount" '/^\/dev\/mapper\/tomb/ { if($3==mnt) print $1 }'`
- tombname="`print $mapper | cut -d. -f2`"
-
+ tombname="`print $mapper | cut -d. -f2`"
fi
# avoid block when the same tomb is mounted, take only the first
@@ -835,45 +890,43 @@ umount_tomb() {
fi
if [ $SLAM ]; then
- notice "Slamming tomb $tombname mounted on $tombmount"
- act "Kill all processes busy inside the tomb"
- pidk=`lsof -t "$tombmount"`
- for p in "$pidk"; do
- pname=`pidof $p`
- func "killing PID $p of $pname..."
- kill -9 $p
- done
+ notice "Slamming tomb $tombname mounted on $tombmount"
+ act "Kill all processes busy inside the tomb"
+ slam_tomb "$tombmount"
+ if [[ $? == 1 ]]; then
+ error "Cannot slam the tomb $tombname"
+ return 1
+ fi
else
- notice "Closing tomb $tombname mounted on $tombmount"
+ notice "Closing tomb $tombname mounted on $tombmount"
fi
# check if there are binded dirs and close them
tombmount_esc=`sed 's:\/:\\\/:g' <<< $tombmount `
unbind=`mount | awk "/^$tombmount_esc.*bind/"' { print $3 }'`
for b in ${(f)unbind}; do
- hook="`basename $b`"
- act "closing tomb hook: $hook"
- umount $b
- if ! [ $? = 0 ]; then
- if [ $SLAM ]; then
- notice "Slamming tomb: killing all processes using this hook"
- pidk=`lsof -t $b`
- for p in "$pidk"; do
- pname=`pidof $p`
- notice "Killing PID $p of $pname..."
- kill -9 $p
- done
- umount $b
- else
- error "Tomb hook is busy, cannot close tomb."
- return 1
+ hook="`basename $b`"
+ act "closing tomb hook: $hook"
+ umount $b
+ if [[ $? != 0 ]]; then
+ if [ $SLAM ]; then
+ notice "Slamming tomb: killing all processes using this hook"
+ slam_tomb "$b"
+ if [[ $? == 1 ]]; then
+ error "Cannot slam the tomb $b"
+ return 1
+ fi
+ umount $b
+ else
+ error "Tomb hook is busy, cannot close tomb."
+ return 1
+ fi
fi
- fi
done
# Execute post-hooks for eventual cleanup
if ! [ $NOBIND ]; then
- exec_safe_post_hooks ${tombmount%%/} close
+ exec_safe_post_hooks ${tombmount%%/} close
fi
if [ $tombmount ]; then # tomb is actively mounted