changeset 13349:06962a3446ee

910 mountall thinks smbfs filesystems are local Reviewed by: Jason King <jason.brian.king+illumoshg@gmail.com> Reviewed by: Robert Gordon <rbg@openrbg.com> Reviewed by: Garrett D'Amore <garrett@nexenta.com> Approved by: Garrett D'Amore <garrett@nexenta.com>
author Gordon Ross <gwr@nexenta.com>
date Mon, 25 Apr 2011 12:59:44 -0400
parents 4389ac5d32c3
children a4d1acb7a7f5
files usr/src/cmd/initpkg/mountall.sh usr/src/cmd/initpkg/umountall.sh
diffstat 2 files changed, 141 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/initpkg/mountall.sh	Mon Apr 25 12:48:49 2011 -0400
+++ b/usr/src/cmd/initpkg/mountall.sh	Mon Apr 25 12:59:44 2011 -0400
@@ -20,16 +20,36 @@
 #
 # CDDL HEADER END
 #
+
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
 #	  All Rights Reserved
 #
 
+usage () {
+	if [ -n "$1" ]; then
+		echo "mountall: $1" 1>&2
+	fi
+	echo "Usage:\nmountall [-F FSType] [-l|-r|-g] [file_system_table]" 1>&2
+	exit 2
+}
+
+PATH=/usr/sbin:/usr/bin
+TYPES=all
+FSTAB=/etc/vfstab
+err=0
+
+# Clear these in case they were already set in our environment.
+FSType=
+GFLAG=
+RFLAG=
+LFLAG=
+SFLAG=
+RemoteFSTypes=
+
 #	checkmessage "fsck_device | mount_point"
 #
 # Simple auxilary routine to the shell function checkfs. Prints out
@@ -105,12 +125,29 @@
 	fi
 }
 
+# Do the passed mount options include "global"?
+isglobal() {
+	case ",${1}," in
+	*,global,*)
+		return 0
+		;;
+	esac
+	return 1
+}
 
-PATH=/usr/sbin:/usr/bin
-USAGE="Usage:\nmountall [-F FSType] [-l|-r|-g] [file_system_table]"
-TYPES=all
-FSTAB=/etc/vfstab
-err=0
+# Is the passed fstype a "remote" one?
+# Essentially: /usr/bin/grep "^$1" /etc/dfs/fstypes
+isremote() {
+	for t in $RemoteFSTypes
+	do
+		[ "$t" = "$1" ] && return 0
+	done
+	return 1
+}
+
+# Get list of remote FS types (just once)
+RemoteFSTypes=`while read t junk; do echo $t; done < /etc/dfs/fstypes`
+
 
 #
 # Process command line args
@@ -136,16 +173,14 @@
 			exit 2
 		esac
 		;;
-	\?)	echo "$USAGE" 1>&2; exit 2;;
+	\?)	usage "";;
 	esac
 done
 
 shift `/usr/bin/expr $OPTIND - 1`	# get past the processed args
 
 if [ $# -gt 1 ]; then
-	echo "mountall: multiple arguments not supported" 1>&2
-	echo "$USAGE" 1>&2
-	exit 2
+	usage "multiple arguments not supported"
 fi
 
 # get file system table name and make sure file exists
@@ -179,22 +214,19 @@
      "$RFLAG" = "r" -a "$GFLAG$LFLAG" != "" -o \
      "$LFLAG" = "l" -a "$RFLAG$GFLAG" != "" ]
 then
-	echo "mountall: options -g, -r and -l are mutually exclusive" 1>&2
-	echo "$USAGE" 1>&2
-	exit 2
+	usage "options -g, -r and -l are mutually exclusive"
 fi
 
-if [ \( "$FSType" = "cachefs" -o "$FSType" = "nfs" \) -a "$LFLAG" = "l" ]
-then
-	echo "mountall: option -l and FSType are incompatible" 1>&2
-	echo "$USAGE" 1>&2
-	exit 2
+if [ "$LFLAG" = "l" -a -n "$FSType" ]; then
+	# remote FSType not allowed
+	isremote "$FSType" &&
+	usage "option -l and FSType are incompatible"
 fi
