#!/bin/bash # # zfcp_san_disc # # Outputs a list of zFCP WWPNs or LUNs # # Usage: # zfcp_san_disc [-h | -W | -L -p ] -b # # Return codes # 1 zFCP sysfs directory not available # 2 Invalid command line parameter # 3 Too many commands used # 4 Error retrieving HBA list # 5 Bus ID not found # 6 Error retrieving Port list # 7 WWPN not found # 8 Bus ID sysfs directory not available # 9 WWPN sysfs directory not available/unable to add port to Bus ID # 10 Error retrieving LUN list # 11 HBA API device not available # START_DIR=`pwd` SCRIPT_NAME=`basename $0` cd `dirname $0` SCRIPT_DIR=`pwd` cd "${START_DIR}" FCP_SYS_DIR='/sys/bus/ccw/drivers/zfcp' # Commands available LIST_WWPN='-W' LIST_LUN='-L' COMMAND='' BUSID='' WWPN='' echo_err() { echo "$SCRIPT_NAME: $1" 1>&2 } usage() { echo "$0 [-h | $LIST_WWPN | $LIST_LUN -p ] -b " 1>&2 echo 1>&2 echo "Commands:" 1>&2 echo " $LIST_WWPN List WWPNs for the given BUS_ID" 1>&2 echo " $LIST_LUN List LUNs for the given BUS_ID and WWPN" 1>&2 echo " -h This usage information" 1>&2 echo "Options:" 1>&2 echo " -b BUSID Bus ID to use for listing" 1>&2 echo " -p WWPN WWPN to use for listing" 1>&2 } list_lun() { local PRINT_WWPN local BUSID_DIR local WWPN_DIR local ADDED_PORT } deactivate() { local ccw=$1 echo 0 > /sys/bus/ccw/devices/$ccw/online } lun_remove() { local syspath=$1 local lun=$2 echo "$lun" > $syspath/unit_remove } sg_remove() { local sg=$1 local sgnum sgnum=${sg#/dev/sg} : deactivate /sys/class/scsi_generic/sg$sgnum/device/delete echo 1 > /sys/class/scsi_generic/sg$sgnum/device/delete udevadm settle } while [ $# -gt 0 ] do case "$1" in -b* ) if [ "$1" == "-b" ] then shift BUSID="$1" else BUSID="${1:2}" fi BUSID=`echo $BUSID | tr A-F a-f` ;; -p* ) if [ "$1" == "-p" ] then shift WWPN="$1" else WWPN="${1:2}" fi WWPN=`echo $WWPN | tr A-FX a-fx` ;; "$LIST_WWPN"|"$LIST_LUN" ) if [ -z "$COMMAND" -o "$1" == "$COMMAND" ] then COMMAND=$1 else echo_err "You have already specified the $COMMAND command, and cannot use the $1 command also." exit 3 fi ;; -h ) usage exit 0 ;; * ) usage echo_err "Unknown command line parameter : $1" exit 2 ;; esac shift done if [ -z "$BUSID" ] ; then echo_err "No bus ID given" exit 2 fi if [ -z "$COMMAND" ] ; then echo_err "Please specify either -W or -L" exit 2 fi if [ ! -d /sys/bus/ccw/devices/$BUSID ] ; then echo_err "Unknown bus ID $BUSID" exit 2 fi read devtype < /sys/bus/ccw/devices/$BUSID/devtype read cutype < /sys/bus/ccw/devices/$BUSID/cutype if [ "$cutype" != "1731/03" ] ; then echo_err "Bus ID $BUSID is not an zfcp adapter" exit 2 fi if [ "$devtype" != "1732/03" -a "$devtype" != "1732/04" ] ; then echo_err "Bus ID $BUSID is not an zfcp adapter" exit 2 fi # Now we're sure we're dealing with zfcp devices if [ ! -d "$FCP_SYS_DIR" ] ; then modprobe zfcp fi [ "$COMMAND" == "$LIST_LUN" -a -z "$WWPN" ] && usage && exit 2 read online < /sys/bus/ccw/devices/$BUSID/online if [ "$online" != 1 ] ; then # Activate adapter echo 1 > /sys/bus/ccw/devices/$BUSID/online read online < /sys/bus/ccw/devices/$BUSID/online if [ "$online" != 1 ] ; then echo_err "Cannot activate zfcp adapter at $BUSID" exit 2 fi trapcmd="deactivate $BUSID" trap "$trapcmd" EXIT fi for loop in 1 2 3 4 5 ; do read status < /sys/bus/ccw/devices/$BUSID/status (( $status & 0x10000000 )) && break; done read wwpn_status < /sys/bus/ccw/devices/$BUSID/status if !(( $wwpn_status & 0x10000000 )) ; then echo_err "Adapter activation failed, status $wwpn_status" exit 3 fi for host in /sys/bus/ccw/devices/$BUSID/host* ; do if [ -d $host ] ; then hba_num=${host##*host} fi done if [ -z "$hba_num" ] ; then echo_err "No SCSI host allocated" exit 3 fi if [ "$COMMAND" == "$LIST_WWPN" ] then for PRINT_WWPN in /sys/bus/ccw/devices/$BUSID/0x* do test -d $PRINT_WWPN && echo ${PRINT_WWPN##*/} done exit 0 elif [ "$COMMAND" != "$LIST_LUN" ] then exit 1 fi ERR=0 read allow_lun_scan < /sys/module/zfcp/parameters/allow_lun_scan if [ "$allow_lun_scan" = "Y" ] ; then read port_type < /sys/class/fc_host/host${hba_num}/port_type if [ "$port_type" = "NPIV VPORT" ] ; then skip_activation=1 fi fi if [ -z "$skip_activation" ] ; then WWPN_DIR=/sys/bus/ccw/devices/$BUSID/$WWPN if [ ! -d "${WWPN_DIR}" ] then echo_err "port $WWPN not found on zfcp $BUSID" exit 9 fi # Activate WLUN if [ ! -d $WWPN_DIR/0xc101000000000000 ] ; then echo 0xc101000000000000 > $WWPN_DIR/unit_add orig_trapcmd="$trapcmd" trapcmd="lun_remove $WWPN_DIR 0xc101000000000000; $trapcmd" trap "$trapcmd" EXIT activated=1 # Wait for udev to catch up udevadm settle sleep 1 fi # Find corresponding sg device sgdev=$(lsscsi -t -g $hba_num:-:-:49409 | sed -n "s/.* fc:$WWPN.* \(\/dev\/sg[0-9]*\)[[:blank:]]*$/\1/p") if [ -c "$sgdev" ] ; then if sg_luns $sgdev > /dev/null 2>&1 ; then LUN_LIST=`sg_luns $sgdev | sed -n 's/^ \(.*\)/\1/p'` trapcmd="sg_remove $sgdev; $trapcmd" trap "$trapcmd" EXIT wlun=1 else wlun= fi fi if [ -z "$wlun" ] ; then if [ -n "$activated" ] ; then trapcmd=$orig_trapcmd trap "$trapcmd" EXIT lun_remove $WWPN_DIR 0xc101000000000000 activated= fi # Activate LUN 0 if [ ! -d $WWPN_DIR/0x0000000000000000 ] ; then echo 0 > $WWPN_DIR/unit_add orig_trapcmd=$trapcmd trapcmd="lun_remove $WWPN_DIR 0x0000000000000000; $trapcmd" trap "$trapcmd" EXIT activated=1 # Wait for udev to catch up udevadm settle sleep 1 fi # Find corresponding sg device sgdev=$(lsscsi -t -g $hba_num:-:-:0 | sed -n "s/.* fc:$WWPN.* \(\/dev\/sg[^[:blank:]]*\)[[:blank:]]*$/\1/p") if [ -c "$sgdev" ] ; then if sg_luns $sgdev > /dev/null 2>&1 ; then LUN_LIST=`sg_luns $sgdev | sed -n 's/^ \(.*\)/\1/p'` fi if [ -n "$activated" ] ; then trapcmd="sg_remove $sgdev; $trapcmd" trap "$trapcmd" EXIT fi else echo_err "Unable to activate LUN 0" trap "$trapcmd" EXIT lun_remove $WWPN_DIR 0x0000000000000000 activated= sgdev= ERR=10 fi fi for LUN in $LUN_LIST ; do echo 0x$LUN done exit $ERR else for loop in 1 2 3 4 5 ; do if [ -n "$(ls -d /sys/class/fc_remote_ports/rport-${hba_num}:* 2>/dev/null)" ] ; then break else sleep 1 fi done if [ -z "$(ls -d /sys/class/fc_remote_ports/rport-${hba_num}:* 2>/dev/null)" ]; then echo "The remote Fiber Channel port has not become available. Exiting" exit 1 fi for rport in /sys/class/fc_remote_ports/rport-${hba_num}:* ; do [ -f ${rport}/port_name ] || continue read port_name < ${rport}/port_name if [ "$port_name" = "$WWPN" ] ; then for t in ${rport}/device/target* ; do [ -f ${t}/uevent ] || continue targetid=${t#*target} targetid=${targetid##*:} break done fi done lsscsi -xx ${hba_num}:0:${targetid}:- | sed -n "s/\[${hba_num}:0:${targetid}:\(0x[0-9a-f]*\)\].*/\1/p" fi