#!/bin/sh
#
# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#ident	"@(#)MOUNTGFSYS	1.42	05/03/07 SMI"

# Check if SMF is present
INCLUDE_FILE="/lib/svc/share/smf_include.sh"
if [ -f $INCLUDE_FILE ]
then
	. $INCLUDE_FILE

	#Save a copy of file descriptors to the
	#Greenline logs
	exec 4>&1 5>&2
else
	exec 4>/dev/null 5>&4
fi

#Set up stdout and stderr to write to the console
exec 1>/dev/msglog 2>&1

# Exit if we are not booted as a cluster.
/usr/sbin/clinfo > /dev/null 2>&1
if [ $? != 0 ] ; then
	if [ -f $INCLUDE_FILE ]
	then
		svcadm mark -t maintenance $SMF_FMRI
	fi

	exit 0
fi

#
#	gmountmessage
#
# Print out instructions for a manual file system check before entering
# the shell.
#
gmountmessage() {
	echo ""
	echo "WARNING - Unable to globally mount all filesystems."
	echo "Check logs for error messages and correct the problems."
	echo "Exit the shell when done to continue the boot process."
	echo ""
}

#
#	gdevmountmessage "fsck_device | mount_point"
#
# Simple auxilary routine to the mounting of /global/.devices/node@<N>.
# Prints out instructions for a manual file system mount before entering
# the shell.
#
gdevmountmessage() {
	echo ""
	echo "WARNING - Unable to mount one or more of the following filesystem(s):"
	echo "\t$1"
	echo "If this is not repaired, global devices will be unavailable."
	echo "Run mount manually (mount filesystem...)."
	echo "Exit the shell when done to continue the boot process."
	echo ""
}

#
#	checkmessage "fsck_device | mount_point"
#
# Simple auxilary routine to the shell function checkfs. Prints out
# instructions for a manual file system check before entering the shell.
#
checkmessage() {
	echo ""
	echo "WARNING - Unable to repair one or more of the following filesystem(s):"
	echo "\t$1"
	echo "Run fsck manually (fsck filesystem...)."
	echo "Exit the shell when done to continue the boot process."
	echo ""
}

#
#	checkfs raw_device fstype mountpoint
#
# Check the file system specified. The return codes from fsck have the
# following meanings.
#	 0 - file system is unmounted and okay
#	32 - file system is unmounted and needs checking (fsck -m only)
#	33 - file system is already mounted
#	34 - cannot stat device
#	36 - uncorrectable errors detected - terminate normally (4.1 code 8)
#	37 - a signal was caught during processing (4.1 exit 12)
#	39 - uncorrectable errors detected - terminate rightaway (4.1 code 8)
#	40 - for root, same as 0 (used by rcS to remount root)
# Note that should a shell be entered and the operator be instructed to
# manually check a file system, it is assumed the operator will do the right
# thing. The file system is not rechecked.
#
checkfs() {
	/usr/sbin/fsck -F $2 -m $1  >/dev/null 2>&1

	if [ $? -ne 0 ]
	then
		# Determine fsck options by file system type
		case "$2" in
		ufs)	foptions="-o p"
			;;
		s5)	foptions="-y -t /var/tmp/tmp$$ -D"
			;;
		*)	foptions="-y"
			;;
		esac

		echo "The "$3" file system ("$1") is being checked."
		/usr/sbin/fsck -F $2 ${foptions} $1
	
		case $? in
		0|40)	# file system OK
			;;

		*)	# couldn't fix the file system - enter a shell
			checkmessage "$1"
			if [ -f $INCLUDE_FILE ]
			then
				exit $SMF_EXIT_ERR_CONFIG
			else 
				/sbin/sulogin < /dev/console
				echo "resuming mountall"
			fi
			;;
		esac
	fi
}

#
# Used to save an entry that we will want to mount either in
# a command file or as a mount point list.
#
# saveentry fstype options special mountp
#
saveentry() {
	speclist="$speclist $3"
	mntlist="$mntlist $4"
}

