#!/sbin/sh
#
# Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#ident	"@(#)sv	1.25	05/08/09 SMI"

[ ! -d /usr/sbin -o ! -d /usr/bin ] && exit

# Constants

FLAGFILE=/etc/opt/SUNWesm/donotrun
SVADM=/usr/opt/SUNWesm/sbin/svadm
SVBOOT=/usr/opt/SUNWesm/sbin/svboot
CLINFO=/usr/sbin/clinfo

# 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 -x -- "$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 -x -- "$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 $SVADM ]
then
	echo "$0: cannot find $SVADM"
	exit 1
fi

case "$1" in
'start')
	# presence of $FLAGFILE prevents SVE software fom starting
	if [ -f $FLAGFILE ]
	then
		echo "$0: $FLAGFILE is set: startup aborted"
		exit 0
	fi

	COPT=

	if $CLINFO
	then
		# in cluster - look for local volumes only
		COPT="-C l."`/usr/bin/hostname`
	fi

	$SVBOOT $COPT -r
	;;

'stop')
	COPT=

	if $CLINFO
	then
		# in cluster - look for local volumes only
		COPT="-C l."`/usr/bin/hostname`
	fi

	if [ -r /dev/sv ]
	then
		#
		# Unmount all filesystems using the sv devices
		#

		# grab list of configured sv devices

		svfiles=`$SVADM $COPT 2>/dev/null | \
				awk '{print $1}' - | \
				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 -x -- "$special"` -gt 0 ]
			then
				# only unmount local filesystems
				# - 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 $COPT -s
	fi
	;;

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