1 #!/bin/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 # ident "%Z%%M% %I% %E% SMI" 23 # 24 # Copyright 2008 Sun Microsystems, Inc. All rights reserved. 25 # Use is subject to license terms. 26 # 27 28 PATH=/usr/bin:/usr/sbin:$PATH; export PATH 29 30 PREFIX=/tmp/scsi_vhci.$$ 31 FPCONF=kernel/drv/fp.conf 32 # 33 # Add any new entries to be added to fp.conf to this file. The class action 34 # script for fp.conf will append the entries of this file to fp.conf. 35 # 36 NEW_FPCONF_ENTRIES=/tmp/fp.conf.new_entries 37 38 # 39 # Check if mpxio is enabled or disabled in the given scsi_vhci.conf file 40 # $1 scsi_vhci.conf file 41 # 42 # Returns 0 if disabled, 1 if enabled, 2 if can't determine. 43 # 44 is_mpxio_enabled() 45 { 46 if egrep "^[ ]*mpxio-disable[ ]*=[ ]*\"yes\"[ ]*;" \ 47 $1 > /dev/null 2>&1; then 48 return 0 49 fi 50 51 if egrep "^[ ]*mpxio-disable[ ]*=[ ]*\"no\"[ ]*;" \ 52 $1 > /dev/null 2>&1; then 53 return 1 54 fi 55 56 return 2 57 } 58 59 # 60 # Make sed script to do most of the work of upgrading scsi_vhci.conf. 61 # 62 make_sed_script() 63 { 64 # 65 # remove mpxio-disable and forceattach properties. 66 # forceattach is no longer necessary as the framework always loads 67 # scsi_vhci early during boot. 68 # 69 cat > $SEDSCRIPT << EOF 70 /^# mpxio Global enable\/disable configuration$/d 71 /^# possible values are mpxio-disable="no" or mpxio-disable="yes"$/d 72 /^# mpxio global enable\/disable switch: setting mpxio-disable="no" will activate$/d 73 /^# I\/O multipathing; setting mpxio-disable="yes" disables this feature (do$/d 74 /^# not remove this property).$/d 75 /^[ ]*mpxio-disable[ ]*=/d 76 /^# Force load driver to support hotplug activity (do not remove this property).$/d 77 /^ddi-forceattach=1;$/d 78 EOF 79 # 80 # convert old 'scsi-options' oriented device-type-scsi-options-list to 81 # new 'name' oriented scsi-vhci-failover-override 82 # 83 cat > $SEDSCRIPT << EOF 84 /^# For enabling MPxIO support for 3rd party symmetric device need an$/d 85 /^# entry similar to following in this file. Just replace the "SUN SENA"$/d 86 /^# part with the Vendor ID\/Product ID for the device, exactly as reported by$/d 87 /^# Inquiry cmd.$/d 88 /^# device-type-scsi-options-list =$/d 89 /^# "SUN SENA", "symmetric-option";$/d 90 /^# symmetric-option = 0x1000000;$/d 91 s/device-type-scsi-options-list/scsi-vhci-failover-override/ 92 EOF 93 # old 'symetric' scsi-options property of 1000000 -> f_sym name 94 SYMMETRIC_OPTION=`grep -v '^#' $2 | grep 1000000 | \ 95 awk -F= '{print $1}'|awk '{print $1}'` 96 if [ "$SYMMETRIC_OPTION"x != "x" ]; then 97 echo "/^[ ]*$SYMMETRIC_OPTION/d" >> $SEDSCRIPT 98 echo "s/$SYMMETRIC_OPTION/f_sym/" >> $SEDSCRIPT 99 fi 100 101 # old 'disable' scsi-options property of 7000000 -> NONE name 102 DISABLE_OPTION=`grep -v '^#' $2 | grep 7000000 | \ 103 awk -F= '{print $1}'|awk '{print $1}'` 104 if [ "$DISABLE_OPTION"x != "x" ]; then 105 echo "/^[ ]*$DISABLE_OPTION/d" >> $SEDSCRIPT 106 echo "s/$DISABLE_OPTION/NONE/" >> $SEDSCRIPT 107 fi 108 } 109 110 # 111 # Make FAILOVER_MODULE_BLOCK file 112 # 113 make_fmbfile() 114 { 115 # 116 # Form file with new scsi_vhci FAILOVER_MODULE_BLOCK information 117 # 118 cat > $FMBFILE << EOF 119 #BEGIN: FAILOVER_MODULE_BLOCK (DO NOT MOVE OR DELETE) 120 # 121 # Declare scsi_vhci failover module paths with 'ddi-forceload' so that 122 # they get loaded early enough to be available for scsi_vhci root use. 123 # 124 # NOTE: Correct operation depends on the value of 'ddi-forceload', this 125 # value should not be changed. The ordering of entries is from 126 # most-specific failover modules (with a "probe" implementation that is 127 # completely VID/PID table based), to most generic (failover modules that 128 # are based on T10 standards like TPGS). By convention the last part of a 129 # failover module path, after "/scsi_vhci_", is called the 130 # "failover-module-name", which begins with "f_" (like "f_asym_sun"). The 131 # "failover-module-name" is also used in the override mechanism below. 132 ddi-forceload = 133 "misc/scsi_vhci/scsi_vhci_f_asym_sun", 134 "misc/scsi_vhci/scsi_vhci_f_asym_lsi", 135 "misc/scsi_vhci/scsi_vhci_f_asym_emc", 136 "misc/scsi_vhci/scsi_vhci_f_sym_emc", 137 "misc/scsi_vhci/scsi_vhci_f_sym_hds", 138 "misc/scsi_vhci/scsi_vhci_f_sym", 139 # "misc/scsi_vhci/scsi_vhci_f_tpgs_tape", 140 # "misc/scsi_vhci/scsi_vhci_f_tape", 141 "misc/scsi_vhci/scsi_vhci_f_tpgs"; 142 143 # 144 # For a device that has a GUID, discovered on a pHCI with mpxio enabled, vHCI 145 # access also depends on one of the scsi_vhci failover modules accepting the 146 # device. The default way this occurs is by a failover module's "probe" 147 # implementation (sfo_device_probe) indicating the device is supported under 148 # scsi_vhci. To override this default probe-oriented configuration in 149 # order to 150 # 151 # 1) establish support for a device not currently accepted under scsi_vhci 152 # 153 # or 2) override the module selected by "probe" 154 # 155 # or 3) disable scsi_vhci support for a device 156 # 157 # you can add a 'scsi-vhci-failover-override' tuple, as documented in 158 # scsi_get_device_type_string(9F). For each tuple, the first part provides 159 # basic device identity information (vid/pid) and the second part selects 160 # the failover module by "failover-module-name". If you want to disable 161 # scsi_vhci support for a device, use the special failover-module-name "NONE". 162 # Currently, for each failover-module-name in 'scsi-vhci-failover-override' 163 # (except "NONE") there needs to be a 164 # "misc/scsi_vhci/scsi_vhci_<failover-module-name>" in 'ddi-forceload' above. 165 # 166 # " 111111" 167 # "012345670123456789012345", "failover-module-name" or "NONE" 168 # "|-VID--||-----PID------|", 169 # scsi-vhci-failover-override = 170 # "STK FLEXLINE 400", "f_asym_lsi", 171 # "SUN T4", "f_tpgs", 172 # "CME XIRTEMMYS", "NONE"; 173 # 174 #END: FAILOVER_MODULE_BLOCK (DO NOT MOVE OR DELETE) 175 EOF 176 } 177 178 # 179 # Upgrade the destination scsi_vhci.conf file. 180 # $1 source scsi_vhci.conf file 181 # $2 destination scsi_vhci.conf file (the file to be upgraded) 182 # 183 # Returns 0 on success, non zero on failure. 184 # 185 update_scsi_vhci() 186 { 187 TMPSCSIVHCI=$PREFIX.conf 188 SEDSCRIPT=$PREFIX.sed 189 FMBFILE=$PREFIX.fb 190 191 # make sed script to do most of the work of upgrading 192 make_sed_script $1 $2 193 194 sed -f $SEDSCRIPT $2 > $TMPSCSIVHCI 2>/dev/null 195 retval=$? 196 if [ $retval -eq 0 ]; then 197 cp $TMPSCSIVHCI $2 198 grep "FAILOVER_MODULE_BLOCK" $2 >/dev/null 2>&1 199 if [ $? -ne 0 ]; then 200 make_fmbfile 201 cat $FMBFILE >> $2 202 fi 203 fi 204 205 rm -f $SEDSCRIPT $TMPSCSIVHCI $FMBFILE 206 return $retval 207 } 208 209 # 210 # Preprocess a driver.conf file. The output is written to out file. 211 # $1 driver.conf file 212 # $2 out file 213 # 214 preprocess() 215 { 216 TMPPREPROCESS=$PREFIX.preprocess 217 218 # strip comments, blank lines, leading and trailing spaces 219 sed -e "/^[ ]*#/d" \ 220 -e "/^[ ]*$/d" \ 221 -e "s/^[ ]*//" \ 222 -e "s/[ ]*$//" $1 > $TMPPREPROCESS 223 224 # combine entries that spawn more than one line 225 sed -e "/;$/p" \ 226 -e "/;$/d" \ 227 -e ":rdnext" \ 228 -e "N" \ 229 -e "s/\n/ /" \ 230 -e "/;$/p" \ 231 -e "/;$/d" \ 232 -e "b rdnext" $TMPPREPROCESS > $2 233 234 rm -f $TMPPREPROCESS 235 } 236 237 # 238 # Disable mpxio on all fp ports. 239 # $1 fp.conf file 240 # 241 # Returns 0 on success, non zero on failure. 242 # 243 disable_mpxio_globally() 244 { 245 TMPFP1=$PREFIX.fp1 246 TMPFP2=$PREFIX.fp2 247 248 if [ ! -f $1 ]; then 249 echo "mpxio-disable=\"yes\";" > $NEW_FPCONF_ENTRIES 250 return 0 251 fi 252 253 # 254 # change all occurrences of mpxio-disable (including per port) value 255 # from "no" to "yes" except in comments. 256 # 257 sed -e "/^[ ]*#/p" -e "/^[ ]*#/d" \ 258 -e "s/mpxio-disable[ ]*=[ ]*\"no\"/mpxio-disable=\"yes\"/g"\ 259 $1 > $TMPFP1 2>/dev/null 260 261 retval=$? 262 if [ $retval -eq 0 ]; then 263 preprocess $TMPFP1 $TMPFP2 264 # add global mpxio-disable if not already present 265 egrep "^mpxio-disable[ ]*=[ ]*\"yes\"[ ]*;" \ 266 $TMPFP2 >/dev/null 2>&1 267 if [ $? -ne 0 ]; then 268 echo "mpxio-disable=\"yes\";" > $NEW_FPCONF_ENTRIES 269 fi 270 cp $TMPFP1 $1 271 rm -f $TMPFP2 272 fi 273 274 rm -f $TMPFP1 275 return $retval 276 } 277 278 # 279 # Check if mpxio-disable entry is present in fp.conf file for the specified 280 # controller and port. 281 # 282 # $1 fp.conf file 283 # $2 controller name 284 # $3 port number 285 # 286 # Returns 1 if the entry is present, 0 if not. 287 # 288 check_mpxio() 289 { 290 TMPFILE=$PREFIX.check 291 292 preprocess $1 $TMPFILE 293 if egrep "parent[ ]*=[ ]*\"$2\"" $TMPFILE \ 294 2>/dev/null | egrep "port[ ]*=[ ]*$3" 2>/dev/null | \ 295 egrep "mpxio-disable[ ]*=[ ]*\".*\"" >/dev/null 2>&1; then 296 rm -f $TMPFILE 297 return 1 298 fi 299 300 rm -f $TMPFILE 301 return 0 302 } 303 304 # 305 # Reads vfstab entry fields corresponding to the specified mount point. 306 # This function assumes that stdin is already set to vfstab. 307 # 308 # $1 mount point 309 # 310 readvfstab() 311 { 312 while read special fsckdev mountp fstype fsckpass automnt mntopts; do 313 case "$special" in 314 '#'* | '') # Ignore comments, empty lines 315 continue ;; 316 '-') # Ignore no-action lines 317 continue 318 esac 319 320 [ "x$mountp" = "x$1" ] && break 321 done 322 } 323 324 # 325 # Disable mpxio on the specified controller if the controller had mpxio 326 # disabled (implicitly) before the upgrade. 327 # 328 # $1 directory on which the root filesystem of the OS image being 329 # upgraded is mounted. 330 # $2 /dev link or /devices name of the root slice whose controller needs 331 # to have mpxio disabled. 332 # 333 disable_mpxio() 334 { 335 if echo "$2" | grep "/devices/" >/dev/null 2>&1; then 336 physpath=`echo "$2" | sed "s/^.*\/devices\//\//" 2>/dev/null` 337 elif echo "$2" | grep "/dev/" >/dev/null 2>&1; then 338 # it is /dev link 339 physpath=`ls -l $1/$2 | sed "s/^.*\/devices\//\//" 2>/dev/null` 340 else 341 return 342 fi 343 344 if echo "$physpath" | grep "/fp@" >/dev/null 2>&1; then 345 # extract controller and port number 346 controller=`echo "$physpath" | sed "s/\/fp@.*$//" 2>/dev/null` 347 port=`echo "$physpath" | sed -e "s/^.*\/fp@//" 2>/dev/null \ 348 -e "s/,0\/.*$//" 2>/dev/null` 349 350 # 351 # add an entry to fp.conf to disable mpxio only if not already 352 # present. 353 # 354 check_mpxio $1/$FPCONF $controller $port 355 if [ $? -eq 0 ]; then 356 echo "name=\"fp\" parent=\"$controller\" port=$port \ 357 mpxio-disable=\"yes\";" >> $NEW_FPCONF_ENTRIES 358 fi 359 fi 360 } 361 362 # 363 # Disable mpxio on the root controller if it was implicitly disabled before 364 # the upgrade. 365 # 366 # Note that s8 and s9 didn't have mpxio support on the root controller. 367 # So root controller always had mpxio disabled. But Network Storage supplies a 368 # patch to enable mpxio on the root controller. 369 # 370 # $1 directory on which the root filesystem of the OS image being 371 # upgraded is mounted. 372 # 373 disable_mpxio_on_root() 374 { 375 rel=`uname -r | cut -f 2 -d .` 376 if [ $rel -lt 10 ]; then 377 # live upgrade 378 root=/ 379 else 380 root=$1 381 fi 382 383 # 384 # if the root is a metadevice disable mpxio on each of the component 385 # controllers if the component controller had mpxio disabled before. 386 # 387 if mount | grep "^$root on /dev/md/dsk/" >/dev/null 2>&1; then 388 metadev=`mount | grep "^$root on /dev/md/dsk/" | \ 389 cut -f3 -d " " | cut -f5 -d "/"` 390 devlist=`metastat -p $metadev | grep " 1 1 " | \ 391 sed -e "s/^.* 1 1 //" | cut -f1 -d " "` 392 if [ "x$devlist" = x ]; then 393 return 394 fi 395 for d in $devlist 396 do 397 disable_mpxio $1 /dev/dsk/$d 398 done 399 else 400 exec < ${root}/etc/vfstab; readvfstab "/" 401 disable_mpxio $1 $special 402 fi 403 404 } 405 406 if read src dest; then 407 # first delete if a stale version of this file exists 408 rm -f $NEW_FPCONF_ENTRIES 409 410 if [ ! -f $dest ]; then 411 cp $src $dest 412 # 413 # If we are upgrading from s7 or s8, scsi_vhci.conf file 414 # won't exist and mpxio needs to be globally disabled. 415 # 416 # XXX Install doesn't provide a way to distinguish between 417 # fresh install and upgrade. In this hack we assume that if 418 # the system's vfstab already contains an entry for the root 419 # it must be an upgrade. 420 # 421 if [ -s $PKG_INSTALL_ROOT/etc/vfstab ]; then 422 exec < $PKG_INSTALL_ROOT/etc/vfstab; readvfstab "/" 423 if [ "x$mountp" = x/ ]; then 424 disable_mpxio_globally $PKG_INSTALL_ROOT/$FPCONF 425 if [ $? -ne 0 ]; then 426 exit 1 427 fi 428 fi 429 fi 430 exit 0 431 fi 432 433 is_mpxio_enabled $dest 434 mpxio_on=$? 435 update_scsi_vhci $src $dest 436 if [ $? -ne 0 ]; then 437 exit 1 438 fi 439 440 if [ $mpxio_on -eq 0 ]; then 441 disable_mpxio_globally $PKG_INSTALL_ROOT/$FPCONF 442 if [ $? -ne 0 ]; then 443 exit 1 444 fi 445 elif [ $mpxio_on -eq 1 ]; then 446 if [ "x$PKG_INSTALL_ROOT" != x ]; then 447 disable_mpxio_on_root $PKG_INSTALL_ROOT 448 else 449 disable_mpxio_on_root / 450 fi 451 fi 452 fi 453 454 exit 0 455