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 2008 Sun Microsystems, Inc.  All rights reserved.
  24 # Use is subject to license terms.
  25 #


  26 #       Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
  27 #         All Rights Reserved
  28 #
  29 #
  30 
  31 usage () {
  32         if [ -n "$1" ]; then
  33                 echo "umountall: $1" 1>&2
  34         fi
  35         echo "Usage:\n\tumountall [-k] [-s] [-F FSType] [-l|-r] [-z] [-n]" 1>&2
  36         echo "\tumountall [-k] [-s] [-h host] [-z] [-n]" 1>&2
  37         exit 2
  38 }
  39 
  40 MNTTAB=/etc/mnttab
  41 
  42 # This script is installed as both /sbin/umountall (as used in some
  43 # /sbin/rc? and /etc/init.d scripts) _and_ as /usr/sbin/umountall (typically
  44 # PATHed from the command line).  As such it should not depend on /usr
  45 # being mounted (if /usr is a separate filesystem).
  46 #
  47 # /sbin/sh Bourne shell builtins we use:
  48 #       echo
  49 #       exit
  50 #       getopts
  51 #       test, [ ]
  52 #       exec
  53 #       read
  54 #
  55 # /sbin commands we use:
  56 #       /sbin/uname
  57 #       /sbin/umount
  58 #
  59 # The following /usr based commands may be used by this script (depending on
  60 # command line options).  We will set our PATH to find them, but where they
  61 # are not present (eg, if /usr is not mounted) we will catch references to
  62 # them via shell functions conditionally defined after option processing
  63 # (don't use any of these commands before then).
  64 #
  65 #       Command         Command line option and use
  66 # /usr/bin/sleep        -k, to sleep after an fuser -c -k on the mountpoint
  67 # /usr/sbin/fuser       -k, to kill processes keeping a mount point busy
  68 #

  69 # In addition, we use /usr/bin/tail if it is available; if not we use
  70 # slower shell constructs to reverse a file.
  71 
  72 PATH=/sbin:/usr/sbin:/usr/bin
  73 
  74 DEFERRED_ACTIVATION_PATCH_FLAG="/var/run/.patch_loopback_mode"
  75 SVC_STARTD="/lib/svc/bin/svc.startd"
  76 
  77 # Clear these in case they were already set in our inherited environment.
  78 FSType=
  79 FFLAG=
  80 HOST=
  81 HFLAG=
  82 RFLAG=
  83 LFLAG=
  84 SFLAG=
  85 KFLAG=
  86 ZFLAG=
  87 NFLAG=
  88 LOCALNAME=
  89 UMOUNTFLAG=
  90 
  91 
  92 while getopts ?rslkF:h:zn c
  93 do
  94         case $c in
  95         r)      RFLAG="r";;
  96         l)      LFLAG="l";;
  97         s)      SFLAG="s";;
  98         k)      KFLAG="k";;
  99         h)      if [ -n "$HFLAG" ]; then
 100                         usage "more than one host specified"
 101                 fi
 102                 HOST=$OPTARG
 103                 HFLAG="h"
 104                 LOCALNAME=`uname -n`
 105                 ;; 
 106         F)      if [ -n "$FFLAG" ]; then
 107                         usage "more than one FStype specified"
 108                 fi
 109                 FSType=$OPTARG 
 110                 FFLAG="f"
 111                 case $FSType in
 112                 ?????????*) 
 113                         usage "FSType ${FSType} exceeds 8 characters"
 114                 esac;
 115                 ;;
 116         z)      ZFLAG="z";;
 117         n)      NFLAG="n"
 118                 # Alias any commands that would perform real actions to
 119                 # something that tells what action would have been performed
 120                 UMOUNTFLAG="-V"
 121                 fuser () {
 122                         echo "fuser $*" 1>&2
 123                 }
 124                 sleep () {
 125                         : # No need to show where we'd sleep
 126                 }
 127                 ;;
 128         \?)     usage ""
 129                 ;;
 130         esac
 131 done
 132 
 133 # Sanity checking:
 134 #       1) arguments beyond those supported
 135 #       2) can't specify both remote and local
 136 #       3) can't specify a host with -r or -l
 137 #       4) can't specify a fstype with -h
 138 #       5) can't specify this host with -h (checks only uname -n)
 139 #       6) can't be fstype nfs and local
 140 #       7) only fstype nfs is remote
 141 
 142 if [ $# -ge $OPTIND ]; then                                             # 1
 143         usage "additional arguments not supported"
 144 fi
 145 
 146 if [ -n "$RFLAG" -a -n "$LFLAG" ]; then                                 # 2
 147         usage "options -r and -l are incompatible"
 148 fi
 149 
 150 if [ \( -n "$RFLAG" -o -n "$LFLAG" \) -a "$HFLAG" = "h" ]; then         # 3
 151         usage "option -${RFLAG}${LFLAG} incompatible with -h option"
 152 fi
 153 
 154 if [ -n "$FFLAG" -a "$HFLAG" = "h" ]; then                              # 4
 155         usage "Specifying FStype incompatible with -h option"
 156 fi
 157 
 158 if [ -n "$HFLAG" -a "$HOST" = "$LOCALNAME" ]; then                      # 5
 159         usage "Specifying local host illegal for -h option"
 160 fi
 161 
 162 if [ "$FSType" = "nfs" -a "$LFLAG" = "l" ]; then                        # 6
 163         usage "option -l and FSType nfs are incompatible"
 164 fi
 165 
 166 if [ -n "$FFLAG" -a "$FSType" != "nfs"  -a -n "$RFLAG" ]; then          # 7
 167         usage "option -r and FSType ${FSType} are incompatible"
 168 fi
 169 
 170 ZONENAME=`zonename`
 171 
 172 # Check and if needed sync the boot archive before unmounting everything.
 173 #
 174 if [ -z "${RFLAG}${NFLAG}${HFLAG}${FSType}" -a "$ZONENAME" = "global" -a \
 175     `uname -p` = "i386" -a -x /sbin/bootadm ] ; then
 176         /sbin/bootadm -a update_all
 177 fi
 178 

 179 #
 180 # If we are in deferred activation patching, and the caller is
 181 # svc.startd, then exit without unmounting any of the remaining
 182 # file systems since the call path is from shutdown.  Note that
 183 # by the time we get here, smf stop methods for nfs, cachefs
 184 # etc, will have run.
 185 #
 186 if [ -f $DEFERRED_ACTIVATION_PATCH_FLAG ] ; then
 187         ppid=`ps -o ppid= -p $$`        # parent of umountall will be sh
 188                                         # from system()
 189 
 190         ppid=`ps -o ppid= -p $ppid`     # parent of sh will be svc.startd
 191         COMM=`ps -o comm= -p $ppid`
 192         if [ "$COMM" = "$SVC_STARTD" ] ; then
 193                 exit
 194         fi
 195 fi
 196 
 197 #
 198 # Take advantage of parallel unmounting at this point if we have no
 199 # criteria to match and we are in the global zone
 200 #
 201 if [ -z "${SFLAG}${LFLAG}${RFLAG}${HFLAG}${KFLAG}${FFLAG}${ZFLAG}" -a \
 202     "$ZONENAME" = "global" ]; then
 203         umount -a ${UMOUNTFLAG}
 204         exit                    # with return code of the umount -a
 205 fi
 206 
 207 #
 208 # Catch uses of /usr commands when /usr is not mounted
 209 if [ -n "$KFLAG" -a -z "$NFLAG" ]; then
 210         if [ ! -x /usr/sbin/fuser ]; then
 211                 fuser () {
 212                         echo "umountall: fuser -k skipped (no /usr)" 1>&2
 213                         # continue - not fatal
 214                 }
 215                 sleep () {
 216                         : # no point in sleeping if fuser is doing nothing
 217                 }
 218         else
 219                 if [ ! -x /usr/bin/sleep ]; then
 220                         sleep () {
 221                                 echo "umountall: sleep after fuser -k skipped (no /usr)" 1>&2
 222                                 # continue - not fatal
 223                         }
 224                 fi
 225         fi
 226 fi
 227 
 228 #
 229 # Shell function to avoid using /usr/bin/cut.  Given a dev from a
 230 # fstype=nfs line in mnttab (eg, "host:/export) extract the host
 231 # component.
 232 print_host () {
 233         OIFS=$IFS
 234         IFS=":"
 235         set -- $*
 236         echo $1
 237         IFS=$OIFS
 238 }
 239 
 240 #
 241 # doumounts echos its return code to stdout, so commands used within
 242 # this function should take care to produce no other output to stdout.
 243 doumounts () {
 244         (
 245         rc=0
 246         fslist=""
 247         while read dev mountp fstype mode dummy
 248         do
 249                 case "${mountp}" in
 250                 /                       | \
 251                 /dev                    | \
 252                 /dev/fd                 | \
 253                 /devices                | \
 254                 /etc/mnttab             | \
 255                 /etc/svc/volatile       | \
 256                 /lib                    | \
 257                 /proc                   | \
 258                 /sbin                   | \
 259                 /system/contract        | \
 260                 /system/object          | \
 261                 /tmp                    | \
 262                 /usr                    | \
 263                 /var                    | \
 264                 /var/adm                | \
 265                 /var/run                | \
 266                 '' )
 267                         #
 268                         # file systems possibly mounted in the kernel or
 269                         # in the methods of some of the file system
 270                         # services
 271                         #
 272                         continue
 273                         ;;
 274                 * )
 275                         if [ -n "$HFLAG" ]; then
 276                                 if [ "$fstype" = "nfs" ]; then
 277                                         thishost=`print_host $dev`
 278                                         if [ "$HOST" != "$thishost" ]; then
 279                                                 continue
 280                                         fi
 281                                 else
 282                                         continue
 283                                 fi
 284                         fi
 285                         if [ -n "$FFLAG" -a "$FSType" != "$fstype" ]; then
 286                                 continue
 287                         fi
 288                         if [ -n "$LFLAG" -a "$fstype" = "nfs" ]; then
 289                                 continue
 290                         fi
 291                         if [ -n "$RFLAG" -a "$fstype" != "nfs" ]; then
 292                                 continue
 293                         fi
 294                         if [ "$ZONENAME" != "global" ]; then
 295                                 for option in `echo $mode | tr , '\012'`; do
 296                                         #
 297                                         # should not see any zone options
 298                                         # but our own
 299                                         #
 300                                         if [ "$option" = "zone=$ZONENAME" ]; then
 301                                                 break
 302                                         fi
 303                                 done
 304                                 if [ "$option" != "zone=$ZONENAME" ]; then
 305                                         continue
 306                                 fi
 307                         elif [ -n "$ZFLAG" ]; then
 308                                 #
 309                                 # we are called from global zone with '-z' set:
 310                                 # skip all mounts having 'zone=' option
 311                                 #
 312                                 for option in `echo $mode | tr , '\012'`; do
 313                                         case "$option" in
 314                                         zone=*)
 315                                                 option="zone="
 316                                                 break
 317                                         ;;
 318                                         esac
 319                                 done
 320                                 if [ "$option" = "zone=" ]; then
 321                                         continue
 322                                 fi
 323                         fi
 324                         if [ -n "${KFLAG}" ]; then
 325                                 fuser -c -k $mountp 1>&2
 326                                 sleep 2
 327                         fi
 328                         if [ -n "$SFLAG" ]; then
 329                                 umount ${UMOUNTFLAG} ${mountp} 1>&2
 330                                 trc=$?
 331                                 if [ $trc -ne 0 ]; then
 332                                         rc=$trc
 333                                 fi
 334                         else
 335                                 # We want to umount in parallel
 336                                 fslist="$fslist $mountp"
 337                         fi
 338                 esac
 339         done
 340 
 341         if [ -n "$fslist" ]; then
 342                 umount -a ${UMOUNTFLAG} $fslist 1>&2
 343                 trc=$?
 344                 if [ $trc -ne 0 ]; then
 345                         rc=$trc
 346                 fi
 347         fi
 348 
 349         echo $rc
 350         )
 351 }
 352 
 353 #
 354 # /etc/mnttab has the most recent mounts last.  Reverse it so that we
 355 # may umount in opposite order to the original mounts.
 356 #
 357 
 358 if [ ! -x /usr/bin/tail ]; then
 359         exec < $MNTTAB
 360         REVERSED=
 361         while read line; do
 362                 if [ -n "$REVERSED" ]; then
 363                         REVERSED="$line\n$REVERSED"
 364                 else
 365                         REVERSED="$line"
 366                 fi
 367         done
 368 
 369         error=`echo $REVERSED | doumounts`
 370 else
 371         error=`tail -r $MNTTAB | doumounts`
 372 fi
 373 
 374 exit $error
--- EOF ---