#!/bin/sh # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # ident "%Z%%M% %I% %E% SMI" # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # PATH=/usr/bin:/usr/sbin:$PATH; export PATH PREFIX=/tmp/scsi_vhci.$$ FPCONF=kernel/drv/fp.conf # # Add any new entries to be added to fp.conf to this file. The class action # script for fp.conf will append the entries of this file to fp.conf. # NEW_FPCONF_ENTRIES=/tmp/fp.conf.new_entries # # Check if mpxio is enabled or disabled in the given scsi_vhci.conf file # $1 scsi_vhci.conf file # # Returns 0 if disabled, 1 if enabled, 2 if can't determine. # is_mpxio_enabled() { if egrep "^[ ]*mpxio-disable[ ]*=[ ]*\"yes\"[ ]*;" \ $1 > /dev/null 2>&1; then return 0 fi if egrep "^[ ]*mpxio-disable[ ]*=[ ]*\"no\"[ ]*;" \ $1 > /dev/null 2>&1; then return 1 fi return 2 } # # Make sed script to do most of the work of upgrading scsi_vhci.conf. # make_sed_script() { # # remove mpxio-disable and forceattach properties. # forceattach is no longer necessary as the framework always loads # scsi_vhci early during boot. # cat > $SEDSCRIPT << EOF /^# mpxio Global enable\/disable configuration$/d /^# possible values are mpxio-disable="no" or mpxio-disable="yes"$/d /^# mpxio global enable\/disable switch: setting mpxio-disable="no" will activate$/d /^# I\/O multipathing; setting mpxio-disable="yes" disables this feature (do$/d /^# not remove this property).$/d /^[ ]*mpxio-disable[ ]*=/d /^# Force load driver to support hotplug activity (do not remove this property).$/d /^ddi-forceattach=1;$/d EOF # # convert old 'scsi-options' oriented device-type-scsi-options-list to # new 'name' oriented scsi-vhci-failover-override # cat > $SEDSCRIPT << EOF /^# For enabling MPxIO support for 3rd party symmetric device need an$/d /^# entry similar to following in this file. Just replace the "SUN SENA"$/d /^# part with the Vendor ID\/Product ID for the device, exactly as reported by$/d /^# Inquiry cmd.$/d /^# device-type-scsi-options-list =$/d /^# "SUN SENA", "symmetric-option";$/d /^# symmetric-option = 0x1000000;$/d s/device-type-scsi-options-list/scsi-vhci-failover-override/ EOF # old 'symetric' scsi-options property of 1000000 -> f_sym name SYMMETRIC_OPTION=`grep -v '^#' $2 | grep 1000000 | \ awk -F= '{print $1}'|awk '{print $1}'` if [ "$SYMMETRIC_OPTION"x != "x" ]; then echo "/^[ ]*$SYMMETRIC_OPTION/d" >> $SEDSCRIPT echo "s/$SYMMETRIC_OPTION/f_sym/" >> $SEDSCRIPT fi # old 'disable' scsi-options property of 7000000 -> NONE name DISABLE_OPTION=`grep -v '^#' $2 | grep 7000000 | \ awk -F= '{print $1}'|awk '{print $1}'` if [ "$DISABLE_OPTION"x != "x" ]; then echo "/^[ ]*$DISABLE_OPTION/d" >> $SEDSCRIPT echo "s/$DISABLE_OPTION/NONE/" >> $SEDSCRIPT fi } # # Make FAILOVER_MODULE_BLOCK file # make_fmbfile() { # # Form file with new scsi_vhci FAILOVER_MODULE_BLOCK information # cat > $FMBFILE << EOF #BEGIN: FAILOVER_MODULE_BLOCK (DO NOT MOVE OR DELETE) # # Declare scsi_vhci failover module paths with 'ddi-forceload' so that # they get loaded early enough to be available for scsi_vhci root use. # # NOTE: Correct operation depends on the value of 'ddi-forceload', this # value should not be changed. The ordering of entries is from # most-specific failover modules (with a "probe" implementation that is # completely VID/PID table based), to most generic (failover modules that # are based on T10 standards like TPGS). By convention the last part of a # failover module path, after "/scsi_vhci_", is called the # "failover-module-name", which begins with "f_" (like "f_asym_sun"). The # "failover-module-name" is also used in the override mechanism below. ddi-forceload = "misc/scsi_vhci/scsi_vhci_f_asym_sun", "misc/scsi_vhci/scsi_vhci_f_asym_lsi", "misc/scsi_vhci/scsi_vhci_f_asym_emc", "misc/scsi_vhci/scsi_vhci_f_sym_emc", "misc/scsi_vhci/scsi_vhci_f_sym_hds", "misc/scsi_vhci/scsi_vhci_f_sym", # "misc/scsi_vhci/scsi_vhci_f_tpgs_tape", # "misc/scsi_vhci/scsi_vhci_f_tape", "misc/scsi_vhci/scsi_vhci_f_tpgs"; # # For a device that has a GUID, discovered on a pHCI with mpxio enabled, vHCI # access also depends on one of the scsi_vhci failover modules accepting the # device. The default way this occurs is by a failover module's "probe" # implementation (sfo_device_probe) indicating the device is supported under # scsi_vhci. To override this default probe-oriented configuration in # order to # # 1) establish support for a device not currently accepted under scsi_vhci # # or 2) override the module selected by "probe" # # or 3) disable scsi_vhci support for a device # # you can add a 'scsi-vhci-failover-override' tuple, as documented in # scsi_get_device_type_string(9F). For each tuple, the first part provides # basic device identity information (vid/pid) and the second part selects # the failover module by "failover-module-name". If you want to disable # scsi_vhci support for a device, use the special failover-module-name "NONE". # Currently, for each failover-module-name in 'scsi-vhci-failover-override' # (except "NONE") there needs to be a # "misc/scsi_vhci/scsi_vhci_<failover-module-name>" in 'ddi-forceload' above. # # " 111111" # "012345670123456789012345", "failover-module-name" or "NONE" # "|-VID--||-----PID------|", # scsi-vhci-failover-override = # "STK FLEXLINE 400", "f_asym_lsi", # "SUN T4", "f_tpgs", # "CME XIRTEMMYS", "NONE"; # #END: FAILOVER_MODULE_BLOCK (DO NOT MOVE OR DELETE) EOF } # # Upgrade the destination scsi_vhci.conf file. # $1 source scsi_vhci.conf file # $2 destination scsi_vhci.conf file (the file to be upgraded) # # Returns 0 on success, non zero on failure. # update_scsi_vhci() { TMPSCSIVHCI=$PREFIX.conf SEDSCRIPT=$PREFIX.sed FMBFILE=$PREFIX.fb # make sed script to do most of the work of upgrading make_sed_script $1 $2 sed -f $SEDSCRIPT $2 > $TMPSCSIVHCI 2>/dev/null retval=$? if [ $retval -eq 0 ]; then cp $TMPSCSIVHCI $2 grep "FAILOVER_MODULE_BLOCK" $2 >/dev/null 2>&1 if [ $? -ne 0 ]; then make_fmbfile cat $FMBFILE >> $2 fi fi rm -f $SEDSCRIPT $TMPSCSIVHCI $FMBFILE return $retval } # # Preprocess a driver.conf file. The output is written to out file. # $1 driver.conf file # $2 out file # preprocess() { TMPPREPROCESS=$PREFIX.preprocess # strip comments, blank lines, leading and trailing spaces sed -e "/^[ ]*#/d" \ -e "/^[ ]*$/d" \ -e "s/^[ ]*//" \ -e "s/[ ]*$//" $1 > $TMPPREPROCESS # combine entries that spawn more than one line sed -e "/;$/p" \ -e "/;$/d" \ -e ":rdnext" \ -e "N" \ -e "s/\n/ /" \ -e "/;$/p" \ -e "/;$/d" \ -e "b rdnext" $TMPPREPROCESS > $2 rm -f $TMPPREPROCESS } # # Disable mpxio on all fp ports. # $1 fp.conf file # # Returns 0 on success, non zero on failure. # disable_mpxio_globally() { TMPFP1=$PREFIX.fp1 TMPFP2=$PREFIX.fp2 if [ ! -f $1 ]; then echo "mpxio-disable=\"yes\";" > $NEW_FPCONF_ENTRIES return 0 fi # # change all occurrences of mpxio-disable (including per port) value # from "no" to "yes" except in comments. # sed -e "/^[ ]*#/p" -e "/^[ ]*#/d" \ -e "s/mpxio-disable[ ]*=[ ]*\"no\"/mpxio-disable=\"yes\"/g"\ $1 > $TMPFP1 2>/dev/null retval=$? if [ $retval -eq 0 ]; then preprocess $TMPFP1 $TMPFP2 # add global mpxio-disable if not already present egrep "^mpxio-disable[ ]*=[ ]*\"yes\"[ ]*;" \ $TMPFP2 >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "mpxio-disable=\"yes\";" > $NEW_FPCONF_ENTRIES fi cp $TMPFP1 $1 rm -f $TMPFP2 fi rm -f $TMPFP1 return $retval } # # Check if mpxio-disable entry is present in fp.conf file for the specified # controller and port. # # $1 fp.conf file # $2 controller name # $3 port number # # Returns 1 if the entry is present, 0 if not. # check_mpxio() { TMPFILE=$PREFIX.check preprocess $1 $TMPFILE if egrep "parent[ ]*=[ ]*\"$2\"" $TMPFILE \ 2>/dev/null | egrep "port[ ]*=[ ]*$3" 2>/dev/null | \ egrep "mpxio-disable[ ]*=[ ]*\".*\"" >/dev/null 2>&1; then rm -f $TMPFILE return 1 fi rm -f $TMPFILE return 0 } # # Reads vfstab entry fields corresponding to the specified mount point. # This function assumes that stdin is already set to vfstab. # # $1 mount point # readvfstab() { while read special fsckdev mountp fstype fsckpass automnt mntopts; do case "$special" in '#'* | '') # Ignore comments, empty lines continue ;; '-') # Ignore no-action lines continue esac [ "x$mountp" = "x$1" ] && break done } # # Disable mpxio on the specified controller if the controller had mpxio # disabled (implicitly) before the upgrade. # # $1 directory on which the root filesystem of the OS image being # upgraded is mounted. # $2 /dev link or /devices name of the root slice whose controller needs # to have mpxio disabled. # disable_mpxio() { if echo "$2" | grep "/devices/" >/dev/null 2>&1; then physpath=`echo "$2" | sed "s/^.*\/devices\//\//" 2>/dev/null` elif echo "$2" | grep "/dev/" >/dev/null 2>&1; then # it is /dev link physpath=`ls -l $1/$2 | sed "s/^.*\/devices\//\//" 2>/dev/null` else return fi if echo "$physpath" | grep "/fp@" >/dev/null 2>&1; then # extract controller and port number controller=`echo "$physpath" | sed "s/\/fp@.*$//" 2>/dev/null` port=`echo "$physpath" | sed -e "s/^.*\/fp@//" 2>/dev/null \ -e "s/,0\/.*$//" 2>/dev/null` # # add an entry to fp.conf to disable mpxio only if not already # present. # check_mpxio $1/$FPCONF $controller $port if [ $? -eq 0 ]; then echo "name=\"fp\" parent=\"$controller\" port=$port \ mpxio-disable=\"yes\";" >> $NEW_FPCONF_ENTRIES fi fi } # # Disable mpxio on the root controller if it was implicitly disabled before # the upgrade. # # Note that s8 and s9 didn't have mpxio support on the root controller. # So root controller always had mpxio disabled. But Network Storage supplies a # patch to enable mpxio on the root controller. # # $1 directory on which the root filesystem of the OS image being # upgraded is mounted. # disable_mpxio_on_root() { rel=`uname -r | cut -f 2 -d .` if [ $rel -lt 10 ]; then # live upgrade root=/ else root=$1 fi # # if the root is a metadevice disable mpxio on each of the component # controllers if the component controller had mpxio disabled before. # if mount | grep "^$root on /dev/md/dsk/" >/dev/null 2>&1; then metadev=`mount | grep "^$root on /dev/md/dsk/" | \ cut -f3 -d " " | cut -f5 -d "/"` devlist=`metastat -p $metadev | grep " 1 1 " | \ sed -e "s/^.* 1 1 //" | cut -f1 -d " "` if [ "x$devlist" = x ]; then return fi for d in $devlist do disable_mpxio $1 /dev/dsk/$d done else exec < ${root}/etc/vfstab; readvfstab "/" disable_mpxio $1 $special fi } if read src dest; then # first delete if a stale version of this file exists rm -f $NEW_FPCONF_ENTRIES if [ ! -f $dest ]; then cp $src $dest # # If we are upgrading from s7 or s8, scsi_vhci.conf file # won't exist and mpxio needs to be globally disabled. # # XXX Install doesn't provide a way to distinguish between # fresh install and upgrade. In this hack we assume that if # the system's vfstab already contains an entry for the root # it must be an upgrade. # if [ -s $PKG_INSTALL_ROOT/etc/vfstab ]; then exec < $PKG_INSTALL_ROOT/etc/vfstab; readvfstab "/" if [ "x$mountp" = x/ ]; then disable_mpxio_globally $PKG_INSTALL_ROOT/$FPCONF if [ $? -ne 0 ]; then exit 1 fi fi fi exit 0 fi is_mpxio_enabled $dest mpxio_on=$? update_scsi_vhci $src $dest if [ $? -ne 0 ]; then exit 1 fi if [ $mpxio_on -eq 0 ]; then disable_mpxio_globally $PKG_INSTALL_ROOT/$FPCONF if [ $? -ne 0 ]; then exit 1 fi elif [ $mpxio_on -eq 1 ]; then if [ "x$PKG_INSTALL_ROOT" != x ]; then disable_mpxio_on_root $PKG_INSTALL_ROOT else disable_mpxio_on_root / fi fi fi exit 0