#!/usr/bin/ksh
#
# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#ident	"@(#)sv.cluster	1.6	04/06/15 SMI"

if [ ! -d /usr/sbin -o ! -d /usr/bin ]
then
	exit 1
fi

# Constants

DSCFG=/usr/opt/SUNWscm/sbin/dscfg
SVBOOT=/usr/opt/SUNWesm/sbin/svboot

# Functions

#
# Unmount files systems prior to stopping the Storage Volume driver
#

umount_list()
{
	# <stdin> - list of special devices
	#
	# find all filesystems that need to be unmounted in order to
	# unmount these special devices, sorted in the correct order to
	# pass to umount

	tmp1=/var/tmp/um.1.$$
	tmp2=/var/tmp/um.2.$$

	rm -f $tmp1 $tmp2

	# read list from <stdin> and convert to mount points

	cat >$tmp1

	# 4486818 - grep out the real device mounts from
	# /etc/mnttab to avoid the NFS and other types of mount

	grep '^/dev/' /etc/mnttab |
	while read special mountp junk
	do
		if fgrep -s -- "$special" $tmp1 >/dev/null 2>&1
		then
			echo $mountp
		fi
	done >$tmp2

	# get the special devices for every mount point whose name
	# begins with that of a mount point that we need to unmount
	# eg. if we want to unmount /sv0, and there is also a /sv0/sv2
	# mount point, then the list of special devices must include
	# both (we cannot unmount /sv0 without first unmounting
	# /sv0/sv2)
	#
	# 4486818 - ensure that the match is only made for
	# subdirectories of the required mountpoint, eg. if $mountp is
	# /sv0 then we do want to unmount /sv0/sv2, but we do *not*
	# want to unmount /sv0foo

	while read mountp
	do
		grep "[ 	]${mountp}[/ 	]" /etc/mnttab
	done <$tmp2 | awk '{ print $1 }' >$tmp1

	# sort the list into reverse mnttab order to give to umount,
	# and display on <stdout>
	#
	# 4486818 - grep out the real device mounts from
	# /etc/mnttab to avoid the NFS and other types of mount

	tail -r /etc/mnttab | grep '^/dev/' |
		while read special junk
		do
			if fgrep -s -- "$special" $tmp1 >/dev/null 2>&1
			then
				echo $special
			fi
		done

	rm -f $tmp1 $tmp2
}

# main program

if [[ ! -x $SVBOOT ]]
then
	echo "$0: cannot find $SVBOOT"
	exit 1
fi

if [[ ! -x $DSCFG ]]
then
    	echo "$0: cannot find $DSCFG"
	exit 1
fi

if [[ -z "$2" ]]
then
	opt=usage
else
	opt=$1
fi

case "$opt" in
'start')
	$SVBOOT -C "$2" -r
	;;

'stop')
	#
	# Unmount all filesystems using the sv devices
	#

	# grab list of configured sv devices

	svfiles=`$DSCFG -l | \
		grep '^sv: ' | \
		cut -d' ' -f2,4 | \
		grep " $2"$ | \
		cut -d' ' -f1 | \
		sed -e 's!/rdsk/!/dsk/!'`

	if [ -z "$svfiles" ]
	then
		# no work to do and we don't want error
		# messages from svboot -s
		exit 0
	fi

	# get list of the special devices for the filesystems
	# mounted on the sv devices that need to be unmounted

	tmpfile=/var/tmp/k$$
	splist=

	rm -f $tmpfile

	# 4486818 - grep out the real device mounts from
	# /etc/mnttab to avoid the NFS and other types of mount

	grep '^/dev/' /etc/mnttab |
	while read special mountp fstyp flags junk
	do
		if [ `echo "$svfiles" | \
			fgrep -c -- "$special"` -gt 0 ]
		then
			# only unmount local filesystems during
			# switchover - the cluster will do the
			# right thing with global filesystems

			echo $flags | grep global > /dev/null 2>&1
			retval=$?
			if [ $retval != 0 ]
			then
				echo $special
			fi
		fi

	done >$tmpfile

	# if there are filesystems that need to be unmounted, then
	# kill all procs using them and unmount them.

	if [ -s $tmpfile ]
	then
		splist=`umount_list <$tmpfile`

		rm -f $tmpfile

		echo 'unmounting filesystems mounted on SV devices'

		# polite kill of procs using the filesystems

		pids=`/usr/sbin/fuser $splist 2>/dev/null`
		if [ -n "$pids" ]
		then
			/usr/bin/kill -15 $pids
			/usr/bin/sleep 5
		fi

		# hard kill of everyone using the filesystems

		/usr/sbin/fuser -k $splist >/dev/null 2>&1
		/usr/bin/sleep 10

		# umount filesystems in the correct order

		/sbin/sync ; /sbin/sync ; /sbin/sync
		for s in $splist
		do
			echo stopping SV mount $s
			/sbin/umount $s
		done
	fi

	$SVBOOT -C "$2" -s
	;;

*)
	echo "Usage: $0 { start | stop } cluster_resource"
	exit 1
	;;
esac
