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 2009 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26 27. /lib/svc/share/fs_include.sh 28. /lib/svc/share/net_include.sh 29 30# Make sure that the essential libraries can be found. 31LD_LIBRARY_PATH=/lib; export LD_LIBRARY_PATH 32STMSBOOTUTIL=/lib/mpxio/stmsboot_util 33SAVEDIR=/etc/mpxio 34BOOTDEVICES=$SAVEDIR/boot-devices 35RECOVERFILE=$SAVEDIR/recover_instructions 36DEVFSADM=/usr/sbin/devfsadm 37DUMPADM=/usr/sbin/dumpadm 38METADEVADM=/usr/sbin/metadevadm 39ISROOTDEV="" 40usrmounted=0 41MACH=`/usr/bin/uname -p` 42ECHO=/usr/bin/echo 43CAT=/usr/bin/cat 44CP=/usr/bin/cp 45DF=/usr/bin/df 46LS=/usr/bin/ls 47RM=/usr/bin/rm 48EGREP=/usr/bin/egrep 49SED=/usr/bin/sed 50ZPOOL=/usr/sbin/zpool 51AWK=/usr/bin/awk 52MOUNT=/sbin/mount 53UMOUNT=/sbin/mount 54EEPROM=/usr/sbin/eeprom 55BOOTADM=/usr/sbin/bootadm 56SVCADM=/usr/sbin/svcadm 57 58mpxio_error() 59{ 60 cecho "\nERROR: stmsboot: $1" 61 # 62 # display recovery instructions - the first call logs to the service 63 # log and the second call displays on the console. 64 # 65 shcat $RECOVERFILE 66 shcat $RECOVERFILE >/dev/msglog 2>&1 67 cecho "These instructions were also logged to the file $RECOVERFILE\n" 68} 69 70# 71# root ("/") is already mounted read only by the kernel. 72# Remount the root read-write. 73# 74mpxio_mount_root() 75{ 76 HASZFSROOT=`$DF -g / |grep zfs` 77 RVAL="" 78 79 # In single-user maintenance mode, we don't have a writable 80 # root partition, so we _cannot_ use devlinks. Therefore we 81 # have to do some dancing - first mount the physical path 82 # read-write, then re-run $STMSBOOTUTIL to get the real 83 # devlink mapping, and then re-mount the root slice. Of course, 84 # if we all used ZFS this wouldn't be such a pain! 85 exec < $vfstab; readvfstab / 86 # ZFS root environments should _not_ have an entry for / 87 # in their /etc/vfstab. 88 if [ -n "$special" ]; then 89 # sanity check for ZFSRoot _and_ / in /etc/vfstab 90 if [ -n "$HASZFSROOT" ]; then 91 # ERROR - this would cause a failure later 92 # so let root know about it now and provide 93 # a chance to handle it before filesystem/usr 94 cecho "stmsboot: System has ZFS Root *and* an entry for / in /etc/vfstab\nstmsboot: Please remove the / entry from /etc/vfstab and then run\n# svcadm clear mpxio-upgrade" 95 exit 1 96 fi 97 ISPHYS=`echo $special |$AWK '/^\/dev\/dsk/ {print}'`; 98 if [ -z "$ISPHYS" ]; then 99 # a metadevice, either /dev/md or /dev/vx 100 new_special=$special 101 $MOUNT -o remount,rw $new_special / >/dev/msglog 2>&1 102 else 103 new_special=`$STMSBOOTUTIL -m $special` 104 if [ "x$new_special" = "xNOT_MAPPED" ]; then 105 # this is a bad state to be in, exit 106 cecho "Error: Your root device is not mapped." 107 exit 1 108 fi 109 checkopt "llock" $mntopts 110 mntopts='remount' 111 [ -n "$otherops" ] && mntopts="${mntopts},${otherops}" 112 RVAL=`$MOUNT -m -F $fstype -o $mntopts $new_special \ 113 $mountp >/dev/msglog 2>&1` 114 # if we've got active-active paths to our rootvp and 115 # the first path returned by $STMSBOOTUTIL is not the 116 # same as the one we booted from, then we need some 117 # handwaving due to restrictions in the ufs module 118 # (see the remountfs() function in 119 # $SRC/uts/common/fs/ufs/ufs_vfsops.c) 120 if [ $? -eq 0 ]; then 121 # now re-run $STMSBOOTUTIL to get the real 122 # mapping for this device 123 new_special=`$STMSBOOTUTIL -m $special` 124 # mount root for real 125 $MOUNT -o remount,rw $new_special / \ 126 >/dev/msglog 2>&1 127 else 128 SLICE=`$ECHO $special | $AWK -F"s" '{print $3}'` 129 for device in `$CAT $BOOTDEVICES`; do 130 new_special="${device}s${SLICE}" 131 $MOUNT -m -F $fstype -o $mntopts \ 132 $new_special $mountp >/dev/msglog 2>&1 133 if [ $? -eq 0 ]; then 134 # success, break out 135 ISROOTDEV=`$ECHO $new_special | 136 $SED -e "s,/dev/dsk/,,"` 137 break; 138 fi 139 done 140 if [ -n "$RVAL" ]; then 141 cecho "Error: Unable to remount your root device" 142 exit 1; 143 fi 144 fi 145 fi 146 else 147 if [ -z "$HASZFSROOT" ]; then 148 cecho "stmsboot: Error: your root slice is invalid" 149 exit 1 150 else 151 cecho "stmsboot: Root is on ZFS" 152 fi 153 fi 154} 155 156# 157# mount /usr read only 158# 159mpxio_mount_usr() 160{ 161 exec < $vfstab; readvfstab "/usr" 162 ret_val=0 163 if [ -n "$mountp" ]; then 164 new_special=`$STMSBOOTUTIL -m $special` 165 166 if [ "$fstype" = cachefs ]; then 167 # Mount read-only without the cache. 168 case "$mntopts" in 169 *backfstype=nfs*) 170 cfsbacktype=nfs 171 ;; 172 *backfstype=hsfs*) 173 cfsbacktype=hsfs 174 ;; 175 *) 176 cecho 'stmsboot: invalid vfstab entry for /usr' 177 cfsbacktype=nfs 178 ;; 179 esac 180 # see the comment below for /dev/null 181 $MOUNT -m -F $cfsbacktype -o ro $new_special $mountp \ 182>/dev/null 2>&1 183 ret_val=$? 184 else 185 # 186 # Must use -o largefiles here to ensure the read-only 187 # mount does not fail as a result of having a large 188 # file present on /usr. 189 # 190 if [ "x$mntopts" = x- ]; then 191 mntopts='ro,largefiles' 192 else 193 checkopt largefiles $mntopts 194 if [ "x$option" != xlargefiles ]; then 195 mntopts="largefiles,$mntopts" 196 fi 197 198 checkopt ro $mntopts 199 if [ "x$option" != xro ]; then 200 mntopts="ro,$mntopts" 201 fi 202 203 # Requesting logging on a read-only mount 204 # causes errors to be displayed, so remove 205 # "logging" from the list of options. 206 checkopt logging $mntopts 207 if [ "x$option" = xlogging ]; then 208 mntopts="$otherops" 209 fi 210 fi 211 212 # In case of a manual restart of the service, mount 213 # will emit messages if /usr is already mounted. 214 # So redirect the output to /dev/null. 215 $MOUNT -m -F $fstype -o $mntopts $new_special /usr \ 216>/dev/null 2>&1 217 ret_val=$? 218 fi 219 if [ $ret_val -eq 0 ]; then 220 usrmounted=1 221 fi 222 fi 223 224 return $ret_val 225} 226 227# update system dump configuration 228update_dumpconf() 229{ 230 # Disable device-in-use checking (done in libdiskmgt). 231 # Without disabling this check, the configuration of dump device 232 # would fail as the device-in-use code incorrectly concludes that 233 # the device is in use and hence prevents configuration of the dump 234 # device. 235 NOINUSE_CHECK=1 236 export NOINUSE_CHECK 237 238 DUMPISZFS=`$AWK -F"=" '/DUMPADM_DEVICE/ {print $2}' /etc/dumpadm.conf|$EGREP zvol` 239 if [ "x$DUMPISZFS" = "x" ]; then 240 set -- `$DUMPADM -u 2>&1 | $EGREP 'cannot use /dev.* as dump device'` 241 if [ "x$4" != x ]; then 242 newname=`$STMSBOOTUTIL -m $4` 243 if [ $? -eq 0 ]; then 244 if $DUMPADM -d $newname > /dev/msglog 2> /dev/console; then 245 cecho "stmsboot: dump configuration \ 246 has been updated." 247 else 248 mpxio_error "failed to configure \ 249 the dump device.\nold \ 250 dump device name: $4" 251 return 1 252 fi 253 fi 254 fi 255 else 256 # make sure we can get to it, force zfs to load fully 257 $LS $DUMPISZFS >>/dev/null 2>&1 258 cecho "stmsboot: dump on ZFS, no dumpadm update required" 259 fi 260 return 0 261} 262 263# Update bootpath for x86 here when we are enabling mpxio on root 264update_bootpath() 265{ 266 cur_bootpath=`$STMSBOOTUTIL -b` 267 if [ $? != 0 ]; then 268 cecho "stmsboot: ERROR! Unable to retrieve bootpath property\n" 269 exit 1 270 fi 271 272 NEWBOOTPATH="" 273 for path in $cur_bootpath; do 274 mapped=`$STMSBOOTUTIL -p $path` 275 if [ "$mapped" != "NOT_MAPPED" ]; then 276 if [ "x$mapped" != "x$path" ]; then 277 NEWBOOTPATH=`echo "$path " | \ 278 $SED -e"s|$path|$mapped|"`" $NEWBOOTPATH" 279 else 280 NEWBOOTPATH="$NEWBOOTPATH $path" 281 fi 282 fi 283 done 284 # now strip off leading and trailing space chars 285 new_bootpath=`echo $NEWBOOTPATH` 286 $EEPROM bootpath="$new_bootpath" 287 cecho "stmsboot: bootpath has been updated" 288 cecho "" 289} 290 291# Now do the actual work 292mpxio_main() 293{ 294 # NOTE: If the first attempt to run the service has failed due to an 295 # expected error, users should be able to manually rerun the service. 296 # 297 # First mount /usr read only. This must be done to run 298 # utilities such as fsck and devfsadm. 299 # In the case of a manual rerun of the service, mounting of /usr here 300 # fails if /usr already happens to be mounted. It is better that we 301 # do not mount /usr if already mounted, but there seems to be no 302 # apparent way to check whether /usr is mounted or not as we mount 303 # /usr without making an entry into /etc/mnttab. So instead of 304 # explicitly checking for mount failures, we just do a sanity check 305 # by looking for some file (in this case devfsadm) in /usr. 306 # 307 mpxio_mount_usr 308 if [ ! -s $DEVFSADM ]; then 309 mpxio_error "failed to mount the /usr filesystem." 310 return 311 fi 312 313 if mpxio_mount_root; then 314 # create /dev links 315 cecho "stmsboot: configuring devices" 316 $DEVFSADM 317 318 # update /etc/vfstab to reflect device name changes 319 $STMSBOOTUTIL -u >/dev/msglog 2>&1 320 if [ $? -eq 0 ]; then 321 $CP /etc/vfstab /etc/vfstab.old 322 # handle active-active paths, where the probe order 323 # for the hba reports a different path to what the 324 # boot-device variable gives us 325 if [ -n "$ISROOTDEV" ]; then 326 ROOTDEVCHK=`grep $ISROOTDEV /etc/vfstab` 327 if [ $? != 0 ]; then 328 # we got a different path for root 329 exec < $SAVEDIR/vfstab.new; readvfstab / 330 FILEDEV=`$ECHO $special | \ 331 $SED -e"s,/dev/dsk/,,"` 332 $SED -e"s,$FILEDEV,$ISROOTDEV,g" < \ 333 $SAVEDIR/vfstab.new > /etc/vfstab 334 fi 335 else 336 $CP $SAVEDIR/vfstab.new /etc/vfstab 337 fi 338 $RM $SAVEDIR/vfstab.new 339 cecho "" 340 cecho "stmsboot: vfstab has been updated" 341 if update_dumpconf; then 342 # update svm configuration to reflect new names 343 if [ -s /kernel/drv/md.conf ] && \ 344 [ -x $METADEVADM ]; then 345 $METADEVADM -r >/dev/msglog 2>&1 346 fi 347 fi 348 if [ "x$MACH" = "xi386" ]; then 349 # only update bootpath here for x86 350 update_bootpath 351 fi 352 cecho "stmsboot: now regenerating boot archive" 353 $BOOTADM update-archive 354 else 355 mpxio_error "failed to update /etc/vfstab." 356 fi 357 358 $SVCADM disable system/device/mpxio-upgrade 359 else 360 mpxio_error "failed to mount the root filesystem." 361 if [ $usrmounted -eq 1 ]; then 362 $UMOUNT /usr 363 fi 364 fi 365} 366 367mpxio_main 368