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