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