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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24 # 25 26 . /lib/svc/share/fs_include.sh 27 . /lib/svc/share/net_include.sh 28 29 # Make sure that the essential libraries can be found. 30 LD_LIBRARY_PATH=/lib; export LD_LIBRARY_PATH 31 STMSBOOTUTIL=/lib/mpxio/stmsboot_util 32 SAVEDIR=/etc/mpxio 33 BOOTDEVICES=$SAVEDIR/boot-devices 34 RECOVERFILE=$SAVEDIR/recover_instructions 35 DEVFSADM=/usr/sbin/devfsadm 36 DUMPADM=/usr/sbin/dumpadm 37 METADEVADM=/usr/sbin/metadevadm 38 ISROOTDEV="" 39 ISROOTDEVPATH="" 40 usrmounted=0 41 UNAME=/usr/bin/uname 42 ECHO=/usr/bin/echo 43 CAT=/usr/bin/cat 44 CP=/usr/bin/cp 45 DF=/usr/bin/df 46 LS=/usr/bin/ls 47 RM=/usr/bin/rm 48 EGREP=/usr/bin/egrep 49 SED=/usr/bin/sed 50 ZPOOL=/usr/sbin/zpool 51 AWK=/usr/bin/awk 52 MOUNT=/sbin/mount 53 UMOUNT=/sbin/mount 54 EEPROM=/usr/sbin/eeprom 55 BOOTADM=/usr/sbin/bootadm 56 SVCADM=/usr/sbin/svcadm 57 REBOOT=/usr/sbin/reboot 58 59 mpxio_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 # 75 mpxio_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 for device in `$CAT $BOOTDEVICES`; do 130 new_special="/devices${device}" 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 ISROOTDEVPATH=`$ECHO $device | \ 136 $AWK -F":" '{print $1}'` 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 # 159 mpxio_mount_usr() 160 { 161 exec < $vfstab; readvfstab "/usr" 162 ret_val=0 163 if [ -n "$mountp" ]; then 164 case "$special" in 165 /dev/md/*) 166 new_special=$special 167 ;; 168 /dev/vx/*) 169 new_special=$special 170 ;; 171 *) 172 new_special=`$STMSBOOTUTIL -m $special` 173 ;; 174 esac 175 176 if [ "$fstype" = "cachefs" ]; then 177 # Mount read-only without the cache. 178 case "$mntopts" in 179 *backfstype=nfs*) 180 cfsbacktype=nfs 181 ;; 182 *backfstype=hsfs*) 183 cfsbacktype=hsfs 184 ;; 185 *) 186 cecho 'stmsboot: invalid vfstab entry for /usr' 187 cfsbacktype=nfs 188 ;; 189 esac 190 # see the comment below for /dev/null 191 $MOUNT -m -F $cfsbacktype -o ro $new_special $mountp \ 192 >/dev/null 2>&1 193 ret_val=$? 194 else 195 # 196 # Must use -o largefiles here to ensure the read-only 197 # mount does not fail as a result of having a large 198 # file present on /usr. 199 # 200 if [ "$mntopts" = "-" ]; then 201 mntopts='ro,largefiles' 202 else 203 checkopt largefiles $mntopts 204 if [ "$option" != "largefiles" ]; then 205 mntopts="largefiles,$mntopts" 206 fi 207 208 checkopt ro $mntopts 209 if [ "$option" != "ro" ]; then 210 mntopts="ro,$mntopts" 211 fi 212 213 # Requesting logging on a read-only mount 214 # causes errors to be displayed, so remove 215 # "logging" from the list of options. 216 checkopt logging $mntopts 217 if [ "$option" = "logging" ]; then 218 mntopts="$otherops" 219 fi 220 fi 221 222 # In case of a manual restart of the service, mount 223 # will emit messages if /usr is already mounted. 224 # So redirect the output to /dev/null. 225 $MOUNT -m -F $fstype -o $mntopts $new_special /usr \ 226 >/dev/null 2>&1 227 ret_val=$? 228 fi 229 if [ $ret_val -eq 0 ]; then 230 usrmounted=1 231 fi 232 fi 233 234 return $ret_val 235 } 236 237 # update system dump configuration 238 update_dumpconf() 239 { 240 # Disable device-in-use checking (done in libdiskmgt). 241 # Without disabling this check, the configuration of dump device 242 # would fail as the device-in-use code incorrectly concludes that 243 # the device is in use and hence prevents configuration of the dump 244 # device. 245 NOINUSE_CHECK=1 246 export NOINUSE_CHECK 247 248 DUMPISZFS=`$AWK -F"=" '/DUMPADM_DEVICE/ {print $2}' /etc/dumpadm.conf|$EGREP zvol` 249 if [ -z "$DUMPISZFS" ]; then 250 set -- `$DUMPADM -u 2>&1 | $EGREP 'cannot use /dev.* as dump device'` 251 if [ -n "$4" ]; then 252 newname=`$STMSBOOTUTIL -m $4` 253 if [ $? -eq 0 ]; then 254 if $DUMPADM -d $newname > /dev/msglog 2> /dev/console; then 255 cecho "stmsboot: dump configuration \ 256 has been updated." 257 else 258 mpxio_error "failed to configure \ 259 the dump device.\nold \ 260 dump device name: $4" 261 return 1 262 fi 263 fi 264 fi 265 else 266 # make sure we can get to it, force zfs to load fully 267 $LS $DUMPISZFS >>/dev/null 2>&1 268 cecho "stmsboot: dump on ZFS, no dumpadm update required" 269 fi 270 return 0 271 } 272 273 # Update bootpath for x86 here when we are enabling mpxio on root 274 update_bootpath() 275 { 276 cur_bootpath=`$STMSBOOTUTIL -b` 277 if [ $? -ne 0 ]; then 278 cecho "stmsboot: ERROR! Unable to retrieve bootpath property\n" 279 exit 1 280 fi 281 282 # Since on x64 platforms the eeprom command doesn't update the 283 # kernel, the file /boot/solaris/bootenv.rc and the kernel's 284 # bootpath variable have a good chance of differing. We do some 285 # extra handwaving to get the correct bootpath variable setting. 286 287 ONDISKVER=`$AWK '/bootpath/ {print $3}' /boot/solaris/bootenv.rc|\ 288 $SED -e"s,',,g"` 289 if [ "$ONDISKVER" != "$cur_bootpath" ]; then 290 cur_bootpath="$ONDISKVER" 291 fi 292 293 NEWBOOTPATH="" 294 for path in $cur_bootpath; do 295 mapped=`$STMSBOOTUTIL -p $path` 296 if [ "$mapped" != "NOT_MAPPED" ]; then 297 if [ "$mapped" != "$path" ]; then 298 NEWBOOTPATH=`echo "$path " | \ 299 $SED -e"s|$path|$mapped|"`" $NEWBOOTPATH" 300 else 301 NEWBOOTPATH="$NEWBOOTPATH $path" 302 fi 303 fi 304 done 305 # now strip off leading and trailing space chars 306 new_bootpath=`echo $NEWBOOTPATH` 307 $EEPROM bootpath="$new_bootpath" 308 cecho "stmsboot: bootpath has been updated" 309 cecho "" 310 } 311 312 # Now do the actual work 313 mpxio_main() 314 { 315 # NOTE: If the first attempt to run the service has failed due to an 316 # expected error, users should be able to manually rerun the service. 317 # 318 # First mount /usr read only. This must be done to run 319 # utilities such as fsck and devfsadm. 320 # In the case of a manual rerun of the service, mounting of /usr here 321 # fails if /usr already happens to be mounted. It is better that we 322 # do not mount /usr if already mounted, but there seems to be no 323 # apparent way to check whether /usr is mounted or not as we mount 324 # /usr without making an entry into /etc/mnttab. So instead of 325 # explicitly checking for mount failures, we just do a sanity check 326 # by looking for some file (in this case devfsadm) in /usr. 327 # 328 mpxio_mount_usr 329 if [ ! -s $DEVFSADM ]; then 330 mpxio_error "failed to mount the /usr filesystem." 331 return 332 fi 333 334 if mpxio_mount_root; then 335 # create /dev links 336 cecho "stmsboot: configuring devices" 337 $DEVFSADM 338 339 if [ -n "$ISROOTDEVPATH" ]; then 340 ISROOTDEV=`$STMSBOOTUTIL -o $ISROOTDEVPATH` 341 fi 342 343 # update /etc/vfstab to reflect device name changes 344 $STMSBOOTUTIL -u >/dev/msglog 2>&1 345 if [ $? -eq 0 ]; then 346 $CP /etc/vfstab /etc/vfstab.old 347 # handle active-active paths, where the probe order 348 # for the hba reports a different path to what the 349 # boot-device variable gives us 350 if [ -n "$ISROOTDEV" ]; then 351 ROOTDEVCHK=`grep $ISROOTDEV /etc/vfstab` 352 if [ $? -ne 0 ]; then 353 # we got a different path for root 354 exec < $SAVEDIR/vfstab.new; readvfstab / 355 FILEDEV=`$ECHO $special | \ 356 $SED -e"s,/dev/dsk/,," -e"s,s[0-9]*,,"` 357 $SED -e"s,$FILEDEV,$ISROOTDEV,g" < \ 358 $SAVEDIR/vfstab.new > /etc/vfstab 359 fi 360 else 361 $CP $SAVEDIR/vfstab.new /etc/vfstab 362 fi 363 $RM $SAVEDIR/vfstab.new 364 cecho "" 365 cecho "stmsboot: vfstab has been updated" 366 367 if update_dumpconf; then 368 # update svm configuration to reflect new names 369 if [ -s /kernel/drv/md.conf ] && \ 370 [ -x $METADEVADM ]; then 371 $METADEVADM -r >/dev/msglog 2>&1 372 fi 373 fi 374 375 MACH=`$UNAME -p` 376 if [ "$MACH" = "i386" ]; then 377 # only update bootpath here for x86 378 update_bootpath 379 fi 380 cecho "stmsboot: now regenerating boot archive" 381 $BOOTADM update-archive 382 else 383 mpxio_error "failed to update /etc/vfstab." 384 fi 385 386 $SVCADM disable system/device/mpxio-upgrade 387 388 if [ $usrmounted -eq 1 ]; then 389 cecho "stmsboot: rebooting the system now." 390 $REBOOT 391 fi 392 else 393 mpxio_error "failed to mount the root filesystem." 394 fi 395 } 396 397 mpxio_main