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 we're an x86/x64 machine and our bootpath is on fibrechannel 246 # then we cannot disable mpxio for that controller. Yet..... 247 # This code block is an ugly hack and when we either get full-time 248 # mpxio for all devices, or devfsadm gets re-written then we can 249 # remove it. For now, though, we have to see the beauty in ugly. 250 251 if [ "x$MACH" = "xi386" ]; then 252 BOOTPATH=`/usr/sbin/eeprom bootpath | $AWK -F"=" '{print $2}'` 253 FPBOOT=`echo "$BOOTPATH" | $GREP "/fp@"` 254 if [ ! -z "$FPBOOT" ]; then 255 NEWP=`/usr/bin/dirname $BOOTPATH` 256 NNEWP=`/usr/bin/dirname $NEWP` 257 258 # check that we haven't already got this entry 259 # in /kernel/drv/fp.conf. 260 261 EXISTP=`$GREP "^name.*$NNEWP" /kernel/drv/fp.conf` 262 if [ $? != 0 ]; then 263 cat >>/kernel/drv/fp.conf << EOF 264# This entry must be the last one in the fp.conf file 265# to ensure that the boot path mpxio setting is not 266# accidentally overridden 267name="fp" parent="$NNEWP" port=0 mpxio-disable="no"; 268EOF 269 fi 270 fi 271 fi 272 273 if [ $need_bootscript -gt 0 ]; then 274 need_bootscript=1 275 if [ "x$MACH" = "xi386" -a "x$new_bootpath" != "x" ]; then 276 #only update bootpath for x86. 277 cp $BOOTENV_FILE $SAVEDIR 278 /usr/sbin/eeprom bootpath=$new_bootpath 279 fi 280 # 281 # Enable the mpxio-upgrade service, but don't run it now. 282 # The service will run during the next reboot and will do 283 # the actual job of modifying the system files. 284 # 285 $SVCADM disable -t $STMSINSTANCE 286 $SVCCFG -f - << EOF 287select $STMSINSTANCE 288setprop general/enabled = true 289EOF 290 else 291 need_bootscript=0 292 fi 293 294 build_recover $need_bootscript 295 296 if [ "x$MACH" = "xi386" ]; then 297 $BOOTADM update-archive 298 fi 299 300 gettext "The changes will come into effect after rebooting the system.\nReboot the system now ? [y/n] (default: y) " 301 read response 302 303 if [ "x$response" = x -o "x$response" = xy -o \ 304 "x$response" = xY ]; then 305 /usr/sbin/reboot 306 fi 307 308 return 0 309} 310 311# 312# Enable or disable mpxio as specified by the cmd. 313# Returns 0 on success, 1 on failure. 314# 315# Args: $cmd = {enable | disable} 316# $d = {fp | mpt} 317# 318# the global variable $DRVLIST is used 319# 320configure_mpxio() 321{ 322 mpxiodisableno='mpxio-disable[ ]*=[ ]*"no"[ ]*;' 323 mpxiodisableyes='mpxio-disable[ ]*=[ ]*"yes"[ ]*;' 324 325 if [ "x$cmd" = xenable ]; then 326 mpxiodisable_cur_entry=$mpxiodisableyes 327 propval=no 328 msg=`gettext "STMS already enabled"` 329 else 330 mpxiodisable_cur_entry=$mpxiodisableno 331 propval=yes 332 msg=`gettext "STMS already disabled"` 333 fi 334 335 DRVCONF=$d.conf 336 KDRVCONF=/kernel/drv/$d.conf 337 TMPDRVCONF=/var/run/tmp.$d.conf.$$ 338 TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$; 339 340 echo "Checking mpxio status for driver $d" 341 if delete_mpxio_disable_entries $KDRVCONF $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY; then 342 343 if [ -s $TMPDRVCONF_MPXIO_ENTRY ]; then 344 # $DRVCONF does have mpxiodisable entries 345 $EGREP -s "$mpxiodisable_cur_entry" $TMPDRVCONF_MPXIO_ENTRY 346 if [ $? -ne 0 ]; then 347 # if all mpxiodisable entries are no/yes for 348 # enable/disable mpxio, notify the user 349 rm -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1 350 continue; 351 else 352 reboot_needed=`$EXPR $reboot_needed + 1` 353 fi 354 355 # If mpxiodisable entries do not exist, always continue update 356 fi 357 else 358 rm -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1 359 gettext "failed to update " 1>&2 360 echo "$KDRVCONF." 1>&2 361 gettext "No changes were made to your STMS configuration.\n" 1>&2 362 return 1 363 fi 364 365 rm $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1 366 echo "mpxio-disable=\"${propval}\";" >> $TMPDRVCONF 367 368} 369 370setcmd() 371{ 372 if [ "x$cmd" = xnone ]; then 373 cmd=$1 374 else 375 echo "$USAGE" 1>&2 376 exit 2 377 fi 378} 379 380# 381#Need to update bootpath on x86 if boot system from FC disk 382#Only update bootpath here when mpxio is enabled 383#If mpxio is disabled currently, will update bootpath in mpxio-upgrade 384# 385 386get_newbootpath_for_stmsdev() { 387 if [ "x$cmd" = "xenable" ]; then 388 return 0 389 fi 390 391 cur_bootpath=`eeprom bootpath | \ 392 sed 's/bootpath=[ ]*//g' | sed 's/[ ]*$//'` 393 if [ "x$cur_bootpath" = "x" ]; then 394 gettext "failed to get bootpath by eeprom\n" 1>&2 395 return 1 396 fi 397 398 #only update bootpath for STMS path 399 echo $cur_bootpath|$EGREP $CLIENT_TYPE_VHCI > /dev/null 2>&1 400 if [ $? -eq 1 ]; then 401 return 0 402 fi 403 404 new_bootpath=`$STMSBOOTUTIL -p /devices$cur_bootpath` 405 if [ $? -ne 0 ]; then 406 new_bootpath="" 407 return 1 408 fi 409 410 # we replace "sd" with "disk" if we need to work on the eeprom 411 # bootpath setting, since fibre-channel devices will report as 412 # being attached via "disk" and not "sd". One day we'll have a 413 # truly unified and architecture-independent view of the device 414 # tree, and this block will be redundant 415 fp_bootpath=`echo $new_bootpath|grep fp.*sd` 416 if [ "x$fp_bootpath" != "x" ]; then 417 new_bootpath=`echo $fp_bootpath |sed -e"s,sd,disk,g"` 418 fi 419} 420 421# 422# Emit a warning message to the user that by default we 423# operate on all multipath-capable controllers that are 424# attached to the system, and that if they want to operate 425# on only a specific controller type (fp|mpt|....) then 426# they need to re-invoke stmsboot with "-D $driver" in 427# their argument list 428# 429 430emit_driver_warning_msg() { 431 432 # for each driver that we support, grab the list 433 # of controllers attached to the system. 434 435 echo "" 436 echo "WARNING: stmsboot operates on each supported multipath-capable controller" 437 echo " detected in a host. In your system, these controllers are" 438 439 for WARNDRV in `echo $SUPPORTED_DRIVERS| $SED -e"s,|, ,g"`; do 440 for i in `$STMSBOOTUTIL -D $WARNDRV -n | $SED -e"s,|, ,g"`; do 441 $GREP "$i.*$WARNDRV.$" /etc/path_to_inst | $AWK -F"\"" '{print "/devices"$2}' 442 done; 443 done; 444 445 echo "" 446 echo "If you do NOT wish to operate on these controllers, please quit stmsboot" 447 echo "and re-invoke with -D { fp | mpt } to specify which controllers you wish" 448 echo "to modify your multipathing configuration for." 449 450 echo "" 451 gettext "Do you wish to continue? [y/n] (default: y) " 1>&2 452 read response 453 454 if [ "x$response" != "xY" -a "x$response" != "xy" ]; then 455 exit 456 fi 457 458} 459 460cmd=none 461 462# process options 463while getopts D:geduLl: c 464do 465 case $c in 466 e) setcmd enable;; 467 d) setcmd disable;; 468 u) setcmd update;; 469 L) setcmd listall;; 470 l) setcmd list 471 controller=$OPTARG;; 472 D) DRV=$OPTARG;; 473 g) GUID="-g";; 474 \?) echo "$USAGE" 1>&2 475 exit 2;; 476 esac 477done 478 479if [ "x$cmd" = xnone ]; then 480 echo "$USAGE" 1>&2 481 exit 2 482fi 483 484if [ "x$DRV" = "x" ]; then 485 DRVLIST="fp mpt" 486else 487 DRVLIST=$DRV 488fi 489 490 491STMSPRIVS=`/usr/bin/ppriv $$ | $EGREP "E:.*all|E:.*sys_devices"` 492USERID=`id` 493if [ "$USERID" != "uid=0(root) gid=0(root)" ] -o [ "x$STMSPRIVS" == "x" ]; then 494 gettext "You must be super-user to run this script.\n" 1>&2 495 exit 1 496fi 497 498# just a sanity check 499if [ ! -f $STMSBOOTUTIL -o ! -f $STMSMETHODSCRIPT ]; then 500 fmt=`gettext "Can't find %s and/or %s"` 501 printf "$fmt\n" "$STMSBOOTUTIL" "$STMSMETHODSCRIPT" 1>&2 502 exit 1 503fi 504 505# If the old sun4u-specific SMF method is found, remove it 506$SVCCFG -s "platform/sun4u/mpxio-upgrade:default" < /dev/null > /dev/null 2>&1 507if [ $? -eq 0 ]; then 508 $SVCCFG delete "platform/sun4u/mpxio-upgrade:default" > /dev/null 2>&1 509fi 510 511# now import the new service, if necessary 512$SVCPROP -q $STMSINSTANCE < /dev/null > /dev/null 2>&1 513if [ $? -ne 0 ]; then 514 if [ -f /var/svc/manifest/system/device/mpxio-upgrade.xml ]; then 515 $SVCCFG import /var/svc/manifest/system/device/mpxio-upgrade.xml 516 if [ $? -ne 0 ]; then 517 fmt=`gettext "Unable to import %s service"` 518 printf "$fmt\n" "$STMSINSTANCE" 1>&2 519 exit 1 520 else 521 fmt=`gettext "Service %s imported successfully, continuing"` 522 printf "$fmt\n" "$STMSINSTANCE" 1>&2 523 fi 524 else 525 fmt=`gettext "Service %s does not exist on this host"` 526 printf "$fmt\n" "$STMSINSTANCE" 1>&2 527 exit 1 528 fi 529fi 530 531if [ "x$cmd" = xenable -o "x$cmd" = xdisable -o "x$cmd" = xupdate ]; then 532 # 533 # The bootup script doesn't work on cache-only-clients as the script 534 # is executed before the plumbing for cachefs mounting of root is done. 535 # 536 if $MOUNT -v | $EGREP -s " on / type (nfs|cachefs) "; then 537 gettext "This command option is not supported on systems with nfs or cachefs mounted root filesystem.\n" 1>&2 538 exit 1 539 fi 540 541 # if the user has left the system with the mpxio-upgrade service 542 # in a temporarily disabled state (ie, service is armed for the next 543 # reboot), then let them know. We need to ensure that the system is 544 # is in a sane state before allowing any further invocations, so 545 # try to get the system admin to do so 546 547 ISARMED=`$SVCS -l $STMSINSTANCE |$GREP "enabled.*temporary"` 548 if [ $? -eq 0 ]; then 549 echo "" 550 echo "You need the reboot the system in order to complete" 551 echo "the previous invocation of stmsboot." 552 echo "" 553 echo "Do you wish to reboot the system now? (y/n, default y) \c" 554 read response 555 556 if [ "x$response" = "xY" -o "x$response" = "xy" ]; then 557 /usr/sbin/reboot 558 else 559 /bin/echo "" 560 /bin/echo "Please reboot this system before continuing" 561 /bin/echo "" 562 exit 1 563 fi 564 fi 565 566 if [ -d $SAVEDIR ]; then 567 # 568 # keep a copy of the last saved files, useful for manual 569 # recovery in case of a problem. 570 # 571 for d in $DRVLIST; do 572 DRVCONF=$d.conf 573 KDRVCONF=/kernel/drv/$d.conf 574 TMPDRVCONF=/var/run/tmp.$d.conf.$$ 575 TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$; 576 577 if [ "x$MACH" = "xsparc" ]; then 578 backup_lastsaved $KDRVCONF $VFSTAB 579 else 580 backup_lastsaved $KDRVCONF $VFSTAB $BOOTENV_FILE 581 fi 582 done 583 else 584 mkdir $SAVEDIR 585 fi 586 587fi 588 589if [ "x$cmd" = xenable -o "x$cmd" = xdisable ]; then 590 591 msgneeded=`echo "$DRVLIST" |grep " "` 592 if [ -n "$msgneeded" ]; then 593 emit_driver_warning_msg 594 fi 595 for d in $DRVLIST; do 596 configure_mpxio $cmd $d 597 done 598 599 if [ $reboot_needed -ne 0 ]; then 600 601 # Need to update bootpath on x86 if our boot device is 602 # now accessed through mpxio. 603 # Only update bootpath before reboot when mpxio is enabled 604 # If mpxio is currently disabled, we will update bootpath 605 # on reboot in the mpxio-upgrade service 606 607 if [ "x$MACH" = "xi386" -a "x$cmd" = "xdisable" ]; then 608 get_newbootpath_for_stmsdev 609 if [ $? -ne 0 ]; then 610 rm -f $TMPDRVCONF > /dev/null 2>&1 611 gettext "failed to update bootpath.\n" 1>&2 612 gettext "No changes were made to your STMS configuration.\n" 1>&2 613 return 1 614 fi 615 fi 616 update_sysfiles 617 else 618 echo "STMS is already ${cmd}d. No changes or reboots needed" 619 fi 620 621 622elif [ "x$cmd" = xupdate ]; then 623 if [ "x$MACH" = "xi386" ]; then 624 # In this case we always change the bootpath to phci-based 625 # path first. bootpath will later be modified in mpxio-upgrade 626 # to the vhci-based path if mpxio is enabled on root. 627 get_newbootpath_for_stmsdev 628 if [ $? -ne 0 ]; then 629 gettext "failed to update bootpath.\n" 1>&2 630 return 1 631 fi 632 fi 633 update_sysfiles 634 635elif [ "x$cmd" = xlist ]; then 636 $STMSBOOTUTIL $GUID -l $controller 637else 638 $STMSBOOTUTIL $GUID -L 639fi 640 641exit $? 642