6777298 umountall(1M) -z  ... limit unmounting action(s) to the current zone
6502014 NFS mounts in non-global zones are unmounted if NFS is restarted in the global zone
6512906 Autofs mounts in non-global zones are unmounted when autofs is restarted in the global zone
6777323 smb mounts in non-global zones are unmounted when smb/client is restarted in the global zone

   1 #!/sbin/sh
   2 #
   3 # CDDL HEADER START
   4 #
   5 # The contents of this file are subject to the terms of the
   6 # Common Development and Distribution License (the "License").
   7 # You may not use this file except in compliance with the License.
   8 #
   9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10 # or http://www.opensolaris.org/os/licensing.
  11 # See the License for the specific language governing permissions
  12 # and limitations under the License.
  13 #
  14 # When distributing Covered Code, include this CDDL HEADER in each
  15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16 # If applicable, add the following below this CDDL HEADER, with the
  17 # fields enclosed by brackets "[]" replaced with your own identifying
  18 # information: Portions Copyright [yyyy] [name of copyright owner]
  19 #
  20 # CDDL HEADER END
  21 #
  22 #
  23 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  24 # Use is subject to license terms.
  25 #
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 #
  28 #       Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
  29 #         All Rights Reserved
  30 #
  31 #
  32 
  33 usage () {
  34         if [ -n "$1" ]; then
  35                 echo "umountall: $1" 1>&2
  36         fi
  37         echo "Usage:\n\tumountall [-k] [-s] [-F FSType] [-l|-r] [-n]" 1>&2
  38         echo "\tumountall [-k] [-s] [-h host] [-n]" 1>&2
  39         exit 2
  40 }
  41 
  42 MNTTAB=/etc/mnttab
  43 
  44 # This script is installed as both /sbin/umountall (as used in some
  45 # /sbin/rc? and /etc/init.d scripts) _and_ as /usr/sbin/umountall (typically
  46 # PATHed from the command line).  As such it should not depend on /usr
  47 # being mounted (if /usr is a separate filesystem).
  48 #
  49 # /sbin/sh Bourne shell builtins we use:
  50 #       echo
  51 #       exit
  52 #       getopts
  53 #       test, [ ]
  54 #       exec
  55 #       read
  56 #
  57 # /sbin commands we use:
  58 #       /sbin/uname
  59 #       /sbin/umount
  60 #
  61 # The following /usr based commands may be used by this script (depending on
  62 # command line options).  We will set our PATH to find them, but where they
  63 # are not present (eg, if /usr is not mounted) we will catch references to
  64 # them via shell functions conditionally defined after option processing
  65 # (don't use any of these commands before then).
  66 #
  67 #       Command         Command line option and use
  68 # /usr/bin/sleep        -k, to sleep after an fuser -c -k on the mountpoint
  69 # /usr/sbin/fuser       -k, to kill processes keeping a mount point busy
  70 #
  71 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  72 # In addition, we use /usr/bin/tail if it is available; if not we use
  73 # slower shell constructs to reverse a file.
  74 
  75 PATH=/sbin:/usr/sbin:/usr/bin
  76 
  77 DEFERRED_ACTIVATION_PATCH_FLAG="/var/run/.patch_loopback_mode"
  78 SVC_STARTD="/lib/svc/bin/svc.startd"
  79 
  80 # Clear these in case they were already set in our inherited environment.
  81 FSType=
  82 FFLAG=
  83 HOST=
  84 HFLAG=
  85 RFLAG=
  86 LFLAG=
  87 SFLAG=
  88 KFLAG=

  89 NFLAG=
  90 LOCALNAME=
  91 UMOUNTFLAG=
  92 
  93 
  94 while getopts ?rslkF:h:n c
  95 do
  96         case $c in
  97         r)      RFLAG="r";;
  98         l)      LFLAG="l";;
  99         s)      SFLAG="s";;
 100         k)      KFLAG="k";;
 101         h)      if [ -n "$HFLAG" ]; then
 102                         usage "more than one host specified"
 103                 fi
 104                 HOST=$OPTARG
 105                 HFLAG="h"
 106                 LOCALNAME=`uname -n`
 107                 ;; 
 108         F)      if [ -n "$FFLAG" ]; then
 109                         usage "more than one FStype specified"
 110                 fi
 111                 FSType=$OPTARG 
 112                 FFLAG="f"
 113                 case $FSType in
 114                 ?????????*) 
 115                         usage "FSType ${FSType} exceeds 8 characters"
 116                 esac;
 117                 ;;

 118         n)      NFLAG="n"
 119                 # Alias any commands that would perform real actions to
 120                 # something that tells what action would have been performed
 121                 UMOUNTFLAG="-V"
 122                 fuser () {
 123                         echo "fuser $*" 1>&2
 124                 }
 125                 sleep () {
 126                         : # No need to show where we'd sleep
 127                 }
 128                 ;;
 129         \?)     usage ""
 130                 ;;
 131         esac
 132 done
 133 
 134 # Sanity checking:
 135 #       1) arguments beyond those supported
 136 #       2) can't specify both remote and local
 137 #       3) can't specify a host with -r or -l
 138 #       4) can't specify a fstype with -h
 139 #       5) can't specify this host with -h (checks only uname -n)
 140 #       6) can't be fstype nfs and local
 141 #       7) only fstype nfs is remote
 142 
 143 if [ $# -ge $OPTIND ]; then                                             # 1
 144         usage "additional arguments not supported"
 145 fi
 146 
 147 if [ -n "$RFLAG" -a -n "$LFLAG" ]; then                                 # 2
 148         usage "options -r and -l are incompatible"
 149 fi
 150 
 151 if [ \( -n "$RFLAG" -o -n "$LFLAG" \) -a "$HFLAG" = "h" ]; then         # 3
 152         usage "option -${RFLAG}${LFLAG} incompatible with -h option"
 153 fi
 154 
 155 if [ -n "$FFLAG" -a "$HFLAG" = "h" ]; then                              # 4
 156         usage "Specifying FStype incompatible with -h option"
 157 fi
 158 
 159 if [ -n "$HFLAG" -a "$HOST" = "$LOCALNAME" ]; then                      # 5
 160         usage "Specifying local host illegal for -h option"
 161 fi
 162 
 163 if [ "$FSType" = "nfs" -a "$LFLAG" = "l" ]; then                        # 6
 164         usage "option -l and FSType nfs are incompatible"
 165 fi
 166 
 167 if [ -n "$FFLAG" -a "$FSType" != "nfs"  -a -n "$RFLAG" ]; then          # 7
 168         usage "option -r and FSType ${FSType} are incompatible"
 169 fi
 170 
 171 ZONENAME=`zonename`
 172 
 173 # Check and if needed sync the boot archive before unmounting everything.
 174 #
 175 if [ -z "${RFLAG}${NFLAG}${HFLAG}${FSType}" -a "$ZONENAME" = "global" -a \
 176     `uname -p` = "i386" -a -x /sbin/bootadm ] ; then
 177         /sbin/bootadm -a update_all
 178 fi
 179 
 180 
 181 #
 182 # If we are in deferred activation patching, and the caller is 
 183 # svc.startd, then exit without unmounting any of the remaining 
 184 # file systems since the call path is from shutdown.  Note that
 185 # by the time we get here, smf stop methods for nfs, cachefs
 186 # etc, will have run.  
 187 #
 188 if [ -f $DEFERRED_ACTIVATION_PATCH_FLAG ] ; then 
 189         ppid=`ps -o ppid= -p $$`        # parent of umountall will be sh
 190                                         # from system()
 191 
 192         ppid=`ps -o ppid= -p $ppid`     # parent of sh will be svc.startd
 193         COMM=`ps -o comm= -p $ppid`
 194         if [ "$COMM" = "$SVC_STARTD" ] ; then
 195                 exit
 196         fi
 197 fi
 198 
 199 #
 200 # Take advantage of parallel unmounting at this point if we have no
 201 # criteria to match and we are in the global zone
 202 #
 203 if [ -z "${SFLAG}${LFLAG}${RFLAG}${HFLAG}${KFLAG}${FFLAG}" -a \
 204     "$ZONENAME" = "global" ]; then
 205         umount -a ${UMOUNTFLAG}
 206         exit                    # with return code of the umount -a
 207 fi
 208 
 209 #
 210 # Catch uses of /usr commands when /usr is not mounted
 211 if [ -n "$KFLAG" -a -z "$NFLAG" ]; then
 212         if [ ! -x /usr/sbin/fuser ]; then
 213                 fuser () {
 214                         echo "umountall: fuser -k skipped (no /usr)" 1>&2
 215                         # continue - not fatal
 216                 }
 217                 sleep () {
 218                         : # no point in sleeping if fuser is doing nothing
 219                 }
 220         else
 221                 if [ ! -x /usr/bin/sleep ]; then
 222                         sleep () {
 223                                 echo "umountall: sleep after fuser -k skipped (no /usr)" 1>&2
 224                                 # continue - not fatal
 225                         }
 226                 fi
 227         fi
 228 fi
 229 
 230 #
 231 # Shell function to avoid using /usr/bin/cut.  Given a dev from a
 232 # fstype=nfs line in mnttab (eg, "host:/export) extract the host
 233 # component.
 234 print_host () {
 235         OIFS=$IFS
 236         IFS=":"
 237         set -- $*
 238         echo $1
 239         IFS=$OIFS
 240 }
 241 
 242 #
 243 # doumounts echos its return code to stdout, so commands used within
 244 # this function should take care to produce no other output to stdout.
 245 doumounts () {
 246         (
 247         rc=0
 248         fslist=""
 249         while read dev mountp fstype mode dummy
 250         do
 251                 case "${mountp}" in
 252                 /                       | \
 253                 /dev                    | \
 254                 /dev/fd                 | \
 255                 /devices                | \
 256                 /etc/mnttab             | \
 257                 /etc/svc/volatile       | \
 258                 /lib                    | \
 259                 /proc                   | \
 260                 /sbin                   | \
 261                 /system/contract        | \
 262                 /system/object          | \
 263                 /tmp                    | \
 264                 /usr                    | \
 265                 /var                    | \
 266                 /var/adm                | \
 267                 /var/run                | \
 268                 '' )
 269                         #
 270                         # file systems possibly mounted in the kernel or
 271                         # in the methods of some of the file system
 272                         # services
 273                         #
 274                         continue
 275                         ;;
 276                 * )
 277                         if [ -n "$HFLAG" ]; then
 278                                 if [ "$fstype" = "nfs" ]; then
 279                                         thishost=`print_host $dev`
 280                                         if [ "$HOST" != "$thishost" ]; then
 281                                                 continue
 282                                         fi
 283                                 else
 284                                         continue
 285                                 fi
 286                         fi
 287                         if [ -n "$FFLAG" -a "$FSType" != "$fstype" ]; then
 288                                 continue
 289                         fi
 290                         if [ -n "$LFLAG" -a "$fstype" = "nfs" ]; then
 291                                 continue
 292                         fi
 293                         if [ -n "$RFLAG" -a "$fstype" != "nfs" ]; then
 294                                 continue
 295                         fi
 296                         if [ "$ZONENAME" != "global" ]; then
 297                                 for option in `echo $mode | tr , '\012'`; do
 298                                         #
 299                                         # should not see any zone options
 300                                         # but our own
 301                                         #
 302                                         if [ "$option" = "zone=$ZONENAME" ]; then
 303                                                 break
 304                                         fi
 305                                 done
 306                                 if [ "$option" != "zone=$ZONENAME" ]; then
 307                                         continue
 308                                 fi
















 309                         fi
 310                         if [ -n "${KFLAG}" ]; then
 311                                 fuser -c -k $mountp 1>&2
 312                                 sleep 2
 313                         fi
 314                         if [ -n "$SFLAG" ]; then
 315                                 umount ${UMOUNTFLAG} ${mountp} 1>&2
 316                                 trc=$?
 317                                 if [ $trc -ne 0 ]; then
 318                                         rc=$trc
 319                                 fi
 320                         else
 321                                 # We want to umount in parallel
 322                                 fslist="$fslist $mountp"
 323                         fi
 324                 esac
 325         done
 326 
 327         if [ -n "$fslist" ]; then
 328                 umount -a ${UMOUNTFLAG} $fslist 1>&2
 329                 trc=$?
 330                 if [ $trc -ne 0 ]; then
 331                         rc=$trc
 332                 fi
 333         fi
 334 
 335         echo $rc
 336         )
 337 }
 338 
 339 #
 340 # /etc/mnttab has the most recent mounts last.  Reverse it so that we
 341 # may umount in opposite order to the original mounts.
 342 #
 343 
 344 if [ ! -x /usr/bin/tail ]; then
 345         exec < $MNTTAB
 346         REVERSED=
 347         while read line; do
 348                 if [ -n "$REVERSED" ]; then
 349                         REVERSED="$line\n$REVERSED"
 350                 else
 351                         REVERSED="$line"
 352                 fi
 353         done
 354 
 355         error=`echo $REVERSED | doumounts`
 356 else
 357         error=`tail -r $MNTTAB | doumounts`
 358 fi
 359 
 360 exit $error
--- EOF ---