mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
The device models 3480 and 3590 are no longer supported by the tape device driver. Remove them from the device list Reviewed-by: Jens Remus <jremus@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
475 lines
9.8 KiB
Bash
Executable File
475 lines
9.8 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# lstape - Tool to show information about tape devices
|
|
#
|
|
# Copyright IBM Corp. 2003, 2018
|
|
#
|
|
# s390-tools is free software; you can redistribute it and/or modify
|
|
# it under the terms of the MIT license. See LICENSE for details.
|
|
#
|
|
|
|
CMD=$(basename $0)
|
|
SG_INQ=$(type -p sg_inq)
|
|
|
|
function RequireArgument() {
|
|
if [ $2 -eq 1 ]; then
|
|
echo "The $1 option requires an argument" >&2
|
|
else
|
|
echo "The $1 option requires $2 arguments" >&2
|
|
fi
|
|
}
|
|
|
|
function PrintUsage() {
|
|
cat <<-EOD | cut -c2-
|
|
:Usage: $(basename $0) [<options>]
|
|
:
|
|
: <options>
|
|
: -h|--help
|
|
: Print this help text.
|
|
: --ccw-only|--scsi-only
|
|
: Limit output to CCW or SCSI devices only.
|
|
: -t|--type <list of device types>
|
|
: Limit output of CCW tape devices to the given
|
|
: devices. The list consists of device types
|
|
: separated by ','.
|
|
: --online|--offline
|
|
: Show only devices that are either online or
|
|
: offline (only one option is allowed). This
|
|
: option only affects CCW devices.
|
|
: -s|--shortid
|
|
: Show only devices on channel subsytem 0 with
|
|
: subchannel set 0 and remove the leading '0.0.'
|
|
: from the displayed bus id (only affects the
|
|
: output of CCW devices).
|
|
: -V|--verbose
|
|
: Print additional information that does not fit
|
|
: into a single line (only affects the output for
|
|
: SCSI devices).
|
|
: -v|--version
|
|
: Display the version of the tools package and
|
|
: the lstape command.
|
|
:
|
|
:$(basename $0) without the --ccw-only option causes extra SAN traffic
|
|
:for each SCSI tape or changer device by invoking the sg_inq command.
|
|
EOD
|
|
}
|
|
|
|
function PrintVersion()
|
|
{
|
|
cat <<-EOD
|
|
$CMD: version %S390_TOOLS_VERSION%
|
|
Copyright IBM Corp. 2003, 2018
|
|
EOD
|
|
}
|
|
|
|
FLSEP=""
|
|
DEVLIST="3490"
|
|
SHORTID=false
|
|
SHOWCCW=true
|
|
VERBOSE=false
|
|
SHOWSCSI=true
|
|
FILTERONLINE=false
|
|
FILTEROFFLINE=false
|
|
|
|
while [ $# -ne 0 ]; do
|
|
case $1 in
|
|
-h|--help)
|
|
PrintUsage
|
|
exit 0
|
|
;;
|
|
-t|--type)
|
|
if [ $# -lt 2 ]; then
|
|
RequireArgument $1 1
|
|
exit 1
|
|
fi
|
|
shift
|
|
DEVLIST="$1"
|
|
;;
|
|
--online)
|
|
if $FILTEROFFLINE; then
|
|
echo -n "Option --online and --offline " >&2
|
|
echo "are exclusive" >&2
|
|
exit 1
|
|
fi
|
|
FILTERONLINE=true
|
|
;;
|
|
--offline)
|
|
if $FILTERONLINE; then
|
|
echo -n "Option --online and --offline " >&2
|
|
echo "are exclusive" >&2
|
|
exit 1
|
|
fi
|
|
FILTEROFFLINE=true
|
|
;;
|
|
-s|--shortid)
|
|
SHORTID=true
|
|
;;
|
|
-v|--version)
|
|
PrintVersion
|
|
exit 0
|
|
;;
|
|
-V|--verbose)
|
|
VERBOSE=true;
|
|
;;
|
|
--ccw-only)
|
|
if ! $SHOWCCW; then
|
|
echo "ERROR: --ccw-only after --scsi-only!" >&2
|
|
exit 1
|
|
fi
|
|
SHOWSCSI=false;
|
|
;;
|
|
--scsi-only)
|
|
if ! $SHOWSCSI; then
|
|
echo "ERROR: --scsi-only after --ccw-only!" >&2
|
|
exit 1
|
|
fi
|
|
SHOWCCW=false
|
|
;;
|
|
-*|--*)
|
|
echo "$CMD: Invalid option $1" >&2
|
|
echo "Try 'lstape --help' for more information." >&2
|
|
exit 1
|
|
;;
|
|
*)
|
|
FILTERLIST="$FILTERLIST$FLSEP$1"
|
|
FLSEP=","
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
function SysfsCreateListCCW() {
|
|
(
|
|
find $1/bus/ccw/drivers/tape_34xx -type l \
|
|
-printf '%f\n' 2>/dev/null
|
|
) | awk -v format="$CCWFORMAT" '
|
|
BEGIN{
|
|
medium_state_str[0] = "UNKNOWN "
|
|
medium_state_str[1] = "LOADED "
|
|
medium_state_str[2] = "UNLOADED"
|
|
|
|
split("'$DEVLIST'", A, ",")
|
|
for(i = 1; i in A; i++) {
|
|
devlist[A[i]] = 1
|
|
}
|
|
shortid = "'$SHORTID'"=="true" ? 1 : 0
|
|
filteronline = "'$FILTERONLINE'"=="true" ? 1 : 0
|
|
filteroffline = "'$FILTEROFFLINE'"=="true" ? 1 : 0
|
|
}
|
|
function Read(file) {
|
|
value = ""
|
|
getline value <file
|
|
close(file)
|
|
return value
|
|
}
|
|
{
|
|
bus_id = tolower($1)
|
|
devdir = "'$1'/bus/ccw/devices/" bus_id
|
|
|
|
devtype = Read(devdir "/devtype")
|
|
split(devtype, A, "/")
|
|
if (!(A[1] in devlist))
|
|
next
|
|
|
|
online = Read(devdir "/online")
|
|
if (filteronline && !online)
|
|
next
|
|
if (filteroffline && online)
|
|
next
|
|
|
|
cutype = Read(devdir "/cutype")
|
|
majmin = Read(devdir "/non-rewinding/dev")
|
|
if (majmin != "") {
|
|
split(majmin, A, ":")
|
|
first_minor = A[2]
|
|
} else {
|
|
first_minor = Read(devdir "/first_minor")
|
|
}
|
|
if(first_minor == "")
|
|
next
|
|
|
|
if (online) {
|
|
medium_state = Read(devdir "/medium_state")
|
|
state = Read(devdir "/state")
|
|
operation = Read(devdir "/operation")
|
|
blocksize = Read(devdir "/blocksize")
|
|
if (blocksize == 0)
|
|
blocksize = "auto"
|
|
} else {
|
|
state = "OFFLINE"
|
|
operation = "---"
|
|
blocksize = "N/A"
|
|
}
|
|
|
|
if (shortid) {
|
|
if (substr(bus_id, 1, 4) != "0.0.")
|
|
next
|
|
bus_id = substr(bus_id, 5)
|
|
}
|
|
|
|
printf(format,
|
|
(online==0) ? "N/A" : first_minor / 2,
|
|
bus_id,
|
|
tolower(cutype),
|
|
tolower(devtype),
|
|
blocksize,
|
|
state,
|
|
operation,
|
|
(online==0) ? "N/A" : \
|
|
medium_state_str[medium_state])
|
|
}
|
|
' | sort
|
|
}
|
|
|
|
# handle SCSI device not necessarily zfcp-attached, e.g. virtio-scsi-ccw
|
|
function SCSISearchCCWBusid()
|
|
{
|
|
local SCSI_DEV=$1
|
|
local SDEVCAN=$(readlink -e $SCSI_DEV)
|
|
while [ -n "$SDEVCAN" ]; do
|
|
# ascend to parent: strip last path part
|
|
SDEVCAN=${SDEVCAN%/*}
|
|
[ -h $SDEVCAN/subsystem ] || continue
|
|
local SUBSYSTEM=$(readlink -e $SDEVCAN/subsystem)
|
|
if [ "${SUBSYSTEM##*/}" = "ccw" ]; then
|
|
echo ${SDEVCAN##*/}
|
|
return
|
|
fi
|
|
done
|
|
echo "N/A"
|
|
}
|
|
|
|
function SysfsCreateListSCSI()
|
|
{
|
|
for SCSI_DEV in $1/bus/scsi/devices/*:*:*:*; do
|
|
if [ ! -e $SCSI_DEV ]; then
|
|
continue
|
|
fi
|
|
TYPE=$(cat $SCSI_DEV/type)
|
|
case $TYPE in
|
|
1)
|
|
DEV_TYPE=tapedrv
|
|
DEV_NAME=IBMtape
|
|
;;
|
|
8)
|
|
DEV_TYPE=changer
|
|
DEV_NAME=IBMchanger
|
|
;;
|
|
*)
|
|
continue
|
|
esac
|
|
SCSI_LIST=$(ls -1d $SCSI_DEV/*)
|
|
SCSI_ID=$(basename $SCSI_DEV)
|
|
VENDOR=$(cat $SCSI_DEV/vendor)
|
|
MODEL=$(cat $SCSI_DEV/model)
|
|
STATE=$(cat $SCSI_DEV/state)
|
|
SG_DEV=$(echo $SCSI_DEV/scsi_generic*)
|
|
|
|
if [ -h $SG_DEV ]; then
|
|
# deprecated sysfs layout
|
|
SG_DEV=$(echo $SG_DEV | awk -F: '{print $NF}')
|
|
elif [ -d $SCSI_DEV/scsi_generic ]; then
|
|
SG_DEV=$(basename $SG_DEV/*)
|
|
else
|
|
SG_DEV=""
|
|
fi
|
|
|
|
if [ -z "$SG_DEV" ]; then
|
|
SG_DEV="N/A"
|
|
TAPE_SERIAL="NO/SG"
|
|
elif [ "$SG_INQ" != "" ]; then
|
|
TAPE_SERIAL=$(
|
|
sg_inq /dev/$SG_DEV |
|
|
awk '/serial/{print $NF}'
|
|
)
|
|
else
|
|
TAPE_SERIAL="NO/INQ"
|
|
fi
|
|
|
|
TAPE_DEV="N/A"
|
|
if [ "$(echo "$SCSI_LIST"|grep scsi_tape)" != "" ]; then
|
|
if [ -d $SCSI_DEV/scsi_tape ]; then
|
|
TAPE_IDX=$(echo $SCSI_DEV/scsi_tape/st*[0-9] |
|
|
sed -e 's/.*scsi_tape\///')
|
|
else
|
|
# deprecated sysfs layout
|
|
TAPE_IDX=$(
|
|
echo "$SCSI_LIST" |
|
|
awk -F: '/scsi_tape\:st[0-9]+$/{print $NF}'
|
|
)
|
|
fi
|
|
if [ "$TAPE_IDX" != "" ]; then
|
|
TAPE_DEV=$TAPE_IDX
|
|
fi
|
|
elif [ "$(echo "$SCSI_LIST"|grep scsi_changer)" != "" ]; then
|
|
if [ -d $SCSI_DEV/scsi_changer ]; then
|
|
CHG_IDX=$(echo $SCSI_DEV/scsi_changer/sch*[0-9] |
|
|
sed -e 's/.*scsi_changer\///')
|
|
else
|
|
# deprecated sysfs layout
|
|
CHG_IDX=$(
|
|
echo "$SCSI_LIST" |
|
|
awk -F: '/scsi_changer\:sch[0-9]+$/{print $NF}'
|
|
)
|
|
fi
|
|
if [ "$CHG_IDX" != "" ]; then
|
|
TAPE_DEV=$CHG_IDX
|
|
fi
|
|
elif [ "$(echo "$SCSI_LIST"|grep lin_tape)" != "" ]; then
|
|
# bash glob sorts so IBMtape0 comes before IBMtape0n
|
|
local IBM_PATH=$(
|
|
ls -1d $SCSI_DEV/lin_tape/$DEV_NAME[0-9]* |
|
|
head -n 1)
|
|
if [ -d "$IBM_PATH" ]; then
|
|
IBM_IDX=${IBM_PATH##*/}
|
|
else
|
|
# deprecated sysfs layout
|
|
IBM_IDX=$(
|
|
echo "$SCSI_LIST" |
|
|
awk -F: '/lin_tape\:'"$DEV_NAME"'[0-9]+$/{print $NF}'
|
|
)
|
|
fi
|
|
if [ "$IBM_IDX" != "" ]; then
|
|
TAPE_DEV=$IBM_IDX
|
|
fi
|
|
elif [ -r /proc/scsi/$DEV_NAME ]; then
|
|
IBM_IDX=$(
|
|
grep -wF "$SCSI_ID" /proc/scsi/$DEV_NAME |
|
|
cut -d ' ' -f 1
|
|
)
|
|
if [ "$IBM_IDX" != "" ]; then
|
|
TAPE_DEV=$DEV_NAME$IBM_IDX
|
|
fi
|
|
fi
|
|
|
|
printf "$SCSIFORMAT" \
|
|
$SG_DEV \
|
|
$TAPE_DEV \
|
|
$SCSI_ID \
|
|
$VENDOR $MODEL \
|
|
$DEV_TYPE \
|
|
$STATE
|
|
|
|
if $VERBOSE; then
|
|
if [ -r $SCSI_DEV/hba_id ]; then
|
|
HBA_ID=$(cat $SCSI_DEV/hba_id)
|
|
else
|
|
HBA_ID=$(SCSISearchCCWBusid $SCSI_DEV)
|
|
fi
|
|
WWPN="N/A"
|
|
[ -r $SCSI_DEV/wwpn ] && WWPN=$(cat $SCSI_DEV/wwpn)
|
|
printf "$SCSIVFORMAT" \
|
|
"$HBA_ID" \
|
|
"$WWPN" \
|
|
$TAPE_SERIAL
|
|
fi
|
|
done
|
|
}
|
|
|
|
case $(uname -r|cut -d. -f1-2) in
|
|
1.*|2.[012])
|
|
echo "Not supported!" >&2
|
|
exit 1
|
|
;;
|
|
2.3|2.4)
|
|
SYSFS=false
|
|
;;
|
|
*)
|
|
SYSFS=true
|
|
if [ "$(cat /proc/filesystems|grep sysfs)" = "" ]; then
|
|
echo "WARNING: no sysfs support." >&2
|
|
SYSFS=false
|
|
fi
|
|
SYSFSDIR=$(cat /proc/mounts|awk '$3=="sysfs"{print $2; exit}')
|
|
if [ "SYSFS" = "true" -a "$SYSFSDIR" = "" ]; then
|
|
echo "WARNING: sysfs not mounted." >&2
|
|
SYSFS=false
|
|
fi
|
|
if [ "$SYSFS" = "false" -a "$SHOWCCW" = "true" ]; then
|
|
echo -n "WARNING: proc interface will not find offline"
|
|
echo " devices on kernel $(uname -r|cut -d. -f1-2)."
|
|
echo
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
function ShowTapesCCW()
|
|
{
|
|
if $SYSFS; then
|
|
SysfsCreateListCCW $SYSFSDIR
|
|
else
|
|
if [ ! -r /proc/tapedevices ]; then
|
|
echo "ERROR: neither proc nor sysfs found!" >&2
|
|
return 1
|
|
fi
|
|
cat /proc/tapedevices
|
|
fi | awk -v LIST="$FILTERLIST" '
|
|
BEGIN{
|
|
if(LIST != "")
|
|
split(LIST, A, ",")
|
|
}
|
|
LIST != ""{
|
|
for(i in A) {
|
|
if(index($2, A[i]) > 0) {
|
|
print $0
|
|
next
|
|
}
|
|
}
|
|
next
|
|
}
|
|
{
|
|
print $0
|
|
}
|
|
'
|
|
}
|
|
|
|
if $SHOWCCW; then
|
|
CCWFORMAT="%-7s %-10s %-12s %-15s %-7s %-7s %-7s %-8s\n"
|
|
LIST=$(ShowTapesCCW)
|
|
|
|
if [ "$LIST" = "" ]; then
|
|
NUMCCW=0
|
|
else
|
|
NUMCCW=$(echo "$LIST"|wc -l)
|
|
fi
|
|
|
|
if $SHOWSCSI; then
|
|
echo "FICON/ESCON tapes (found $NUMCCW):"
|
|
fi
|
|
printf "$CCWFORMAT" "TapeNo" "BusID" "CuType/Model" "DevType/Model" \
|
|
"BlkSize" "State" "Op" "MedState"
|
|
if [ $NUMCCW -gt 0 ]; then
|
|
echo "$LIST"
|
|
fi
|
|
fi
|
|
if $SHOWSCSI; then
|
|
SCSIFORMAT="%-7s %-13s %-12s %-8s %-16s %-8s %s\n"
|
|
SCSIVFORMAT=" %-8s %-18s %s\n"
|
|
LIST=$(SysfsCreateListSCSI $SYSFSDIR)
|
|
|
|
if [ "$LIST" = "" ]; then
|
|
NUMSCSI=0
|
|
else
|
|
NUMSCSI=$(echo "$LIST"|wc -l)
|
|
if $VERBOSE; then
|
|
let "NUMSCSI/=2"
|
|
fi
|
|
fi
|
|
|
|
if $SHOWCCW; then
|
|
echo
|
|
echo "SCSI tape devices (found $NUMSCSI):"
|
|
fi
|
|
printf "$SCSIFORMAT" "Generic" "Device" "Target" "Vendor" "Model" \
|
|
"Type" "State"
|
|
if $VERBOSE; then
|
|
printf "$SCSIVFORMAT" "HBA" "WWPN" "Serial"
|
|
fi
|
|
if [ $NUMSCSI -gt 0 ]; then
|
|
echo "$LIST"
|
|
fi
|
|
fi
|
|
|
|
exit 0
|
|
|