Mercurial > illumos > illumos-gate
changeset 4022:66494e9fa1c4
PSARC 2006/703 MPxIO extension for Serial Attached SCSI (SAS) on mpt(7D)
PSARC 2007/046 stmsboot(1M) extension for mpt(7D)
6442215 mpt.conf maybe over written because the filetype within the SUNWckr package is 'f'
6443044 add mpxio support to SAS mpt driver
6502231 stmsboot needs to support SAS devices
6510425 the properties "flow_control" and "queue" in mpt.conf is useless
6525558 untagged command unlikely to be sent to HBA during heavy I/O
6545198 build should allow architecture dependent class action scripts
line wrap: on
line diff
--- a/usr/src/cmd/stmsboot/mpxio-upgrade Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/cmd/stmsboot/mpxio-upgrade Thu Apr 12 18:26:33 2007 -0700 @@ -38,6 +38,8 @@ METADEVADM=/usr/sbin/metadevadm usrmounted=0 MACH=`/usr/bin/uname -p` +EGREP=/usr/bin/egrep +SED=/usr$SED # map $special and $fsckdev mpxio_mapdev() @@ -169,11 +171,11 @@ NOINUSE_CHECK=1 export NOINUSE_CHECK - set -- `dumpadm -u 2>&1 | egrep 'cannot use /dev.* as dump device'` + set -- `dumpadm -u 2>&1 | $EGREP 'cannot use /dev.* as dump device'` if [ "x$4" != x ]; then newname=`$STMSBOOTUTIL -M $4` if [ $? -eq 0 ]; then - if dumpadm -d $newname > /dev/null; then + if /usr/sbin/dumpadm -d $newname > /dev/msglog 2> /dev/console; then cecho "stmsboot: dump configuration has been \ updated." else @@ -189,16 +191,17 @@ # Update bootpath for x86 here when we are enabling mpxio on root update_bootpath() { - cur_bootpath=`eeprom bootpath | sed 's/bootpath=[ ]*//g' | sed 's/[ ].*//'` + cur_bootpath=`/usr/sbin/eeprom bootpath | $SED 's/bootpath=[ ]*//g' | $SED 's/[ ].*//'` # only take care of phci-based path here - echo $cur_bootpath | egrep -s "/fp@.*/disk@.*" + PHCIOPT=`$STMSBOOTUTIL -D mpt -n` + echo $cur_bootpath | $EGREP -s "/fp@.*/disk|$PHCIOPT" if [ $? -eq 0 ]; then new_bootpath=`$STMSBOOTUTIL -m /devices$cur_bootpath` if [ $? -eq 0 -a "x$new_bootpath" != "x" ]; then # stmsboot_util -m phci-based path got mapped path back means # mpxio is enabled on bootpath - new_bootpath=`echo $new_bootpath|sed "s/.*\/devices//"` + new_bootpath=`echo $new_bootpath|$SED "s/.*\/devices//"` /usr/sbin/eeprom bootpath=$new_bootpath cecho "stmsboot: bootpath has been updated"
--- a/usr/src/cmd/stmsboot/stmsboot.sh Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/cmd/stmsboot/stmsboot.sh Thu Apr 12 18:26:33 2007 -0700 @@ -28,30 +28,45 @@ PATH=/usr/bin:/usr/sbin:$PATH; export PATH STMSBOOTUTIL=/lib/mpxio/stmsboot_util STMSMETHODSCRIPT=/lib/svc/method/mpxio-upgrade -FPCONF=/kernel/drv/fp.conf -TMPFPCONF=/var/run/tmp.fp.conf.$$ -TMPFPCONF_MPXIO_ENTRY=/var/run/tmp.fp.conf.mpxioentry.$$ +KDRVCONF= +DRVCONF= +TMPDRVCONF= +TMPDRVCONF_MPXIO_ENTRY= +DRVLIST= +GUID= VFSTAB=/etc/vfstab SAVEDIR=/etc/mpxio RECOVERFILE=$SAVEDIR/recover_instructions SVCCFG_RECOVERY=$SAVEDIR/svccfg_recover -USAGE=`gettext "Usage: stmsboot -e | -d | -u | -L | -l controller_number"` +SUPPORTED_DRIVERS="fp|mpt" +USAGE=`gettext "Usage: stmsboot [-D $SUPPORTED_DRIVERS] -e | -d | -u | -L | -l controller_number"` TEXTDOMAIN=SUNW_OST_OSCMD export TEXTDOMAIN STMSINSTANCE=system/device/mpxio-upgrade:default +STMSBOOT=/usr/sbin/stmsboot +BOOTADM=/sbin/bootadm +MOUNT=/usr/sbin/mount +EGREP=/usr/bin/egrep +GREP=/usr/bin/grep +AWK=/usr/bin/awk +SORT=/usr/bin/sort +UNIQ=/usr/bin/uniq +EXPR=/usr/bin/expr MACH=`/usr/bin/uname -p` -if [ "x$MACH" = "xsparc" ]; then - CLIENT_TYPE_VHCI="/scsi_vhci.*/ssd@.*" - CLIENT_TYPE_PHCI="/fp@.*/ssd@.*" -else - CLIENT_TYPE_VHCI="/scsi_vhci.*/disk@.*" - CLIENT_TYPE_PHCI="/fp@.*/disk@.*" - BOOTENV_FILE=/boot/solaris/bootenv.rc -fi +BOOTENV_FILE=/boot/solaris/bootenv.rc + +CLIENT_TYPE_VHCI="/scsi_vhci.*/ssd@|/scsi_vhci.*/disk@" +# The phci client type egrep string will change based on the +# drivers which we are operating on, and the cpu architecture +# and we call stmsboot_util -n -D $drv to get that string +CLIENT_TYPE_PHCI= +reboot_needed=0 + # -# Copy all entries (including comments) from source driver.conf to destination -# driver.conf except those entries which contain mpxio-disable property. +# Copy all entries (including comments) from source driver.conf +# to destination driver.conf except those entries which contain +# the mpxio-disable property. # Take into consideration entries that spawn more than one line. # # $1 source driver.conf file @@ -119,12 +134,12 @@ if [ "x$cmd" = xupdate ]; then gettext "\tUndo the modifications you made to STMS configuration.\n\tFor example undo any changes you made to " >> $RECOVERFILE - echo "/mnt$FPCONF." >> $RECOVERFILE + echo "/mnt$KDRVCONF." >> $RECOVERFILE else - echo "\tcp /mnt${SAVEDIR}/fp.conf /mnt$FPCONF" >> $RECOVERFILE + echo "\tcp /mnt${SAVEDIR}/$DRVCONF /mnt$KDRVCONF" >> $RECOVERFILE fi - if [ $1 -eq 1 ]; then + if [ $1 -ne 0 ]; then echo "\tcp /mnt${SAVEDIR}/vfstab /mnt$VFSTAB" >> $RECOVERFILE echo "repository /mnt/etc/svc/repository.db" > $SVCCFG_RECOVERY @@ -139,7 +154,7 @@ fi fi - rootdisk=`mount | grep "/ on " | cut -f 3 -d " "` + rootdisk=`$MOUNT | $GREP "/ on " | cut -f 3 -d " "` echo "\tumount /mnt\n\treboot\n\n${rootdisk} \c" >> $RECOVERFILE gettext "was your root device,\nbut it could be named differently after you boot net.\n" >> $RECOVERFILE } @@ -147,53 +162,101 @@ # # Arrange for /etc/vfstab and dump configuration to be updated # during the next reboot. If the cmd is "enable" or "disable", copy -# $TMPFPCONF to $FPCONF. +# $TMPDRVCONF to $KDRVCONF. # # Returns 0 on success, 1 on failure. # update_sysfiles() { + gettext "WARNING: This operation will require a reboot.\nDo you want to continue ? [y/n] (default: y) " read response if [ "x$response" != x -a "x$response" != xy -a \ "x$response" != xY ]; then - rm -f $TMPFPCONF - return 0 + for d in $DRVLIST; do + TMPDRVCONF=/var/run/tmp.$d.conf.$$ + rm -f $TMPDRVCONF > /dev/null 2>&1 + done; + return 0; fi - need_bootscript=1 + need_bootscript="" + if [ "x$cmd" = xenable -o "x$cmd" = xdisable ]; then - cp $FPCONF $SAVEDIR - cp $TMPFPCONF $FPCONF - rm -f $TMPFPCONF + + for d in $DRVLIST; do + DRVCONF=$d.conf + KDRVCONF=/kernel/drv/$d.conf + TMPDRVCONF=/var/run/tmp.$d.conf.$$ + + cp $KDRVCONF $SAVEDIR + cp $TMPDRVCONF $KDRVCONF + rm -f $TMPDRVCONF > /dev/null 2>&1 + + # + # there is no need to update the system files in the following + # cases: + # - we are enabling mpxio and the system has no configured + # disks accessible by phci paths. + # - we are disabling mpxio and the system has no configured + # disks accessible by vhci paths. + # + + build_parent_list $d; + if [ "x$CLIENT_TYPE_PHCI" = "x" ]; then + continue; + fi - # - # there is no need to update the system files in the following - # cases: - # - we are enabling mpxio and the system has no configured - # disks accessible by phci paths. - # - we are disabling mpxio and the system has no configured - # disks accessible by vhci paths. - # - if [ "x$cmd" = xenable ]; then - ls -l /dev/dsk/*s2 2> /dev/null | \ - egrep -s $CLIENT_TYPE_PHCI - else - ls -l /dev/dsk/*s2 2> /dev/null | \ - egrep -s $CLIENT_TYPE_VHCI - fi + if [ "x$cmd" = "xenable" ]; then + ls -l /dev/dsk/*s2 2> /dev/null | \ + $EGREP -s "$CLIENT_TYPE_PHCI" + else + ls -l /dev/dsk/*s2 2> /dev/null | \ + $EGREP -s "$CLIENT_TYPE_VHCI" + fi + + if [ $? -ne 0 ]; then + need_bootscript="$need_bootscript $d" + fi + done + fi + + # if we're an x86/x64 machine and our bootpath is on fibrechannel + # then we cannot disable mpxio for that controller. Yet..... + # This code block is an ugly hack and when we either get full-time + # mpxio for all devices, or devfsadm gets re-written then we can + # remove it. For now, though, we have to see the beauty in ugly. - if [ $? -ne 0 ]; then - need_bootscript=0 + if [ "x$MACH" = "xi386" ]; then + BOOTPATH=`/usr/sbin/eeprom bootpath | $AWK -F"=" '{print $2}'` + FPBOOT=`echo "$BOOTPATH" | $GREP "/fp@"` + if [ ! -z "$FPBOOT" ]; then + NEWP=`/usr/bin/dirname $BOOTPATH` + NNEWP=`/usr/bin/dirname $NEWP` + + # check that we haven't already got this entry + # in /kernel/drv/fp.conf. + + EXISTP=`$GREP "^name.*$NNEWP" /kernel/drv/fp.conf` +# if [ -z "$EXISTP" ]; then + if [ $? != 0 ]; then + cat >>/kernel/drv/fp.conf << EOF +# This entry must be the last one in the fp.conf file +# to ensure that the boot path mpxio setting is not +# accidentally overridden +name="fp" parent="$NNEWP" port=0 mpxio-disable="no"; +EOF + fi fi fi - if [ $need_bootscript -eq 1 ]; then + if [ -z "$need_bootscript" ]; then + need_bootscript=0 if [ "x$MACH" = "xi386" -a "x$new_bootpath" != "x" ]; then #only update bootpath for x86. cp $BOOTENV_FILE $SAVEDIR - eeprom bootpath=$new_bootpath + /usr/sbin/eeprom bootpath=$new_bootpath fi # # Enable the mpxio-upgrade service, but don't run it now. @@ -209,12 +272,16 @@ build_recover $need_bootscript + if [ "x$MACH" = "xi386" ]; then + $BOOTADM update-archive + fi + gettext "The changes will come into effect after rebooting the system.\nReboot the system now ? [y/n] (default: y) " read response if [ "x$response" = x -o "x$response" = xy -o \ "x$response" = xY ]; then - reboot + /usr/sbin/reboot fi return 0 @@ -224,6 +291,11 @@ # Enable or disable mpxio as specified by the cmd. # Returns 0 on success, 1 on failure. # +# Args: $cmd = {enable | disable} +# $d = {fp | mpt} +# +# the global variable $DRVLIST is used +# configure_mpxio() { mpxiodisableno='mpxio-disable[ ]*=[ ]*"no"[ ]*;' @@ -232,51 +304,46 @@ if [ "x$cmd" = xenable ]; then mpxiodisable_cur_entry=$mpxiodisableyes propval=no - msg=`gettext "STMS already enabled."` + msg=`gettext "STMS already enabled"` else mpxiodisable_cur_entry=$mpxiodisableno propval=yes - msg=`gettext "STMS already disabled."` + msg=`gettext "STMS already disabled"` fi - if delete_mpxio_disable_entries $FPCONF $TMPFPCONF $TMPFPCONF_MPXIO_ENTRY; then - if [ -s $TMPFPCONF_MPXIO_ENTRY ]; then - # fp.conf does have mpxiodisable entries - egrep -s "$mpxiodisable_cur_entry" $TMPFPCONF_MPXIO_ENTRY + DRVCONF=$d.conf + KDRVCONF=/kernel/drv/$d.conf + TMPDRVCONF=/var/run/tmp.$d.conf.$$ + TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$; + + echo "Checking mpxio status for driver $d" + if delete_mpxio_disable_entries $KDRVCONF $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY; then + + if [ -s $TMPDRVCONF_MPXIO_ENTRY ]; then + # $DRVCONF does have mpxiodisable entries + $EGREP -s "$mpxiodisable_cur_entry" $TMPDRVCONF_MPXIO_ENTRY if [ $? -ne 0 ]; then # if all mpxiodisable entries are no/yes for # enable/disable mpxio, notify the user - rm -f $TMPFPCONF $TMPFPCONF_MPXIO_ENTRY - echo "$msg" - return 0 + rm -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1 + continue; + else + reboot_needed=`$EXPR $reboot_needed + 1` fi - # If mpxiodisable entries does not exist, always continue update + + # If mpxiodisable entries do not exist, always continue update fi else - rm -f $TMPFPCONF $TMPFPCONF_MPXIO_ENTRY - gettext "failed to update " 1>&2 - echo "$FPCONF." 1>&2 + rm -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1 + gettext "failed to update " 1>&2 + echo "$KDRVCONF." 1>&2 gettext "No changes were made to your STMS configuration.\n" 1>&2 return 1 fi - rm $TMPFPCONF_MPXIO_ENTRY - echo "mpxio-disable=\"${propval}\";" >> $TMPFPCONF + rm $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1 + echo "mpxio-disable=\"${propval}\";" >> $TMPDRVCONF - #Need to update bootpath on x86 if boot system from FC disk - #Only update bootpath before reboot when mpxio is enabled - #If mpxio is disabled currently, will update bootpath in mpxio-upgrade - if [ "x$MACH" = "xi386" -a "x$cmd" = "xdisable" ]; then - get_newbootpath_for_stmsdev - if [ $? -ne 0 ]; then - rm -f $TMPFPCONF - gettext "failed to update bootpath.\n" 1>&2 - gettext "No changes were made to your STMS configuration.\n" 1>&2 - return 1 - fi - fi - update_sysfiles - return $? } setcmd() @@ -289,23 +356,26 @@ fi } - +# #Need to update bootpath on x86 if boot system from FC disk #Only update bootpath here when mpxio is enabled #If mpxio is disabled currently, will update bootpath in mpxio-upgrade +# + get_newbootpath_for_stmsdev() { if [ "x$cmd" = "xenable" ]; then return 0 fi - cur_bootpath=`eeprom bootpath | sed 's/bootpath=[ ]*//g' | sed 's/[ ]*$//'` + cur_bootpath=`eeprom bootpath | \ + sed 's/bootpath=[ ]*//g' | sed 's/[ ]*$//'` if [ "x$cur_bootpath" = "x" ]; then gettext "failed to get bootpath by eeprom\n" 1>&2 return 1 fi #only update bootpath for STMS path - echo $cur_bootpath|grep $CLIENT_TYPE_VHCI > /dev/null 2>&1 + echo $cur_bootpath|$EGREP $CLIENT_TYPE_VHCI > /dev/null 2>&1 if [ $? -eq 1 ]; then return 0 fi @@ -315,13 +385,80 @@ new_bootpath="" return 1 fi + + # we replace "sd" with "disk" if we need to work on the eeprom + # bootpath setting, since fibre-channel devices will report as + # being attached via "disk" and not "sd". One day we'll have a + # truly unified and architecture-independent view of the device + # tree, and this block will be redundant + fp_bootpath=`echo $new_bootpath|grep fp.*sd` + if [ "x$fp_bootpath" != "x" ]; then + new_bootpath=`echo $fp_bootpath |sed -e"s,sd,disk,g"` + fi +} + +# +# Emit a warning message to the user that by default we +# operate on all multipath-capable controllers that are +# attached to the system, and that if they want to operate +# on only a specific controller type (fp|mpt|....) then +# they need to re-invoke stmsboot with "-D $driver" in +# their argument list +# + +emit_driver_warning_msg() { + + # for each driver that we support, grab the list + # of controllers attached to the system. + + echo "WARNING: stmsboot operates on each supported multipath-capable controller" + echo " detected in a host. In your system, these controllers are" + + for WARNDRV in fp mpt; do + $GREP "$WARNDRV.$" /etc/path_to_inst | $AWK -F"\"" '{print "/devices"$2}' + done; + + echo "" + echo "If you do NOT wish to operate on these controllers, please quit stmsboot" + echo "and re-invoke with -D { fp | mpt } to specify which controllers you wish" + echo "to modify your multipathing configuration for." + + echo + gettext "Do you wish to continue? [y/n] (default: y) " 1>&2 + read response + + if [ "x$response" -ne "xY" -a "x$response" -ne "xy" ]; then + exit + fi + +} + +# Function to setup the CLIENT_TYPE_PHCI string based on +# the list of drivers that we're operating on. The variable +# depends upon the pathname of the parent node in the +# device tree, which can be different on x86/x64 and sparc. +# Oh, if we only had OBP on x86/x64! +build_parent_list() { + + # stmsboot_util -n provides us with the name of the + # node containing "fp" or "sas-$d", and helpfully + # appends "/[ssd|sd]@" as appropriate + + d=$1; + + TLIST=`$STMSBOOTUTIL -D $d -n` + if [ "x$TLIST" != "x" ]; then + CLIENT_TYPE_PHCI="$TLIST|$CLIENT_TYPE_PHCI" + else + CLIENT_TYPE_PHCI="$CLIENT_TYPE_PHCI" + fi } cmd=none # process options -while getopts eduLl: c +while getopts D:geduLl: c do case $c in e) setcmd enable;; @@ -330,6 +467,8 @@ L) setcmd listall;; l) setcmd list controller=$OPTARG;; + D) DRV=$OPTARG;; + g) GUID="-g";; \?) echo "$USAGE" 1>&2 exit 2;; esac @@ -340,8 +479,16 @@ exit 2 fi -set `id` -if [ "$1" != "uid=0(root)" ]; then +if [ "x$DRV" = "x" ]; then + DRVLIST="fp mpt" +else + DRVLIST=$DRV +fi + + +STMSPRIVS=`/usr/bin/ppriv $$ | $EGREP "E:.*all|E:.*sys_devices"` +USERID=`id` +if [ "$USERID" != "uid=0(root) gid=0(root)" ] -o [ "x$STMSPRIVS" == "x" ]; then gettext "You must be super-user to run this script.\n" 1>&2 exit 1 fi @@ -353,11 +500,30 @@ exit 1 fi -svcprop -q $STMSINSTANCE +# If the old sun4u-specific SMF method is found, remove it +/usr/sbin/svccfg -s "platform/sun4u/mpxio-upgrade:default" < /dev/null > /dev/null 2>&1 +if [ $? -ne 0 ]; then + /usr/sbin/svccfg delete "platform/sun4u/mpxio-upgrade:default" > /dev/null 2>&1 +fi + +# now import the new service, if necessary +/usr/bin/svcprop -q $STMSINSTANCE < /dev/null > /dev/null 2>&1 if [ $? -ne 0 ]; then - fmt=`gettext "Can't find %s service"` - printf "$fmt\n" "$STMSINSTANCE" 1>&2 - exit 1 + if [ -f /var/svc/manifest/system/device/mpxio-upgrade.xml ]; then + /usr/sbin/svccfg import /var/svc/manifest/system/device/mpxio-upgrade.xml + if [ $? -ne 0 ]; then + fmt=`gettext "Unable to import %s service"` + printf "$fmt\n" "$STMSINSTANCE" 1>&2 + exit 1 + else + fmt=`gettext "Service %s imported successfully, continuing"` + printf "$fmt\n" "$STMSINSTANCE" 1>&2 + fi + else + fmt=`gettext "Service %s does not exist on this host"` + printf "$fmt\n" "$STMSINSTANCE" 1>&2 + exit 1 + fi fi if [ "x$cmd" = xenable -o "x$cmd" = xdisable -o "x$cmd" = xupdate ]; then @@ -365,7 +531,7 @@ # The bootup script doesn't work on cache-only-clients as the script # is executed before the plumbing for cachefs mounting of root is done. # - if mount -v | egrep -s " on / type (nfs|cachefs) "; then + if $MOUNT -v | $EGREP -s " on / type (nfs|cachefs) "; then gettext "This command option is not supported on systems with nfs or cachefs mounted root filesystem.\n" 1>&2 exit 1 fi @@ -375,11 +541,18 @@ # keep a copy of the last saved files, useful for manual # recovery in case of a problem. # - if [ "x$MACH" = "xsparc" ]; then - backup_lastsaved $FPCONF $VFSTAB - else - backup_lastsaved $FPCONF $VFSTAB $BOOTENV_FILE - fi + for d in $DRVLIST; do + DRVCONF=$d.conf + KDRVCONF=/kernel/drv/$d.conf + TMPDRVCONF=/var/run/tmp.$d.conf.$$ + TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$; + + if [ "x$MACH" = "xsparc" ]; then + backup_lastsaved $KDRVCONF $VFSTAB + else + backup_lastsaved $KDRVCONF $VFSTAB $BOOTENV_FILE + fi + done else mkdir $SAVEDIR fi @@ -387,7 +560,38 @@ fi if [ "x$cmd" = xenable -o "x$cmd" = xdisable ]; then - configure_mpxio $cmd + + msgneeded=`echo "$DRVLIST" |grep " "` + if [ -n "$msgneeded" ]; then + emit_driver_warning_msg + fi + for d in $DRVLIST; do + configure_mpxio $cmd $d + done + + if [ $reboot_needed -ne 0 ]; then + + # Need to update bootpath on x86 if our boot device is + # now accessed through mpxio. + # Only update bootpath before reboot when mpxio is enabled + # If mpxio is currently disabled, we will update bootpath + # on reboot in the mpxio-upgrade service + + if [ "x$MACH" = "xi386" -a "x$cmd" = "xdisable" ]; then + get_newbootpath_for_stmsdev + if [ $? -ne 0 ]; then + rm -f $TMPDRVCONF > /dev/null 2>&1 + gettext "failed to update bootpath.\n" 1>&2 + gettext "No changes were made to your STMS configuration.\n" 1>&2 + return 1 + fi + fi + update_sysfiles + else + echo "STMS is already ${cmd}d. No changes or reboots needed" + fi + + elif [ "x$cmd" = xupdate ]; then if [ "x$MACH" = "xi386" ]; then # In this case we always change the bootpath to phci-based @@ -400,10 +604,11 @@ fi fi update_sysfiles + elif [ "x$cmd" = xlist ]; then - $STMSBOOTUTIL -l $controller + $STMSBOOTUTIL $GUID -l $controller else - $STMSBOOTUTIL -L + $STMSBOOTUTIL $GUID -L fi exit $?
--- a/usr/src/cmd/stmsboot/stmsboot_util.c Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/cmd/stmsboot/stmsboot_util.c Thu Apr 12 18:26:33 2007 -0700 @@ -58,16 +58,16 @@ #define DISK_NODE_NAME "ssd" #define DISK_DRV_NAME "ssd" #define SLASH_DISK_AT "/ssd@" -#define DISK_AT_G "ssd@g" #else /* sparc */ #define DISK_NODE_NAME "disk" #define DISK_DRV_NAME "sd" #define SLASH_DISK_AT "/disk@" -#define DISK_AT_G "disk@g" #endif +#define DISK_AT_G "disk@g" #define SLASH_FP_AT "/fp@" #define SLASH_SCSI_VHCI "/scsi_vhci" +#define SLASH_SD_AT "/sd@" #define DEV_DSK "/dev/dsk/" #define DEV_RDSK "/dev/rdsk/" #define SYS_FILENAME_LEN 256 @@ -82,6 +82,14 @@ /* fcp driver publishes this property */ #define NODE_WWN_PROP "node-wwn" +/* + * For SAS, we look for "sas-$drivername", eg sas-mpt, but + * we strncat the driver name later once we've parsed the + * args passed in from the shell. + */ +#define SASPROP "sas-" + + typedef enum { CLIENT_TYPE_UNKNOWN, CLIENT_TYPE_PHCI, @@ -102,12 +110,20 @@ static char *map_vhciname = ""; static char *stmsboot = "stmsboot"; +char *drvname = (char *)NULL; /* "fp" or "mpt" or ... */ +/* "node-wwn" if drvname=fp, or "sas-$drivername" otherwise */ +char *drvprop = (char *)NULL; +static int parent = 0; /* for "-n" usage */ + static int make_temp(char *, char *, char *, size_t); static void commit_change(char *, char *, char *, int); static int map_devname(char *, char *, size_t, int); static int update_vfstab(char *, char *); static int list_mappings(int, int); static int canopen(char *); +static client_type_t client_by_props(char *path); +static void list_nodes(char *drivername); + static void logerr(char *, ...); static void logdmsg(char *, ...); static void *s_malloc(const size_t); @@ -152,9 +168,17 @@ * if devname is vhci based name and open-able, get the first * onlined phci based name without /devices prefix. * Used in stmsboot to update the phci based bootpath. + * -D drvname + * if supplied, indicates that we're going to operate on + * devices attached to this driver + * -n + * if supplied, returns name of the node containing "fp" or + * "sas-$driver", appends "sd@" or "ssd@" or "disk@". Can only + * be used if -D drv is specified as well */ (void) fprintf(stderr, gettext("usage: %s -u | -m devname | " - "-M devname | -l controller | -L | -p devname\n"), progname); + "-M devname | -l controller | -L | \n" + "\t\t-p devname | -D { fp | mpt } | -n\n"), progname); exit(2); } @@ -172,7 +196,7 @@ /*NOTREACHED*/ } - while ((opt = getopt(argc, argv, "udm:M:Ll:gp:")) != EOF) { + while ((opt = getopt(argc, argv, "udm:M:Ll:gp:D:n")) != EOF) { switch (opt) { case 'u': patch_vfstab = 1; @@ -216,8 +240,8 @@ * to GUID mappings. */ list_guid_mappings = 1; - n++; break; + case 'p': /* * map openable vhci based name to phci base name @@ -226,15 +250,48 @@ n++; break; + case 'D': + /* + * Grab the driver name we need to look for. Each + * time we add support for a new SAS or FC driver + * to this utility, make sure that its driver name + * is checked here. + */ + drvname = s_malloc(sizeof (optarg) + 1); + drvname = s_strdup(optarg); + if (strcmp(drvname, "fp") == 0) { + drvprop = s_malloc(sizeof (NODE_WWN_PROP)); + (void) snprintf(drvprop, sizeof (NODE_WWN_PROP), + NODE_WWN_PROP); + } else if (strcmp(drvname, "mpt") == 0) { + drvprop = s_malloc(sizeof (SASPROP) + + sizeof (drvname) + 1); + (void) snprintf(drvprop, sizeof (SASPROP) + + sizeof (drvname), "%s%s", + SASPROP, drvname); + } else { + logerr(gettext("Driver %s is not supported\n"), + drvname); + clean_exit(1); + } + + break; + + case 'n': + ++parent; + n++; + break; + default: usage(argv[0]); /*NOTREACHED*/ } } - if (n != 1) + if (n != 1) { usage(argv[0]); /*NOTREACHED*/ + } } int @@ -286,6 +343,16 @@ clean_exit(1); } + if (parent > 0) { + if (strcmp(drvname, "") == 0) { + usage(argv[0]); + clean_exit(1); + } else { + list_nodes(drvname); + clean_exit(0); + } + } + /* create a directory where a copy of the system files are saved */ if (patch_vfstab) { if (mkdirp(SAVE_DIR, 0755) != 0 && errno != EEXIST) { @@ -383,7 +450,7 @@ * component. * guid caller supplied buffer where the GUID will be placed on return * guid_len length of the caller supplied guid buffer. - * no_dealy_flag if set open the device with O_NDELAY + * no_delay_flag if set open the device with O_NDELAY * node di_node corresponding to physpath if already available, * otherwise pass DI_NODE_NIL. * @@ -436,12 +503,21 @@ devid_free_guid(i_guid); rv = 0; goto out; - } else + } else { logdmsg("get_guid: devid_to_guid() failed\n"); + logdmsg("Unable to get a GUID for device " + "%s\n", physpath_raw); + } + } else logdmsg("get_guid: devid_get() failed: %s\n", strerror(errno)); - /* fallback to node name as the guid as this is what fcp driver does */ + /* + * Unless we're looking at an fp-attached device, we now + * fallback to node name as the guid as this is what the + * fcp driver does. A sas-attached device will have the + * client-guid property set. + */ if (node == DI_NODE_NIL) { if ((node = di_init(physpath, DINFOCPYALL | DINFOFORCE)) == DI_NODE_NIL) { @@ -452,6 +528,16 @@ snapshot_taken = 1; } + /* non-fp fallout */ + if (strstr(physpath, "fp") == (char *)NULL) { + if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, + "client-guid", &guid) < 0) { + logdmsg("get_guid: non-fp-attached device, " + "bailing out\n"); + goto out; + } + } + if ((n = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, NODE_WWN_PROP, &wwnp)) == -1) { logdmsg("get_guid: di_prop_lookup_bytes() failed to lookup " @@ -482,60 +568,223 @@ * Given client_name return whether it is a phci or vhci based name. * client_name is /devices name of a client without the /devices prefix. * - * client_name Return value + * client_name Return value * on sparc: - * .../fp@xxx/ssd@yyy CLIENT_TYPE_PHCI - * .../scsi_vhci/ssd@yyy CLIENT_TYPE_VHCI - * other CLIENT_TYPE_UNKNOWN + * .../fp@xxx/ssd@yyy CLIENT_TYPE_PHCI (fc) + * .../LSILogic,sas@xxx/sd@yyy CLIENT_TYPE_PHCI (sas) + * .../scsi_vhci/ssd@yyy CLIENT_TYPE_VHCI (fc) + * .../scsi_vhci/disk@yyy CLIENT_TYPE_VHCI (sas) + * other CLIENT_TYPE_UNKNOWN * on x86: - * .../fp@xxx/disk@yyy CLIENT_TYPE_PHCI - * .../scsi_vhci/disk@yyy CLIENT_TYPE_VHCI - * other CLIENT_TYPE_UNKNOWN + * .../fp@xxx/disk@yyy CLIENT_TYPE_PHCI (fc) + * .../pci1000,????@xxx/sd@yyy CLIENT_TYPE_PHCI (sas) + * .../scsi_vhci/disk@yyy CLIENT_TYPE_VHCI + * other CLIENT_TYPE_UNKNOWN */ static client_type_t client_name_type(char *client_name) { client_type_t client_type = CLIENT_TYPE_UNKNOWN; - char *p1, *p2; + char *p1; + char *client_path; + + client_path = s_strdup(client_name); + logdmsg("client_name_type: client is %s\n", client_path); if (*client_name != '/') return (CLIENT_TYPE_UNKNOWN); if ((p1 = strrchr(client_name, '/')) == NULL || - strncmp(p1, SLASH_DISK_AT, sizeof (SLASH_DISK_AT) - 1) != 0) + ((strncmp(p1, "/ssd@", sizeof ("/ssd@") - 1) != 0) && + (strncmp(p1, "/sd@", sizeof ("/sd@") - 1) != 0) && + (strncmp(p1, "/disk@", sizeof ("/disk@") - 1) != 0))) { + logdmsg("client_name_type: p1 = %s\n", p1); return (CLIENT_TYPE_UNKNOWN); + } *p1 = '\0'; - if ((p2 = strrchr(client_name, '/')) != NULL) { - if (strncmp(p2, SLASH_FP_AT, sizeof (SLASH_FP_AT) - 1) == 0) - client_type = CLIENT_TYPE_PHCI; - else if (strncmp(p2, SLASH_SCSI_VHCI, - sizeof (SLASH_SCSI_VHCI) - 1) == 0) - client_type = CLIENT_TYPE_VHCI; - } + /* + * Courtesy of the if (..) block above, we know that any + * device path we have now is either PHCI or VHCI + */ + client_type = client_by_props(client_path); + + logdmsg("client_name_type: client_type = %d\n", client_type); *p1 = '/'; return (client_type); } /* + * client_by_props() is called to determine what the client type + * is, based on properties in the device tree: + * + * drivername property type + * ------------------------------------- + * fp node-wwn CLIENT_TYPE_PHCI + * mpt sas-mpt CLIENT_TYPE_PHCI + * mpt client-guid CLIENT_TYPE_PHCI (corner case) + * + * Normally, the "client-guid" property only shows up for a node + * if we've enumerated that node under scsi_vhci. During testing + * of this function, one particular corner case was found which + * requires an exception handler. + */ + +static client_type_t +client_by_props(char *path) { + + di_node_t clientnode = DI_NODE_NIL; + di_node_t parentnode = DI_NODE_NIL; + unsigned int rval = CLIENT_TYPE_UNKNOWN; + uchar_t *byteprop[32]; + char *charprop = NULL; + char *physpath; + char *parentpath; + + physpath = s_malloc(MAXPATHLEN); + bzero(physpath, MAXPATHLEN); + + physpath = s_strdup(path); + + logdmsg("client_by_props: physpath = (%s)\n", physpath); + + /* easy short-circuits */ + if (strstr(physpath, "scsi_vhci") != (char *)NULL) { + logdmsg("client_by_props: found " + "'scsi_vhci' on path (%s)\n", physpath); + rval = CLIENT_TYPE_VHCI; + goto out; + } else if ((strstr(physpath, "ide") != (char *)NULL) || + (strstr(physpath, "storage") != (char *)NULL)) { + logdmsg("client_by_props: ignoring this device\n"); + goto out; + } + + parentpath = s_malloc(MAXPATHLEN); + bzero(parentpath, MAXPATHLEN); + + (void) strncpy(parentpath, physpath, strlen(physpath) - + strlen(strrchr(physpath, '/'))); + + if ((parentnode = di_init(parentpath, DINFOCPYALL | + DINFOFORCE)) == DI_NODE_NIL) { + logdmsg("client_by_props: unable to di_init(%s)\n", + parentpath); + goto out; + } + + if (strstr(physpath, "fp") != (char *)NULL) { + if (drvprop == (char *)NULL) { + drvprop = s_malloc(strlen(NODE_WWN_PROP) + 1); + } + logdmsg("NODE_WWN_PROP\n"); + (void) snprintf(drvprop, strlen(NODE_WWN_PROP) + 1, + NODE_WWN_PROP); + } else { + if (drvname == (char *)NULL) { + drvname = di_driver_name(parentnode); + logdmsg("client_by_props: drvname = %s\n", drvname); + } + + if (drvprop == (char *)NULL) { + drvprop = s_malloc(sizeof (SASPROP) + + sizeof (drvname) + 1); + } + (void) snprintf(drvprop, sizeof (SASPROP) + + sizeof (drvname), "%s%s", SASPROP, drvname); + + logdmsg("parentpath: %s\nphyspath: %s\n" + "length %d, strrchr: %d\n", + parentpath, physpath, strlen(physpath), + strlen(strrchr(physpath, '/'))); + } + + logdmsg("client_by_props: searching for property '%s'\n", drvprop); + + if ((clientnode = di_init(physpath, DINFOCPYALL | DINFOFORCE)) == + DI_NODE_NIL) { + logdmsg("client_by_props: unable to di_init(%s)\n", + physpath); + + /* + * On x86/x64 systems, we won't be able to di_init() the + * node we want in the device tree, however the parent + * node will still have 'mpxio-disable' set, so we can + * check for that property and make our decision on type + */ + + if (di_prop_lookup_strings(DDI_DEV_T_ANY, parentnode, + "mpxio-disable", &charprop) > -1) { + rval = CLIENT_TYPE_PHCI; + di_fini(parentnode); + logdmsg("client_by_props: device %s is PHCI\n", + physpath); + } + goto out; + } + + if (di_prop_lookup_bytes(DDI_DEV_T_ANY, + clientnode, drvprop, byteprop) > -1) { + logdmsg("client_by_props: found prop %s on " + "path %s\n", drvprop, physpath); + rval = CLIENT_TYPE_PHCI; + } else if (di_prop_lookup_strings(DDI_DEV_T_ANY, + clientnode, "client-guid", &charprop) > -1) { + /* + * A corner case was seen during testing where + * scsi_vhci was loaded, but not all applicable + * devices were enumerated under it. That left + * the phci mapping along with the "client-guid" + * property. + */ + logdmsg("client_by_props: weird... \n"); + rval = CLIENT_TYPE_PHCI; + } else { + logdmsg("client_by_props: unable to find " + "property 'client-guid', 'mpxio-disable' " + "or '%s' anywhere on path (%s)\n", + drvprop, physpath); + logdmsg("client_by_props: this node is unknown\n"); + } + + di_fini(parentnode); + di_fini(clientnode); +out: + free(physpath); + return (rval); +} + + +/* * Map phci based client name to vhci based client name. * * phci_name * phci based client /devices name without the /devices prefix and * minor name component. * ex: + * + * (FC) * for sparc: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0 * for x86: /pci@8,600000/SUNW,qlc@4/fp@0,0/disk@w2100002037cd9f72,0 * + * (SAS) + * for sparc: /pci@0,2/LSILogic,sas@1/disk@6,0 + * for x86: /pci1000,3060@3/sd@0,0 + * * vhci_name * Caller supplied buffer where vhci /devices name will be placed on * return (without the /devices prefix and minor name component). * ex: + * + * (FC) * for sparc: /scsi_vhci/ssd@g2000002037cd9f72 * for x86: /scsi_vhci/disk@g2000002037cd9f72 * + * (SAS) + * both: /scsi_vhci/disk@g600a0b8000254d3e00000284453ed8ac + * * vhci_name_len * Length of the caller supplied vhci_name buffer. * @@ -545,7 +794,7 @@ phci_to_vhci(char *phci_name, char *vhci_name, size_t vhci_name_len) { sv_iocdata_t ioc; - char *slash; + char *slash, *at; char vhci_name_buf[MAXPATHLEN]; char phci_name_buf[MAXPATHLEN]; char addr_buf[MAXNAMELEN]; @@ -556,7 +805,9 @@ if (client_name_type(phci_name_buf) != CLIENT_TYPE_PHCI || (slash = strrchr(phci_name_buf, '/')) == NULL || - strncmp(slash, SLASH_DISK_AT, sizeof (SLASH_DISK_AT) - 1) != 0) { + ((strncmp(slash, "/ssd@", sizeof ("/ssd@") - 1) != 0) && + (strncmp(slash, "/sd@", sizeof ("/sd@") - 1) != 0) && + (strncmp(slash, "/disk@", sizeof ("/disk@") - 1) != 0))) { logdmsg("phci_to_vhci: %s is not of CLIENT_TYPE_PHCI\n", phci_name); return (-1); @@ -568,7 +819,9 @@ } *slash = '\0'; - s_strlcpy(addr_buf, slash + sizeof (SLASH_DISK_AT) - 1, MAXNAMELEN); + + at = strchr(slash + 1, '@'); + s_strlcpy(addr_buf, at + 1, MAXNAMELEN); bzero(&ioc, sizeof (sv_iocdata_t)); ioc.client = vhci_name_buf; @@ -614,10 +867,10 @@ static int vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len) { - di_node_t node, parent; + di_node_t node = DI_NODE_NIL; char *vhci_guid, *devfspath; char phci_guid[MAXPATHLEN]; - char *parent_name, *node_name; + char *node_name; logdmsg("vhci_to_phci: client = %s\n", vhci_name); @@ -627,6 +880,7 @@ return (-1); } + if ((vhci_guid = strrchr(vhci_name, '@')) == NULL || *(++vhci_guid) != 'g') { logerr(gettext("couldn't get guid from %s\n"), vhci_name); @@ -651,14 +905,27 @@ logdmsg("vhci_to_phci: done taking devinfo snapshot\n"); } - for (node = di_drv_first_node(DISK_DRV_NAME, devinfo_root); + + /* + * When we finally get a unified "sd" driver for all + * architectures that Solaris runs on, we can remove this + * first loop around for "ssd" + */ + for (node = di_drv_first_node("ssd", devinfo_root); node != DI_NODE_NIL; node = di_drv_next_node(node)) { - if ((node_name = di_node_name(node)) == NULL || - strcmp(node_name, DISK_NODE_NAME) != 0 || - (parent = di_parent_node(node)) == DI_NODE_NIL || - (parent_name = di_node_name(parent)) == NULL || - strcmp(parent_name, "fp") != 0 || - (devfspath = di_devfs_path(node)) == NULL) + + if ((node_name = di_node_name(node)) == NULL) + continue; + + if ((strcmp(node_name, "disk") != 0) && + (strcmp(node_name, "sd") != 0) && + (strcmp(node_name, "ssd") != 0)) + continue; + + if (di_parent_node(node) == DI_NODE_NIL) + continue; + + if ((devfspath = di_devfs_path(node)) == NULL) continue; /* @@ -666,8 +933,46 @@ * standby paths of T3. So we'll find the preferred paths. */ if (get_guid(devfspath, phci_guid, - sizeof (phci_guid), 0, node) == 0 && - strcmp(phci_guid, vhci_guid) == 0) { + sizeof (phci_guid), 0, node) != 0) + continue; + + if (strcmp(phci_guid, vhci_guid) == 0) { + s_strlcpy(phci_name, devfspath, phci_name_len); + di_devfs_path_free(devfspath); + logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name, + phci_name); + return (0); + } + + di_devfs_path_free(devfspath); + } + + for (node = di_drv_first_node("sd", devinfo_root); + node != DI_NODE_NIL; node = di_drv_next_node(node)) { + + if ((node_name = di_node_name(node)) == NULL) + continue; + + if ((strcmp(node_name, "disk") != 0) && + (strcmp(node_name, "sd") != 0) && + (strcmp(node_name, "ssd") != 0)) + continue; + + if (di_parent_node(node) == DI_NODE_NIL) + continue; + + if ((devfspath = di_devfs_path(node)) == NULL) + continue; + + /* + * Don't set no_delay_flag to have get_guid() fail on + * standby paths of T3. So we'll find the preferred paths. + */ + if (get_guid(devfspath, phci_guid, + sizeof (phci_guid), 0, node) != 0) + continue; + + if (strcmp(phci_guid, vhci_guid) == 0) { s_strlcpy(phci_name, devfspath, phci_name_len); di_devfs_path_free(devfspath); logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name, @@ -764,6 +1069,15 @@ node_name++; *at = '\0'; + logdmsg("vhci_to_phci_by_ioctl: node_name is %s\n", node_name); +#ifndef sparc + /* + * We need to use a libdevinfo call to get this info + * in an architecturally-neutral fashion. Phase-II for sure! + */ + node_name = "sd"; +#endif + /* * return the first online paths as non-online paths may * not be accessible in the target environment. @@ -812,13 +1126,18 @@ int type; int rv; - if ((type = client_name_type(physname)) == CLIENT_TYPE_VHCI) + type = client_name_type(physname); + logdmsg("map_physname: type (%d) physname = %s\n", + type, physname); + + if (type == CLIENT_TYPE_VHCI) rv = vhci_to_phci(physname, new_physname, len); else if (type == CLIENT_TYPE_PHCI) rv = phci_to_vhci(physname, new_physname, len); else rv = -1; + logdmsg("map_physname: returning %d\n", rv); return (rv); } @@ -1011,10 +1330,14 @@ char minor[MAXNAMELEN]; char new_physname[MAXPATHLEN]; - if (get_physname_minor(devname, physname, sizeof (physname), - minor, sizeof (minor)) == 0 && - canopen(devname) == 0 && - map_physname(physname, new_physname, sizeof (new_physname)) == 0) { + logdmsg("map_devname: checking devname %s\n", devname); + if ((get_physname_minor(devname, physname, sizeof (physname), + minor, sizeof (minor)) == 0) && + (canopen(devname) == 0) && + (map_physname(physname, new_physname, + sizeof (new_physname)) == 0)) { + + logdmsg("map_devname: now looking up devlink\n"); if (devlink_flag) { if (lookup_devlink(new_physname, minor, new_devname, @@ -1027,6 +1350,7 @@ } } + logdmsg("map_devname: failed to find mapping for %s\n", devname); return (-1); } @@ -1261,8 +1585,10 @@ if (get_physname_minor(devname, physname, sizeof (physname), minor, sizeof (minor)) != 0 || - client_name_type(physname) != CLIENT_TYPE_PHCI) + client_name_type(physname) != CLIENT_TYPE_PHCI) { + logdmsg("list_mappings: continuing\n"); continue; + } /* * First try phci_to_vhci() mapping. It will work if the @@ -1306,11 +1632,16 @@ (void) printf("%s\t\t%s\n", devname, new_devname); } else { /* extract guid part */ - if ((p1 = strstr(new_physname, DISK_AT_G)) == NULL) { + /* we should be using a getguid() call instead */ + if ((p1 = strstr(new_physname, "@")) + == NULL) { logdmsg("invalid vhci: %s\n", new_physname); continue; } - p1 += sizeof (DISK_AT_G) - 1; + + logdmsg("\tp1 = %s\n", p1); + + p1 += 2; /* "@" + [nwg] */ if ((p2 = strrchr(p1, ':')) != NULL) *p2 = '\0'; @@ -1342,10 +1673,107 @@ if ((fd = open(filename, O_RDONLY)) == -1) return (0); + logdmsg("canopen: was able to open %s\n", filename); (void) close(fd); return (1); } + +/* + * This function traverses the device tree looking for nodes + * which have "drivername" as a property. We return a list of + * these nodes, with SLASH_DISK_AT appended. + * Since there can be many different pci/pcie devices that all + * share the same driver but which have different pci vid/did + * combinations, we have to be smart about returning only those + * pci vid/dids which have the "sas-*" property unless the + * drivername is "fp", in which case we're searching for "node-wwn" + */ +static void +list_nodes(char *drivername) +{ + char *aliaslist; + char *mpxprop = NULL; + di_node_t devroot = DI_NODE_NIL; + di_node_t thisnode = DI_NODE_NIL; + int *intprop = NULL; + int i = 1; /* fencepost */ + + /* + * Since the "fp" driver enumerates with its own name, + * we can special-case its handling. + */ + if (strcmp(drvname, "fp") == 0) { + (void) fprintf(stdout, "fp\n"); + } else { + + if ((devroot = di_init("/", DINFOCPYALL | DINFOFORCE)) + == DI_NODE_NIL) { + logerr(gettext("list_nodes: di_init failed: " + "%s\n"), strerror(errno)); + } + + if ((thisnode = di_drv_first_node(drivername, devroot)) + != NULL) { + logdmsg("list_nodes: searching for property " + "%s\n", drvprop); + + aliaslist = s_malloc(1024 * sizeof (char)); + bzero(aliaslist, 1024); + while (thisnode != DI_NODE_NIL) { + logdmsg("devfs-name %s driver-name %s " + "node-name %s\n", + di_devfs_path(thisnode), + di_driver_name(thisnode), + di_node_name(thisnode)); + + /* We check the child node for drvprop */ + if ((di_prop_lookup_ints(DDI_DEV_T_ANY, + di_child_node(thisnode), drvprop, + &intprop) > -1) || + (((di_prop_lookup_strings(DDI_DEV_T_ANY, + thisnode, "mpxio-disable", &mpxprop) > -1) && + strcmp(di_driver_name(thisnode), + drivername)) == 0)) { + + if (strstr(aliaslist, + di_node_name(thisnode)) + == (char *)NULL) { + char *nname; + + nname = di_node_name(thisnode); + + if (i) { + (void) snprintf(aliaslist, + strlen(nname), "%s", nname); + --i; + } else { + if (strstr(aliaslist, + di_node_name(thisnode)) == + (char *)NULL) { + (void) snprintf(aliaslist, + strlen(nname) + + strlen(aliaslist), + "%s|%s", aliaslist, + nname); + } + } + } + } else { + logdmsg("unable to lookup property %s " + "for node %s. Error %d: %s\n", + drvprop, di_devfs_path(thisnode), + errno, strerror(errno)); + } + thisnode = di_drv_next_node(thisnode); + } + (void) fprintf(stdout, "%s\n", aliaslist); + } + + di_fini(devroot); + } +} + static void logerr(char *msg, ...) {
--- a/usr/src/pkgdefs/SUNWckr/Makefile Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/pkgdefs/SUNWckr/Makefile Thu Apr 12 18:26:33 2007 -0700 @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -28,7 +28,7 @@ include ../Makefile.com DATAFILES += i.etcsystem i.kcfconfbase i.manifest i.preserve i.renameold \ - i.scsivhciconf + i.scsivhciconf i.mptconf MACHDATAFILES += i.sdconf CLOBBERFILES += $(MACHDATAFILES)
--- a/usr/src/pkgdefs/SUNWckr/pkginfo.tmpl Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/pkgdefs/SUNWckr/pkginfo.tmpl Thu Apr 12 18:26:33 2007 -0700 @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -44,6 +44,7 @@ VENDOR="Sun Microsystems, Inc." HOTLINE="Please contact your local service provider" EMAIL="" +CLASSES_i386="mptconf" CLASSES="none etcsystem kcfconfbase manifest preserve renameold scsivhciconf sdconf" BASEDIR=/ SUNW_PKGVERS="1.0"
--- a/usr/src/pkgdefs/SUNWckr/prototype_i386 Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/pkgdefs/SUNWckr/prototype_i386 Thu Apr 12 18:26:33 2007 -0700 @@ -40,6 +40,7 @@ # Include ISA independent files (prototype_com) # !include prototype_com +i i.mptconf # # List files which are i386 specific here # @@ -98,7 +99,7 @@ f none kernel/drv/log 755 root sys f none kernel/drv/mm 755 root sys f none kernel/drv/mpt 755 root sys -f none kernel/drv/mpt.conf 644 root sys +e mptconf kernel/drv/mpt.conf 644 root sys f none kernel/drv/mouse8042 755 root sys f none kernel/drv/openeepr 755 root sys f none kernel/drv/options 755 root sys
--- a/usr/src/pkgdefs/SUNWpd/Makefile Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/pkgdefs/SUNWpd/Makefile Thu Apr 12 18:26:33 2007 -0700 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# 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. @@ -19,15 +18,15 @@ # # CDDL HEADER END # +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1995 by Sun Microsystems, Inc. +# ident "%Z%%M% %I% %E% SMI" # include ../Makefile.com -DATAFILES += depend +DATAFILES += depend i.mptconf .KEEP_STATE:
--- a/usr/src/pkgdefs/SUNWpd/pkginfo.tmpl Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/pkgdefs/SUNWpd/pkginfo.tmpl Thu Apr 12 18:26:33 2007 -0700 @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -44,6 +44,7 @@ VENDOR="Sun Microsystems, Inc." HOTLINE="Please contact your local service provider" EMAIL="" +CLASSES_sparc="mptconf" CLASSES="none" BASEDIR=/ SUNW_PKGVERS="1.0"
--- a/usr/src/pkgdefs/SUNWpd/prototype_sparc Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/pkgdefs/SUNWpd/prototype_sparc Thu Apr 12 18:26:33 2007 -0700 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# 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. @@ -19,10 +18,11 @@ # # CDDL HEADER END # + # -# Copyright 1990-2003 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. -# + #ident "%Z%%M% %I% %E% SMI" # # This required package information file contains a list of package contents. @@ -39,6 +39,7 @@ # Include ISA independent files (prototype_com) # !include prototype_com +i i.mptconf # # # @@ -55,5 +56,6 @@ f none kernel/drv/sparcv9/se 0755 root sys f none kernel/drv/sparcv9/glm 0755 root sys f none kernel/drv/sparcv9/mpt 0755 root sys +e mptconf kernel/drv/mpt.conf 0644 root sys f none kernel/drv/ecpp.conf 0644 root sys f none kernel/drv/sparcv9/ecpp 0755 root sys
--- a/usr/src/pkgdefs/bld_awk_pkginfo.ksh Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/pkgdefs/bld_awk_pkginfo.ksh Thu Apr 12 18:26:33 2007 -0700 @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# 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. @@ -23,8 +22,8 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1995,1997 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # Simple script which builds the awk_pkginfo awk script. This awk script # is used to convert the pkginfo.tmpl files into pkginfo files @@ -48,6 +47,8 @@ VERSION2="VERSION=[^=]*=.*$" PRODVERS="^SUNW_PRODVERS=" ARCH='ARCH=\"ISA\"' +ARCHCLASSES="^CLASSES_" +ALLCLASSES="^CLASSES=" # # parse command line @@ -122,5 +123,18 @@ printf "ARCH=\"%s\"\n", "$mach" next } +/$ARCHCLASSES/ { + sub(/\=/," ") + gsub(/\"/,"") + archclasses[\$1]=\$0 + next + } +/$ALLCLASSES/ { + tag="CLASSES_$mach" + sub(tag,"",archclasses[tag]) + sub(/\"$/,archclasses[tag]"\"") + print + next + } { print } EOF
--- a/usr/src/pkgdefs/common_files/i.kclasses_i386 Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/pkgdefs/common_files/i.kclasses_i386 Thu Apr 12 18:26:33 2007 -0700 @@ -21,7 +21,7 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -65,6 +65,7 @@ -e '/^smartii[ ].*dada/d' \ -e '/^trantor[ ].*scsi/d' \ -e '/^corvette[ ].*scsi/d' \ + -e '/^mpt[ ].*scsi/d' \ $dest > /tmp/c.$$ if cmp -s /tmp/c.$$ $dest > /dev/null 2>&1 then @@ -96,10 +97,6 @@ if [ $? != 0 ] ; then echo 'i2o_scsi scsi' >> $dest fi - grep '^mpt scsi' $dest > /dev/null 2>&1 - if [ $? != 0 ] ; then - echo 'mpt scsi' >> $dest - fi fi done
--- a/usr/src/pkgdefs/common_files/i.kclasses_sparc Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/pkgdefs/common_files/i.kclasses_sparc Thu Apr 12 18:26:33 2007 -0700 @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# 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. @@ -23,7 +22,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -54,6 +53,7 @@ -e '/^ncr[ ]*scsi$/d' \ -e '/^vme[ ]*vme$/d' \ -e '/^pci[ ]*pci$/d' \ + -e '/^mpt[ ]*scsi$/d' \ $dest > /tmp/rest.$$ 2>/dev/null cat /tmp/newident.$$ /tmp/rest.$$ > $dest grep '^isp scsi' $dest > /dev/null 2>&1 @@ -96,10 +96,6 @@ if [ $? != 0 ] ; then echo 'simba pci' >> $dest fi - grep '^mpt scsi' $dest > /dev/null 2>&1 - if [ $? != 0 ] ; then - echo 'mpt scsi' >> $dest - fi fi done rm -f /tmp/newident.$$ /tmp/rest.$$
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/common_files/i.mptconf Thu Apr 12 18:26:33 2007 -0700 @@ -0,0 +1,171 @@ +#!/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 +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# + + +PATH=/usr/bin:/usr/sbin:$PATH; export PATH +PREFIX=/tmp/mpt.conf.$$ + +add_comment_for_vhci_class() +{ + if grep "^# The mpt driver, as a pHCI driver" $1 > /dev/null 2>&1; then + return + fi + + cat >> $1 << EOF + +# +# The mpt driver, as a pHCI driver, must specify the vHCI class it +# belongs to(scsi_vhci). +# +EOF +} + +add_comment_for_mpxio_disable() +{ + + if grep "^# Global mpxio-disable property:" $1 > /dev/null 2>&1; then + return + fi + + cat >> $1 << EOF + +# +# I/O multipathing feature (MPxIO) can be enabled or disabled using +# mpxio-disable property. Setting mpxio-disable="no" will activate +# I/O multipathing; setting mpxio-disable="yes" disables the feature. +# +# Global mpxio-disable property: +# +# To globally enable MPxIO on all mpt controllers set: +# mpxio-disable="no"; +# +# To globally disable MPxIO on all mpt controllers set: +# mpxio-disable="yes"; +# +# You can also enable or disable MPxIO on a per HBA basis. +# Per HBA settings override the global setting for the specified HBAs. +# To disable MPxIO on a controller whose parent is /pci@7c0/pci@0/pci@9 +# and the unit-address is "0" set: +# name="mpt" parent="/pci@7c0/pci@0/pci@9" unit-address="0" mpxio-disable="yes"; +# +EOF +} + +add_comment_for_tape_property() +{ + + if grep "^# The property tape" $1 > /dev/null 2>&1; then + return + fi + + cat >> $1 << EOF + +# +# The property tape is only used for X86 +# +EOF +} + +update_mptconf() +{ + NEWHDR1=$PREFIX.hdr1 + NEWHDR2=$PREFIX.hdr2 + TMPFILE=$PREFIX.tmp + + # replace old copyright with new one + HEADER="^#.* Copyright.*Sun Microsystems.*$" + if grep "$HEADER" $1 > $NEWHDR1 2>/dev/null; then + # replace / by \/ + sed "s/\\//\\\\\\//g" $NEWHDR1 > $NEWHDR2 2>/dev/null + if sed "s/$HEADER/`cat $NEWHDR2`/" $2 > $TMPFILE 2>/dev/null + then + cp $TMPFILE $2 + fi + fi + + # replace old ident with new ident + HEADER="^#.*ident.*SMI\"$" + if grep "$HEADER" $1 > $NEWHDR1 2>/dev/null; then + # replace / by \/ + sed "s/\\//\\\\\\//g" $NEWHDR1 > $NEWHDR2 2>/dev/null + if sed "s/$HEADER/`cat $NEWHDR2`/" $2 > $TMPFILE 2>/dev/null + then + cp $TMPFILE $2 + fi + fi + + if [ "$ARCH" = "i386" ]; then + # remove useless property flow_control and queue + # check the property named tape and that the property is + # only used on i386 platform + sed -e '/^# config file for x86 mpt SCSI HBA driver$/d' \ + -e '/^flow_control="dmult" queue="qsort" tape="sctp";$/d' \ + -e '/^# x86 only$/d' $2 > $TMPFILE + cp $TMPFILE $2 + grep 'tape="sctp"' $2 > /dev/null 2>&1 + if [ $? != 0 ] ; then + add_comment_for_tape_property $2 + echo 'tape="sctp";' >> $2 + fi + fi + + add_comment_for_vhci_class $2 + + # check for property named ddi-vhci-class + grep '^ddi-vhci-class' $2 > /dev/null 2>&1 + if [ $? != 0 ] ; then + echo 'ddi-vhci-class="scsi_vhci";' >> $2 + fi + + add_comment_for_mpxio_disable $2 + + # check for property named mpxio-disable + grep '^mpxio-disable' $2 > /dev/null 2>&1 + if [ $? != 0 ] ; then + echo 'mpxio-disable="yes";' >> $2 + fi + + rm -f $NEWHDR1 $NEWHDR2 $TMPFILE +} + + +if read src dest; then + if [ ! -f $dest ]; then + cp $src $dest + if [ "$ARCH" = "i386" ]; then + # add property tape for i386 platform + add_comment_for_tape_property $dest + echo 'tape="sctp";' >> $dest + fi + else + # upgrading solaris + update_mptconf $src $dest + fi + +fi + +exit 0
--- a/usr/src/tools/scripts/bfu.sh Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/tools/scripts/bfu.sh Thu Apr 12 18:26:33 2007 -0700 @@ -219,6 +219,7 @@ kernel/drv/scsa2usb.conf kernel/drv/scsi_vhci.conf kernel/drv/sd.conf + kernel/drv/mpt.conf platform/*/kernel/drv/*ppm.conf platform/i86pc/kernel/drv/aha.conf platform/i86pc/kernel/drv/asy.conf @@ -599,6 +600,18 @@ fi } +# update x86 version mpt.conf for property tape +mpttapeprop='[ ]*tape[ ]*=[ ]*"sctp"[ ]*;' +update_mptconf_i386() +{ + conffile=$rootprefix/kernel/drv/mpt.conf + test -f $conffile || return + egrep -s "$mpttapeprop" $conffile + if [ $? -ne 0 ] ; then + echo 'tape="sctp";' >> $conffile + fi +} + update_policy_conf() { # update /etc/security/policy.conf with the default # Solaris crypt(3c) policy. @@ -6973,6 +6986,10 @@ update_policy_conf + if [ $target_isa = i386 ]; then + update_mptconf_i386 + fi + if [ $zone != global ]; then rm -rf $global_zone_only_files $superfluous_nonglobal_zone_files fi
--- a/usr/src/uts/common/io/scsi/impl/scsi_hba.c Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/uts/common/io/scsi/impl/scsi_hba.c Thu Apr 12 18:26:33 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1978,6 +1978,16 @@ {"esi", "scsa,0d.busb"}, #endif /* notdef */ + /* + * mapping nodenames for mpt based on scsi dtype + * for being compatible with the original node names + * under mpt controller + */ + {"sd", "scsa,00.bmpt"}, + {"sd", "scsa,05.bmpt"}, + {"sd", "scsa,07.bmpt"}, + {"st", "scsa,01.bmpt"}, + {"ses", "scsa,0d.bmpt"}, {NULL, NULL} }; struct nodename_aliases *nap;
--- a/usr/src/uts/common/io/warlock/mpt.wlcmd Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/uts/common/io/warlock/mpt.wlcmd Thu Apr 12 18:26:33 2007 -0700 @@ -1,5 +1,5 @@ # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -25,6 +25,8 @@ root mpt_kmem_cache_constructor mpt_kmem_cache_destructor root mpt_do_dma root mpt_handle_event +root mpt_handle_dr +root mpt_name_child for ptr in `funcptrs | grep '^scsi_hba_tran::'` do
--- a/usr/src/uts/intel/os/driver_classes Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/uts/intel/os/driver_classes Thu Apr 12 18:26:33 2007 -0700 @@ -1,13 +1,12 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# 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. @@ -32,4 +31,3 @@ pci_pci pci pci_to_i2o i2o i2o_scsi scsi -mpt scsi
--- a/usr/src/uts/sparc/os/driver_classes Thu Apr 12 16:44:57 2007 -0700 +++ b/usr/src/uts/sparc/os/driver_classes Thu Apr 12 18:26:33 2007 -0700 @@ -1,13 +1,12 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# 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. @@ -36,4 +35,3 @@ glm scsi uata dada uata scsi -mpt scsi