-if [ "$FSType" -a "$FSType" != "nfs" -a "$RFLAG" = "r" ]
-then
-	echo "mountall: option -r and FSType are incompatible" 1>&2
-	echo "$USAGE" 1>&2
-	exit 2
+
+if [ "$RFLAG" = "r" -a -n "$FSType" ]; then
+	# remote FSType required
+	isremote "$FSType" ||
+	usage "option -r and FSType are incompatible"
 fi
 
 #	file-system-table format:
@@ -232,25 +264,28 @@
 		continue
 	fi
 
-	if [ "$LFLAG" ]; then
-		# Skip entries that have the "global" option.
-		g=`/usr/bin/grep '\<global\>' << EOF
-			$mntopts
-		EOF`
-		if [ "$fstype" = "cachefs" -o "$fstype" = "nfs" -o "$g" ]; then
-			continue
-		fi
-	elif [ "$RFLAG" -a "$fstype" != "nfs" ]; then
-		continue
-	elif [ "$GFLAG" ]; then
-		# 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
+	# The -g option is not in the man page, but according to
+	# PSARC/1998/255 it's used by Sun Cluster (via contract) to
+	# mount disk-based filesystems with the "global" option.
+	# Also, the -l option now skips those "global" mounts.
+	#
+	# Note: options -g -l -r are mutually exclusive
+	#
+	if [ -n "$GFLAG" ]; then
+		# Mount "local" filesystems that have
+		# the "global" option in mntopts.
+		isremote "$fstype" && continue
+		isglobal "$mntopts" || continue
+	fi
+	if [ -n "$LFLAG" ]; then
+		# Mount "local" filesystems, excluding
+		# those marked "global".
+		isremote "$fstype" && continue
+		isglobal "$mntopts" && continue
+	fi
+	if [ -n "$RFLAG" ]; then
+		# Mount "remote" filesystems.
+		isremote "$fstype" || continue
 	fi
 
 	if [ "$fstype" = "-" ]; then
@@ -374,8 +409,11 @@
 	exit
 fi
 
+# Some remote filesystems (e.g. cachefs or autofs) shouldn't be be mounted
+# with mountall, so the list here is explicit (not from /etc/dfs/fstypes)
 if [ "$RFLAG" ]; then
 	/sbin/mount -a -F nfs
+	/sbin/mount -a -F smbfs
 	exit
 fi
 
--- a/usr/src/cmd/initpkg/umountall.sh	Mon Apr 25 12:48:49 2011 -0400
+++ b/usr/src/cmd/initpkg/umountall.sh	Mon Apr 25 12:59:44 2011 -0400
@@ -83,8 +83,25 @@
 NFLAG=
 LOCALNAME=
 UMOUNTFLAG=
+RemoteFSTypes=
+
+# Is the passed fstype a "remote" one?
+# Essentially: /usr/bin/grep "^$1" /etc/dfs/fstypes
+isremote() {
+	for t in $RemoteFSTypes
+	do
+		[ "$t" = "$1" ] && return 0
+	done
+	return 1
+}
+
+# Get list of remote FS types (just once)
+RemoteFSTypes=`while read t junk; do echo $t; done < /etc/dfs/fstypes`
 
 
+#
+# Process command line args
+#
 while getopts ?rslkF:h:Zn c
 do
 	case $c in
@@ -155,11 +172,15 @@
 	usage "Specifying local host illegal for -h option"
 fi
 
-if [ "$FSType" = "nfs" -a "$LFLAG" = "l" ]; then			# 6
-	usage "option -l and FSType nfs are incompatible"
+if [ "$LFLAG" = "l" -a -n "$FSType" ]; then				# 6
+	# remote FSType not allowed
+	isremote "$FSType" &&
+	usage "option -l and FSType ${FSType} are incompatible"
 fi
 
