Files
s390-tools/zconf/lszfcp
T
Steffen Maier a236180ad8 lszfcp: add new output marker for non-good fc_rports
$ lszfcp -Pe
0.0.50c0/0x500507680b2481fa rport-6:0-2 NotOnline
$ lszfcp -PeV
- (NoMoreZfcpPort:0.0.50c0/0x500507680b2481fa)
/sys/class/fc_remote_ports/rport-6:0-2 NotOnline

$ lszfcp -Pe
0.0.3c40/0x500507680b2181fb rport-7:0-4 NotOnline
$ lszfcp -PeV
/sys/devices/css0/defunct/0.0.3c40/0x500507680b2181fb
/sys/class/fc_remote_ports/rport-7:0-4 NotOnline

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-03-26 17:14:46 +01:00

409 lines
9.7 KiB
Bash
Executable File

#!/bin/bash
#
# lszfcp - Tool to display information about zfcp devices (adapters/ports/units)
#
# Copyright IBM Corp. 2006, 2019
#
# s390-tools is free software; you can redistribute it and/or modify
# it under the terms of the MIT license. See LICENSE for details.
#
SCRIPTNAME='lszfcp'
SYSFS=`cat /proc/mounts | grep -m1 sysfs | awk '{ print $2 }'`
FC_CLASS=false
# Command line parameters
VERBOSITY=0
SHOW_HOSTS=0
SHOW_PORTS=0
SHOW_DEVICES=0
SHOW_ATTRIBUTES=false
SHOW_EXTENDED=false
unset PAR_BUSID PAR_WWPN PAR_LUN
##############################################################################
check_sysfs()
{
if [ -z $SYSFS -o ! -d $SYSFS -o ! -r $SYSFS ]; then
echo "Error: sysfs not available."
exit 1
fi
}
check_zfcp_support()
{
if [ ! -e $SYSFS/bus/ccw/drivers/zfcp ]; then
echo "Error: No zfcp support available."
echo "Load the zfcp module or compile"
echo "the kernel with zfcp support."
exit 1
fi
}
check_fcp_devs()
{
local found=0
if $FC_CLASS; then
# theoretically this includes "defunct" (and thus online) devs
ignore=`ls $SYSFS/class/fc_host/host* 2>&1`
else
ignore=`ls $SYSFS/devices/css0/[0-9]*/[0-9]*/host[0-9]* 2>&1`
fi
[ $? -eq 0 ] && found=1
if [ $found -eq 0 ] && $SHOW_EXTENDED; then
# nothing found yet so search for "defunct" FCP devices
ignore=$(ls -dX $SYSFS/devices/css[0-9]*/defunct/[0-9]*/host[0-9]* 2>&1)
[ $? -eq 0 ] && found=1
fi
if [ $found -eq 0 ]; then
echo "Error: No fcp devices found."
exit 1
fi
}
check_fc_class()
{
if [ -d "$SYSFS/class/fc_host" ]; then
FC_CLASS=true
fi
}
print_version()
{
cat <<EOF
$SCRIPTNAME: version %S390_TOOLS_VERSION%
Copyright IBM Corp. 2006, 2019
EOF
}
print_help()
{
cat <<EOF
Usage: $SCRIPTNAME [OPTIONS]
Provide information contained in sysfs about zfcp adapters, ports and
units that are online.
Mandatory arguments to long options are mandatory for short options too.
OPTIONS:
-H, --hosts show host information (default)
-P, --ports show remote port information
-D, --devices show SCSI device information
-b, --busid=BUSID select specific busid
-p, --wwpn=WWPN select specific port name
-l, --lun=LUN select specific LUN
-a, --attributes show all attributes
-V, --verbose show sysfs paths of associated class
and bus devices
-e, --extended extended output format
-s, --sysfs=PATH use path as sysfs (for dbginfo archives)
-h, --help print this help
-v, --version print version information
EXAMPLE:
List for all zfcp adapters, ports and units the names of their
associated SCSI hosts, FC remote ports and SCSI devices.
#> lszfcp -P -H -D
0.0.3d0c host0
0.0.3d0c/0x500507630300c562 rport-0:0-0
0.0.3d0c/0x500507630300c562/0x4010403300000000 0:0:0:0
The default is to list bus_ids of all zfcp adapters and corresponding
SCSI host names (equals "lszfcp -H").
EOF
}
show_attributes()
{
if [ -z $1 -o ! -d $1 -o ! -r $1 ]; then
return 1
fi
for FILE in `ls $1`; do
read 2>/dev/null CONTENT < $1/$FILE
# Read fails for directories and
# files with permissions 0200.
if [ $? -ne 0 ]; then
continue
fi
printf " %-19s = \"%s\"\n" "$FILE" "$CONTENT"
done
}
show_hosts()
{
HOST_LIST=`ls -dX $SYSFS/devices/css0/[0-9]*/[0-9]*/host[0-9]* \
2> /dev/null`
if $SHOW_EXTENDED; then
# add all "defunct" FCP devices
HOST_LIST="$HOST_LIST
$(ls -dX $SYSFS/devices/css[0-9]*/defunct/[0-9]*/host[0-9]* 2>/dev/null)"
fi
for HOST_PATH in $HOST_LIST; do
SCSI_HOST=`basename $HOST_PATH`
ADAPTER_PATH=`dirname $HOST_PATH`
ADAPTER=`basename $ADAPTER_PATH`
[ $ADAPTER != ${PAR_BUSID:-$ADAPTER} ] && continue
if [ $VERBOSITY -eq 0 ]; then
echo $ADAPTER $SCSI_HOST
else
echo $ADAPTER_PATH
$FC_CLASS && echo "$SYSFS/class/fc_host/$SCSI_HOST"
echo "$SYSFS/class/scsi_host/$SCSI_HOST"
fi
if $SHOW_ATTRIBUTES; then
echo 'Bus = "ccw"'
show_attributes $ADAPTER_PATH
if $FC_CLASS; then
echo 'Class = "fc_host"'
show_attributes \
"$SYSFS/class/fc_host/$SCSI_HOST"
fi
echo 'Class = "scsi_host"'
show_attributes "$SYSFS/class/scsi_host/$SCSI_HOST"
echo
fi
done
}
show_ports()
{
# Without fc_remote_class there is far less information to display.
if ! $FC_CLASS; then
PORT_LIST=`ls -d $SYSFS/devices/css0/*/*/0x*`
for PORT_PATH in $PORT_LIST; do
WWPN=`basename $PORT_PATH`
ADAPTER=`basename \`dirname $PORT_PATH\``
[ $WWPN != ${PAR_WWPN:-$WWPN} ] && continue
[ $ADAPTER != ${PAR_BUSID:-$ADAPTER} ] && continue
if [ $VERBOSITY -eq 0 ]; then
echo "$ADAPTER/$WWPN"
else
echo $PORT_PATH
fi
done
return
fi
if [ -e $SYSFS/class/fc_remote_ports/ ]; then
PORT_LIST=`ls -d $SYSFS/class/fc_remote_ports/* 2>/dev/null`
fi;
for FC_PORT_PATH in $PORT_LIST; do
PORT=`basename $FC_PORT_PATH`
read PORT_STATE < $FC_PORT_PATH/port_state
if [ "$PORT_STATE" == "Online" ] || $SHOW_EXTENDED; then
read WWPN < $FC_PORT_PATH/port_name
else
continue
fi
PORTSTATEMARKER=""
$SHOW_EXTENDED && [ "$PORT_STATE" != "Online" ] \
&& PORTSTATEMARKER=" NotOnline"
[ $WWPN != ${PAR_WWPN:-$WWPN} ] && continue
local sysreal=$(readlink -e "$FC_PORT_PATH")
local ADAPTER=""
while [ -n "$sysreal" ]; do
# ascend to parent: strip last path part
sysreal=${sysreal%/*}
[ -h $sysreal/subsystem ] || continue
local subsystem=$(readlink -e $sysreal/subsystem)
if [ "${subsystem##*/}" = "ccw" ]; then
ADAPTER=${sysreal##*/}
break
fi
done
[ -z "$ADAPTER" ] && continue # skip not zfcp-attached ones
if [ -d $SYSFS/devices/css[0-9]*/[0-9d]*/[0-9]*/$WWPN/../host[0-9]*/$PORT ];
then
ADAPTER_PORT_PATH=$SYSFS/devices/css[0-9]*/[0-9d]*/$ADAPTER/$WWPN
else
ADAPTER_PORT_PATH="-"
fi
[ $ADAPTER != ${PAR_BUSID:-$ADAPTER} ] && continue
if [ $VERBOSITY -eq 0 ]; then
echo "$ADAPTER/$WWPN $PORT$PORTSTATEMARKER"
else
if [ "$ADAPTER_PORT_PATH" != "-" ]; then
echo $ADAPTER_PORT_PATH
else
echo "- (NoMoreZfcpPort:$ADAPTER/$WWPN)"
fi
echo $FC_PORT_PATH$PORTSTATEMARKER
fi
if $SHOW_ATTRIBUTES; then
echo 'Class = "fc_remote_ports"'
show_attributes "$FC_PORT_PATH"
echo
fi
done
}
show_devices()
{
# Differentiate old and new sysfs layout
if $FC_CLASS; then
SCSI_DEVICE_LIST=`ls -d \
$SYSFS/bus/ccw/drivers/zfcp/*/host*/rport*/target*/*/ \
2>/dev/null |grep -P '\d+:\d+:\d+:\d+'`
else
SCSI_DEVICE_LIST=`ls -d $SYSFS/devices/css0/*/*/host[0-9]*/*/`
fi
if [ -z "$SCSI_DEVICE_LIST" ]; then
if $SHOW_EXTENDED; then
echo "Error: No zfcp-attached SCSI devices found."
else
echo "Error: No fcp devices found."
fi
fi
for SCSI_DEVICE_PATH in $SCSI_DEVICE_LIST; do
read ADAPTER < $SCSI_DEVICE_PATH/hba_id
read WWPN < $SCSI_DEVICE_PATH/wwpn
read LUN < $SCSI_DEVICE_PATH/fcp_lun
[ $LUN != ${PAR_LUN:-$LUN} ] && continue
[ $WWPN != ${PAR_WWPN:-$WWPN} ] && continue
[ $ADAPTER != ${PAR_BUSID:-$ADAPTER} ] && continue
if [ $VERBOSITY -eq 0 ]; then
echo "$ADAPTER/$WWPN/$LUN `basename $SCSI_DEVICE_PATH`"
else
echo "`ls -d $SYSFS/devices/css0/*/$ADAPTER`/$WWPN/$LUN"
echo ${SCSI_DEVICE_PATH%*/} # without trailing slash
# On live systems, there are links to the block and
# generic devices. In a dbginfo archive, these links
# are not present. Therefore, fall back to reading
# the runtime.out log file.
if [ `ls $SCSI_DEVICE_PATH | grep -c block:` -eq 1 ]
then
BLOCK_DEV=`ls $SCSI_DEVICE_PATH | grep block:`
GEN_DEV=`ls $SCSI_DEVICE_PATH |\
grep scsi_generic:`
echo -n "$SYSFS/block/${BLOCK_DEV#*:} "
echo "$SYSFS/class/scsi_generic/${GEN_DEV#*:}"
elif [ -d $SCSI_DEVICE_PATH/block ] && $SHOW_EXTENDED
then
# case without CONFIG_SYSFS_DEPRECATED
BLOCK_DEV=$(echo $SCSI_DEVICE_PATH/block/*)
BLOCK_DEV=${BLOCK_DEV##*/}
echo -n "$SYSFS/block/$BLOCK_DEV "
local SGPATH=$SCSI_DEVICE_PATH/scsi_generic
if [ -d $SGPATH ]; then
GEN_DEV=$(echo $SGPATH/*)
GEN_DEV=${GEN_DEV##*/}
echo "$SYSFS/class/scsi_generic/$GEN_DEV"
else
echo "-"
fi
# FIXME Find a way to assign the generic devices.
elif [ -r $SYSFS/../runtime.out ]; then
SCSI_DEV=`basename $SCSI_DEVICE_PATH`
echo "$SYSFS/block/"`grep -r "\[$SCSI_DEV\]"\
$SYSFS/../runtime.out |\
awk -F "/dev/" '{print $2}'`
fi
fi
if $SHOW_ATTRIBUTES; then
echo 'Class = "scsi_device"'
show_attributes "$SCSI_DEVICE_PATH"
echo
fi
done
}
##############################################################################
ARGS=`getopt --options ahvHPDVb:p:l:s:e --longoptions \
attributes,help,version,hosts,ports,devices,verbose,busid:,wwpn:,lun:,sysfs:,extended \
-n "$SCRIPTNAME" -- "$@"`
if [ $? -ne 0 ]; then
echo
print_help
exit
fi
eval set -- "$ARGS"
for ARG; do
case "$ARG" in
-a|--attributes) SHOW_ATTRIBUTES=true; shift 1;;
-e|--extended) SHOW_EXTENDED=true; shift 1;;
-b|--busid) PAR_BUSID=$2; shift 2;;
-h|--help) print_help; exit 0;;
-l|--lun) PAR_LUN=$2; shift 2;;
-p|--wwpn) PAR_WWPN=$2; shift 2;;
-v|--version) print_version; exit 0;;
-H|--hosts) SHOW_HOSTS=1; shift 1;;
-D|--devices) SHOW_DEVICES=1; shift 1;;
-P|--ports) SHOW_PORTS=1; shift 1;;
-V|--verbose) VERBOSITY=1; shift 1;;
-s|--sysfs) SYSFS=$2; shift 2;;
--) shift; break;;
esac
done
check_sysfs
check_zfcp_support
check_fc_class
check_fcp_devs
default=1
if [ $SHOW_HOSTS -eq 1 ]; then
default=0; show_hosts
elif [ $SHOW_PORTS -eq 0 -a $SHOW_DEVICES -eq 0 -a -n "$PAR_BUSID" ]; then
default=0; show_hosts
fi
if [ $SHOW_PORTS -eq 1 ]; then
default=0; show_ports
elif [ $SHOW_HOSTS -eq 0 -a $SHOW_DEVICES -eq 0 -a -n "$PAR_WWPN" ]; then
default=0; show_ports
fi
if [ $SHOW_DEVICES -eq 1 ]; then
default=0; show_devices
elif [ $SHOW_HOSTS -eq 0 -a $SHOW_PORTS -eq 0 -a -n "$PAR_LUN" ]; then
default=0; show_devices
fi
if [ $default == 1 ]; then
show_hosts
fi