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