#
# Mount PXFS file systems.
#
case "$1" in
'start')

	#
	# Get access to all attached disks
	#
	/usr/cluster/lib/sc/run_reserve -c node_join

	#
	# Now that this node is no longer fenced from any disks, tell VxVM
	# to re-scan the disks.
	# Check for vxdctl utility to confirm VxVM package is installed.
	# If no vxdctl utility, infer VxVM package is not installed on 
	# this node.
	#
	if [ -x /usr/sbin/vxdctl ]
	then
		/usr/sbin/vxdctl enable
	fi

	#
	# Unmount /global/.devices/node@<nodeid> locally
	# (will be mounted globally below).
	#
	gdev_root=/global/.devices/node@`/usr/sbin/clinfo -n`
	/sbin/umount $gdev_root >/dev/null 2>&1

	#
	# Enable global mounts (this imports extant global mounts).
	# Note that this will also attempt to unmount stale versions of
	# global mounts.
	#
	/usr/cluster/lib/sc/clconfig -g
	while [ $? != 0 ] ; do

		gmountmessage

		if [ -f $INCLUDE_FILE ]
		then
			exit $SMF_EXIT_ERR_CONFIG
		else 
			/sbin/sulogin < /dev/console
		fi

		/usr/cluster/lib/sc/clconfig -g
	done

	# Mount the global devices partition.
	/sbin/mount $gdev_root
	if [ $? != 0 ] ; then
		# try again
		# Most of the time mount failed with EBUSY. This
		# seems to be due to the directory being busy.
		# We will retry the unmount with a force and the
		# mount with an "overlay" mount option.

		echo Trying to remount $gdev_root

		/sbin/umount -f $gdev_root >/dev/null 2>&1
		/sbin/mount -O $gdev_root
		if [ $? != 0 ] ; then
			gdevmountmessage "$gdev_root"

			if [ -f $INCLUDE_FILE ]
			then
				exit $SMF_EXIT_ERR_CONFIG
			else
				/sbin/sulogin < /dev/console
				echo "resuming boot"
			fi

		else
			echo Succeeded in remounting $gdev_root
		fi
	fi

	#
	# Mount all other PXFS file systems.
	#
	exec < /etc/vfstab
	while read special fsckdev mountp fstype fsckpass automnt mntopts
	do
		case $special in
		'#'* | '')	#  Ignore comments, empty lines
		continue ;;
		'-')		#  Ignore no-action lines
			continue
		esac

		# Skip entries that aren't enabled to be mounted.
		if [ "$automnt" != "yes" -o "$fstype" = "-" ]; then
			continue
		fi

		# Skip entries that have don't the "global" option.
		g=`/usr/bin/grep '\<global\>' << EOF
			$mntopts
		EOF`
		if [ "$fstype" = "cachefs" -o "$fstype" = "nfs" -o -z "$g" ]
		then
			continue
		fi

		#
		# Try to get the fsck/mount lock for this device.
		# We won't get the lock if it is already mounted or
		# some other node beats us.
		#
		/usr/cluster/lib/sc/clconfig -l $special >/dev/null 2>&1
		if [ $? != 0 ] ; then
			continue
		fi

		OPTIONS=""

		#
		# Can't fsck if no fsckdev is specified
		#
		if [ "$fsckdev" = "-" ]; then
			saveentry $fstype "$OPTIONS" $special $mountp
			continue
		fi
		#
		# For fsck purposes, we make a distinction between ufs
		# and other file systems
		# 
		if [ "$fstype" = "ufs" ]; then
			saveentry $fstype "$OPTIONS" $special $mountp
			continue
		fi
		#
		# fsck everything else:
		#
		# fsck -m simply returns true if the filesystem is
		# suitable for mounting.
		#
		/usr/sbin/fsck -m -F $fstype $fsckdev >/dev/null 2>&1
		case $? in
		0|40)	saveentry $fstype "$OPTIONS" $special $mountp
			continue
			;;
		32)	checkfs $fsckdev $fstype $mountp
			saveentry $fstype "$OPTIONS" $special $mountp
			continue
			;;
		33)	# already mounted
			echo "$special already mounted"
			;;
		34)	# bogus special device
			echo "Cannot stat $fsckdev - ignoring"
			;;
		*)	# uncorrectable errors
			echo "$fsckdev uncorrectable error"
			;;
		esac
		/usr/cluster/lib/sc/clconfig -u $special >/dev/null 2>&1
	done

	#
	# If VxVM is installed, make sure VxVM namespace is correct
	#
	if [ -d /dev/vx ]
	then
		/usr/cluster/lib/dcs/scvxvmlg
	fi

	if [ "$mntlist" ]; then
		/sbin/mount -a $mntlist

		# Unlock devices
		for special in $speclist; do
			/usr/cluster/lib/sc/clconfig -u $special >/dev/null 2>&1
		done
	fi

	#
	# Initiate switchbacks now that the .devices filesystem has been
	# mounted as PXFS.
	#
	/usr/cluster/lib/sc/clconfig -s
	if [ $? != 0 ] ; then
		echo ""
		echo "WARNING - Could not initiate switchbacks on this node."
		echo "Check logs for error messages."
		echo ""
	fi
	;;

'stop')
	# We are shutting down - disable unmounts on this node.
	/usr/cluster/lib/sc/clconfig -d
	;;

*)
	echo "Usage: $0 start"
	;;
esac

exit 0
