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 2007 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26#ident "%Z%%M% %I% %E% SMI" 27 28PATH=/usr/bin:/usr/sbin:$PATH; export PATH 29STMSBOOTUTIL=/lib/mpxio/stmsboot_util 30STMSMETHODSCRIPT=/lib/svc/method/mpxio-upgrade 31KDRVCONF= 32DRVCONF= 33TMPDRVCONF= 34TMPDRVCONF_MPXIO_ENTRY= 35DRVLIST= 36GUID= 37VFSTAB=/etc/vfstab 38SAVEDIR=/etc/mpxio 39RECOVERFILE=$SAVEDIR/recover_instructions 40SVCCFG_RECOVERY=$SAVEDIR/svccfg_recover 41SUPPORTED_DRIVERS="fp|mpt" 42USAGE=`gettext "Usage: stmsboot [-D $SUPPORTED_DRIVERS] -e | -d | -u | -L | -l controller_number"` 43TEXTDOMAIN=SUNW_OST_OSCMD 44export TEXTDOMAIN 45STMSINSTANCE=system/device/mpxio-upgrade:default 46STMSBOOT=/usr/sbin/stmsboot 47BOOTADM=/sbin/bootadm 48MOUNT=/usr/sbin/mount 49EGREP=/usr/bin/egrep 50GREP=/usr/bin/grep 51AWK=/usr/bin/awk 52SORT=/usr/bin/sort 53UNIQ=/usr/bin/uniq 54EXPR=/usr/bin/expr 55 56MACH=`/usr/bin/uname -p` 57BOOTENV_FILE=/boot/solaris/bootenv.rc 58 59CLIENT_TYPE_VHCI="/scsi_vhci.*/ssd@|/scsi_vhci.*/disk@" 60# The phci client type egrep string will change based on the 61# drivers which we are operating on, and the cpu architecture 62# and we call stmsboot_util -n -D $drv to get that string 63CLIENT_TYPE_PHCI= 64reboot_needed=0 65 66# 67# Copy all entries (including comments) from source driver.conf 68# to destination driver.conf except those entries which contain 69# the mpxio-disable property. 70# Take into consideration entries that spawn more than one line. 71# 72# $1 source driver.conf file 73# $2 destination driver.conf file 74# 75# Returns 0 on success, non zero on failure. 76# 77delete_mpxio_disable_entries() 78{ 79 sed ' 80 /^[ ]*#/{ p 81 d 82 } 83 s/[ ]*$// 84 /^$/{ p 85 d 86 } 87 /mpxio-disable[ ]*=.*;$/{ w '$3' 88 d 89 } 90 /;$/{ p 91 d 92 } 93 :rdnext 94 N 95 s/[ ]*$// 96 /[^;]$/b rdnext 97 /mpxio-disable[ ]*=/{ s/\n/ /g 98 w '$3' 99 d 100 } 101 ' $1 > $2 102 103 return $? 104} 105 106# 107# backup the last saved copy of the specified files. 108# $* files to backup 109# 110backup_lastsaved() 111{ 112 for file in $* 113 do 114 file=`basename $file` 115 if [ -f $SAVEDIR/$file ]; then 116 mv $SAVEDIR/$file $SAVEDIR/${file}.old 117 fi 118 done 119} 120 121# 122# build recover instructions 123# 124# $1 1 to include boot script in the instructions 125# 0 otherwise 126# 127build_recover() 128{ 129 gettext "Instructions to recover your previous STMS configuration (if in case the system does not boot):\n\n" > $RECOVERFILE 130 echo "\tboot net \c" >> $RECOVERFILE 131 gettext "(or from a cd/dvd/another disk)\n" >> $RECOVERFILE 132 echo "\tfsck <your-root-device>" >> $RECOVERFILE 133 echo "\tmount <your-root-device> /mnt" >> $RECOVERFILE 134 135 if [ "x$cmd" = xupdate ]; then 136 gettext "\tUndo the modifications you made to STMS configuration.\n\tFor example undo any changes you made to " >> $RECOVERFILE 137 echo "/mnt$KDRVCONF." >> $RECOVERFILE 138 else 139 echo "\tcp /mnt${SAVEDIR}/$DRVCONF /mnt$KDRVCONF" >> $RECOVERFILE 140 fi 141 142 if [ $1 -ne 0 ]; then 143 echo "\tcp /mnt${SAVEDIR}/vfstab /mnt$VFSTAB" >> $RECOVERFILE 144 145 echo "repository /mnt/etc/svc/repository.db" > $SVCCFG_RECOVERY 146 echo "select $STMSINSTANCE" >> $SVCCFG_RECOVERY 147 echo "setprop general/enabled=false" >> $SVCCFG_RECOVERY 148 echo "exit" >> $SVCCFG_RECOVERY 149 150 echo "\t/usr/sbin/svccfg -f /mnt$SVCCFG_RECOVERY" >> $RECOVERFILE 151 152 if [ "x$MACH" = "xi386" -a "x$new_bootpath" != "x" ]; then 153 echo "\tcp /mnt${SAVEDIR}/bootenv.rc /mnt$BOOTENV_FILE" >> $RECOVERFILE 154 fi 155 fi 156 157 rootdisk=`$MOUNT | $GREP "/ on " | cut -f 3 -d " "` 158 echo "\tumount /mnt\n\treboot\n\n${rootdisk} \c" >> $RECOVERFILE 159 gettext "was your root device,\nbut it could be named differently after you boot net.\n" >> $RECOVERFILE 160} 161 162# 163# Arrange for /etc/vfstab and dump configuration to be updated 164# during the next reboot. If the cmd is "enable" or "disable", copy 165# $TMPDRVCONF to $KDRVCONF. 166# 167# Returns 0 on success, 1 on failure. 168# 169update_sysfiles() 170{ 171 172 gettext "WARNING: This operation will require a reboot.\nDo you want to continue ? [y/n] (default: y) " 173 read response 174 175 if [ "x$response" != x -a "x$response" != xy -a \ 176 "x$response" != xY ]; then 177 for d in $DRVLIST; do 178 TMPDRVCONF=/var/run/tmp.$d.conf.$$ 179 rm -f $TMPDRVCONF > /dev/null 2>&1 180 done; 181 return 0; 182 fi 183 184 need_bootscript="" 185 186 if [ "x$cmd" = xenable -o "x$cmd" = xdisable ]; then 187 188 for d in $DRVLIST; do 189 DRVCONF=$d.conf 190 KDRVCONF=/kernel/drv/$d.conf 191 TMPDRVCONF=/var/run/tmp.$d.conf.$$ 192 193 cp $KDRVCONF $SAVEDIR 194 cp $TMPDRVCONF $KDRVCONF 195 rm -f $TMPDRVCONF > /dev/null 2>&1 196 197 # 198 # there is no need to update the system files in the following 199 # cases: 200 # - we are enabling mpxio and the system has no configured 201 # disks accessible by phci paths. 202 # - we are disabling mpxio and the system has no configured 203 # disks accessible by vhci paths. 204 # 205 206 build_parent_list $d; 207 if [ "x$CLIENT_TYPE_PHCI" = "x" ]; then 208 continue; 209 fi 210 211 if [ "x$cmd" = "xenable" ]; then 212 ls -l /dev/dsk/*s2 2> /dev/null | \ 213 $EGREP -s "$CLIENT_TYPE_PHCI" 214 else 215 ls -l /dev/dsk/*s2 2> /dev/null | \ 216 $EGREP -s "$CLIENT_TYPE_VHCI" 217 fi 218 219 if [ $? -ne 0 ]; then 220 need_bootscript="$need_bootscript $d" 221 fi 222 done 223 fi 224 225 # if we're an x86/x64 machine and our bootpath is on fibrechannel 226 # then we cannot disable mpxio for that controller. Yet..... 227 # This code block is an ugly hack and when we either get full-time 228 # mpxio for all devices, or devfsadm gets re-written then we can 229 # remove it. For now, though, we have to see the beauty in ugly. 230 231 if [ "x$MACH" = "xi386" ]; then 232 BOOTPATH=`/usr/sbin/eeprom bootpath | $AWK -F"=" '{print $2}'` 233 FPBOOT=`echo "$BOOTPATH" | $GREP "/fp@"` 234 if [ ! -z "$FPBOOT" ]; then 235 NEWP=`/usr/bin/dirname $BOOTPATH` 236 NNEWP=`/usr/bin/dirname $NEWP` 237 238 # check that we haven't already got this entry 239 # in /kernel/drv/fp.conf. 240 241 EXISTP=`$GREP "^name.*$NNEWP" /kernel/drv/fp.conf` 242# if [ -z "$EXISTP" ]; then 243 if [ $? != 0 ]; then 244 cat >>/kernel/drv/fp.conf << EOF 245# This entry must be the last one in the fp.conf file 246# to ensure that the boot path mpxio setting is not 247# accidentally overridden 248name="fp" parent="$NNEWP" port=0 mpxio-disable="no"; 249EOF 250 fi 251 fi 252 fi 253 254 if [ -z "$need_bootscript" ]; then 255 need_bootscript=0 256 if [ "x$MACH" = "xi386" -a "x$new_bootpath" != "x" ]; then 257 #only update bootpath for x86. 258 cp $BOOTENV_FILE $SAVEDIR 259 /usr/sbin/eeprom bootpath=$new_bootpath 260 fi 261 # 262 # Enable the mpxio-upgrade service, but don't run it now. 263 # The service will run during the next reboot and will do 264 # the actual job of modifying the system files. 265 # 266 svcadm disable -t $STMSINSTANCE 267 svccfg -f - << EOF 268select $STMSINSTANCE 269setprop general/enabled = true 270EOF 271 fi 272 273 build_recover $need_bootscript 274 275 if [ "x$MACH" = "xi386" ]; then 276 $BOOTADM update-archive 277 fi 278 279 gettext "The changes will come into effect after rebooting the system.\nReboot the system now ? [y/n] (default: y) " 280 read response 281 282 if [ "x$response" = x -o "x$response" = xy -o \ 283 "x$response" = xY ]; then 284 /usr/sbin/reboot 285 fi 286 287 return 0 288} 289 290# 291# Enable or disable mpxio as specified by the cmd. 292# Returns 0 on success, 1 on failure. 293# 294# Args: $cmd = {enable | disable} 295# $d = {fp | mpt} 296# 297# the global variable $DRVLIST is used 298# 299configure_mpxio() 300{ 301 mpxiodisableno='mpxio-disable[ ]*=[ ]*"no"[ ]*;' 302 mpxiodisableyes='mpxio-disable[ ]*=[ ]*"yes"[ ]*;' 303 304 if [ "x$cmd" = xenable ]; then 305 mpxiodisable_cur_entry=$mpxiodisableyes 306 propval=no 307 msg=`gettext "STMS already enabled"` 308 else 309 mpxiodisable_cur_entry=$mpxiodisableno 310 propval=yes 311 msg=`gettext "STMS already disabled"` 312 fi 313 314 DRVCONF=$d.conf 315 KDRVCONF=/kernel/drv/$d.conf 316 TMPDRVCONF=/var/run/tmp.$d.conf.$$ 317 TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$; 318 319 echo "Checking mpxio status for driver $d" 320 if delete_mpxio_disable_entries $KDRVCONF $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY; then 321 322 if [ -s $TMPDRVCONF_MPXIO_ENTRY ]; then 323 # $DRVCONF does have mpxiodisable entries 324 $EGREP -s "$mpxiodisable_cur_entry" $TMPDRVCONF_MPXIO_ENTRY 325 if [ $? -ne 0 ]; then 326 # if all mpxiodisable entries are no/yes for 327 # enable/disable mpxio, notify the user 328 rm -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1 329 continue; 330 else 331 reboot_needed=`$EXPR $reboot_needed + 1` 332 fi 333 334 # If mpxiodisable entries do not exist, always continue update 335 fi 336 else 337 rm -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1 338 gettext "failed to update " 1>&2 339 echo "$KDRVCONF." 1>&2 340 gettext "No changes were made to your STMS configuration.\n" 1>&2 341 return 1 342 fi 343 344 rm $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1 345 echo "mpxio-disable=\"${propval}\";" >> $TMPDRVCONF 346 347} 348 349setcmd() 350{ 351 if [ "x$cmd" = xnone ]; then 352 cmd=$1 353 else 354 echo "$USAGE" 1>&2 355 exit 2 356 fi 357} 358 359# 360#Need to update bootpath on x86 if boot system from FC disk 361#Only update bootpath here when mpxio is enabled 362#If mpxio is disabled currently, will update bootpath in mpxio-upgrade 363# 364 365get_newbootpath_for_stmsdev() { 366 if [ "x$cmd" = "xenable" ]; then 367 return 0 368 fi 369 370 cur_bootpath=`eeprom bootpath | \ 371 sed 's/bootpath=[ ]*//g' | sed 's/[ ]*$//'` 372 if [ "x$cur_bootpath" = "x" ]; then 373 gettext "failed to get bootpath by eeprom\n" 1>&2 374 return 1 375 fi 376 377 #only update bootpath for STMS path 378 echo $cur_bootpath|$EGREP $CLIENT_TYPE_VHCI > /dev/null 2>&1 379 if [ $? -eq 1 ]; then 380 return 0 381 fi 382 383 new_bootpath=`$STMSBOOTUTIL -p /devices$cur_bootpath` 384 if [ $? -ne 0 ]; then 385 new_bootpath="" 386 return 1 387 fi 388 389 # we replace "sd" with "disk" if we need to work on the eeprom 390 # bootpath setting, since fibre-channel devices will report as 391 # being attached via "disk" and not "sd". One day we'll have a 392 # truly unified and architecture-independent view of the device 393 # tree, and this block will be redundant 394 fp_bootpath=`echo $new_bootpath|grep fp.*sd` 395 if [ "x$fp_bootpath" != "x" ]; then 396 new_bootpath=`echo $fp_bootpath |sed -e"s,sd,disk,g"` 397 fi 398} 399 400# 401# Emit a warning message to the user that by default we 402# operate on all multipath-capable controllers that are 403# attached to the system, and that if they want to operate 404# on only a specific controller type (fp|mpt|....) then 405# they need to re-invoke stmsboot with "-D $driver" in 406# their argument list 407# 408 409emit_driver_warning_msg() { 410 411 # for each driver that we support, grab the list 412 # of controllers attached to the system. 413 414 echo "WARNING: stmsboot operates on each supported multipath-capable controller" 415 echo " detected in a host. In your system, these controllers are" 416 417 for WARNDRV in fp mpt; do 418 $GREP "$WARNDRV.$" /etc/path_to_inst | $AWK -F"\"" '{print "/devices"$2}' 419 done; 420 421 echo "" 422 echo "If you do NOT wish to operate on these controllers, please quit stmsboot" 423 echo "and re-invoke with -D { fp | mpt } to specify which controllers you wish" 424 echo "to modify your multipathing configuration for." 425 426 echo 427 gettext "Do you wish to continue? [y/n] (default: y) " 1>&2 428 read response 429 430 if [ "x$response" -ne "xY" -a "x$response" -ne "xy" ]; then 431 exit 432 fi 433 434} 435 436# Function to setup the CLIENT_TYPE_PHCI string based on 437# the list of drivers that we're operating on. The variable 438# depends upon the pathname of the parent node in the 439# device tree, which can be different on x86/x64 and sparc. 440# Oh, if we only had OBP on x86/x64! 441build_parent_list() { 442 443 # stmsboot_util -n provides us with the name of the 444 # node containing "fp" or "sas-$d", and helpfully 445 # appends "/[ssd|sd]@" as appropriate 446 447 d=$1; 448 449 TLIST=`$STMSBOOTUTIL -D $d -n` 450 if [ "x$TLIST" != "x" ]; then 451 CLIENT_TYPE_PHCI="$TLIST|$CLIENT_TYPE_PHCI" 452 else 453 CLIENT_TYPE_PHCI="$CLIENT_TYPE_PHCI" 454 fi 455} 456 457 458cmd=none 459 460# process options 461while getopts D:geduLl: c 462do 463 case $c in 464 e) setcmd enable;; 465 d) setcmd disable;; 466 u) setcmd update;; 467 L) setcmd listall;; 468 l) setcmd list 469 controller=$OPTARG;; 470 D) DRV=$OPTARG;; 471 g) GUID="-g";; 472 \?) echo "$USAGE" 1>&2 473 exit 2;; 474 esac 475done 476 477if [ "x$cmd" = xnone ]; then 478 echo "$USAGE" 1>&2 479 exit 2 480fi 481 482if [ "x$DRV" = "x" ]; then 483 DRVLIST="fp mpt" 484else 485 DRVLIST=$DRV 486fi 487 488 489STMSPRIVS=`/usr/bin/ppriv $$ | $EGREP "E:.*all|E:.*sys_devices"` 490USERID=`id` 491if [ "$USERID" != "uid=0(root) gid=0(root)" ] -o [ "x$STMSPRIVS" == "x" ]; then 492 gettext "You must be super-user to run this script.\n" 1>&2 493 exit 1 494fi 495 496# just a sanity check 497if [ ! -f $STMSBOOTUTIL -o ! -f $STMSMETHODSCRIPT ]; then 498 fmt=`gettext "Can't find %s and/or %s"` 499 printf "$fmt\n" "$STMSBOOTUTIL" "$STMSMETHODSCRIPT" 1>&2 500 exit 1 501fi 502 503# If the old sun4u-specific SMF method is found, remove it 504/usr/sbin/svccfg -s "platform/sun4u/mpxio-upgrade:default" < /dev/null > /dev/null 2>&1 505if [ $? -ne 0 ]; then 506 /usr/sbin/svccfg delete "platform/sun4u/mpxio-upgrade:default" > /dev/null 2>&1 507fi 508 509# now import the new service, if necessary 510/usr/bin/svcprop -q $STMSINSTANCE < /dev/null > /dev/null 2>&1 511if [ $? -ne 0 ]; then 512 if [ -f /var/svc/manifest/system/device/mpxio-upgrade.xml ]; then 513 /usr/sbin/svccfg import /var/svc/manifest/system/device/mpxio-upgrade.xml 514 if [ $? -ne 0 ]; then 515 fmt=`gettext "Unable to import %s service"` 516 printf "$fmt\n" "$STMSINSTANCE" 1>&2 517 exit 1 518 else 519 fmt=`gettext "Service %s imported successfully, continuing"` 520 printf "$fmt\n" "$STMSINSTANCE" 1>&2 521 fi 522 else 523 fmt=`gettext "Service %s does not exist on this host"` 524 printf "$fmt\n" "$STMSINSTANCE" 1>&2 525 exit 1 526 fi 527fi 528 529if [ "x$cmd" = xenable -o "x$cmd" = xdisable -o "x$cmd" = xupdate ]; then 530 # 531 # The bootup script doesn't work on cache-only-clients as the script 532 # is executed before the plumbing for cachefs mounting of root is done. 533 # 534 if $MOUNT -v | $EGREP -s " on / type (nfs|cachefs) "; then 535 gettext "This command option is not supported on systems with nfs or cachefs mounted root filesystem.\n" 1>&2 536 exit 1 537 fi 538 539 if [ -d $SAVEDIR ]; then 540 # 541 # keep a copy of the last saved files, useful for manual 542 # recovery in case of a problem. 543 # 544 for d in $DRVLIST; do 545 DRVCONF=$d.conf 546 KDRVCONF=/kernel/drv/$d.conf 547 TMPDRVCONF=/var/run/tmp.$d.conf.$$ 548 TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$; 549 550 if [ "x$MACH" = "xsparc" ]; then 551 backup_lastsaved $KDRVCONF $VFSTAB 552 else 553 backup_lastsaved $KDRVCONF $VFSTAB $BOOTENV_FILE 554 fi 555 done 556 else 557 mkdir $SAVEDIR 558 fi 559 560fi 561 562if [ "x$cmd" = xenable -o "x$cmd" = xdisable ]; then 563 564 msgneeded=`echo "$DRVLIST" |grep " "` 565 if [ -n "$msgneeded" ]; then 566 emit_driver_warning_msg 567 fi 568 for d in $DRVLIST; do 569 configure_mpxio $cmd $d 570 done 571 572 if [ $reboot_needed -ne 0 ]; then 573 574 # Need to update bootpath on x86 if our boot device is 575 # now accessed through mpxio. 576 # Only update bootpath before reboot when mpxio is enabled 577 # If mpxio is currently disabled, we will update bootpath 578 # on reboot in the mpxio-upgrade service 579 580 if [ "x$MACH" = "xi386" -a "x$cmd" = "xdisable" ]; then 581 get_newbootpath_for_stmsdev 582 if [ $? -ne 0 ]; then 583 rm -f $TMPDRVCONF > /dev/null 2>&1 584 gettext "failed to update bootpath.\n" 1>&2 585 gettext "No changes were made to your STMS configuration.\n" 1>&2 586 return 1 587 fi 588 fi 589 update_sysfiles 590 else 591 echo "STMS is already ${cmd}d. No changes or reboots needed" 592 fi 593 594 595elif [ "x$cmd" = xupdate ]; then 596 if [ "x$MACH" = "xi386" ]; then 597 # In this case we always change the bootpath to phci-based 598 # path first. bootpath will later be modified in mpxio-upgrade 599 # to the vhci-based path if mpxio is enabled on root. 600 get_newbootpath_for_stmsdev 601 if [ $? -ne 0 ]; then 602 gettext "failed to update bootpath.\n" 1>&2 603 return 1 604 fi 605 fi 606 update_sysfiles 607 608elif [ "x$cmd" = xlist ]; then 609 $STMSBOOTUTIL $GUID -l $controller 610else 611 $STMSBOOTUTIL $GUID -L 612fi 613 614exit $? 615