-if [ -n "$FFLAG" -a "$FSType" != "nfs"  -a -n "$RFLAG" ]; then		# 7
+if [ "$RFLAG" = "r" -a -n "$FSType" ]; then				# 7
+	# remote FSType required
+	isremote "$FSType" ||
 	usage "option -r and FSType ${FSType} are incompatible"
 fi
 
@@ -189,7 +210,7 @@
 	else
 		if [ ! -x /usr/bin/sleep ]; then
 			sleep () {
-				echo "umountall: sleep after fuser -k skipped (no /usr)" 1>&2
+		echo "umountall: sleep after fuser -k skipped (no /usr)" 1>&2
 				# continue - not fatal
 			}
 		fi
@@ -199,14 +220,28 @@
 #
 # Shell function to avoid using /usr/bin/cut.  Given a dev from a
 # fstype=nfs line in mnttab (eg, "host:/export) extract the host
-# component.
-print_host () {
+# component.  The dev string looks like: "host:/path"
+print_nfs_host () {
 	OIFS=$IFS
 	IFS=":"
 	set -- $*
 	echo $1
 	IFS=$OIFS
 }
+#
+# Similar for smbfs, but tricky due to the optional parts
+# of the "device" syntax.  The dev strings look like:
+# "//server/share" or "//user@server/share"
+print_smbfs_host () {
+	OIFS=$IFS
+	IFS="/@"
+	set -- $*
+	case $# in
+	3) echo "$2";;
+	2) echo "$1";;
+	esac
+	IFS=$OIFS
+}
 
 #
 # doumounts echos its return code to stdout, so commands used within
@@ -215,7 +250,6 @@
 	(
 	rc=0
 	fslist=""
-	nfslist=""
 	while read dev mountp fstype mode dummy
 	do
 		case "${mountp}" in
@@ -246,24 +280,28 @@
 			;;
 		* )
 			if [ -n "$HFLAG" ]; then
+				thishost='-'
 				if [ "$fstype" = "nfs" ]; then
-					thishost=`print_host $dev`
-					if [ "$HOST" != "$thishost" ]; then
-						continue
-					fi
-				else
+					thishost=`print_nfs_host $dev`
+				fi
+				if [ "$fstype" = "smbfs" ]; then
+					thishost=`print_smbfs_host $dev`
+				fi
+				if [ "$HOST" != "$thishost" ]; then
 					continue
 				fi
 			fi
 			if [ -n "$FFLAG" -a "$FSType" != "$fstype" ]; then
 				continue
 			fi
-			if [ -n "$LFLAG" -a "$fstype" = "nfs" ]; then
-				nfslist="$nfslist $mountp"
-				continue
+
+			if [ -n "$LFLAG" ]; then
+				# umount local filesystems
+				isremote "$fstype" && continue
 			fi
-			#
-			# This will filter out autofs mounts with nfs file
+
+			# Note: isremote is true for both nfs & autofs, so
+			# this will filter out autofs mounts with nfs file
 			# system mounted on the top of it.
 			#
 			# WARNING: use of any syscall on a NFS file system has
@@ -272,19 +310,11 @@
 			# down beforehand.
 			# For the reason described above, a simple test like 
 			# "df -F nfs $mountp" can't be used to filter out
-			# nfs-over-autofs mounts. We loop over a list instead:
+			# nfs-over-autofs mounts.  (isremote works OK)
 			#
-			if [ -n "$LFLAG" -a -n "$nfslist" -a "$fstype" = "autofs" ]
-			then
-				for m in $nfslist; do
-					if [ "$mountp" = "$m" ]; then
-						# Resume the outer while loop
-						continue 2
-					fi
-				done
-			fi
-			if [ -n "$RFLAG" -a "$fstype" != "nfs" ]; then
-				continue
+			if [ -n "$RFLAG" ]; then
+				# umount remote filesystems
+				isremote "$fstype" || continue
 			fi
 			if [ "$ZONENAME" != "global" ]; then
 				for option in `echo $mode | tr , '\012'`; do