Home | History | Annotate | Download | only in common_files
      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