Files
s390-tools/zconf/lstape
Jan Höppner 1bd8ee4b79 lstape: Remove type filter support
There is only one supported tape device type left. A filter command line
option doesn't make any sense anymore.

Remove the functionality and documentation of the --type option.

Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:00 +01:00

456 lines
9.4 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.
: --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=""
SHORTID=false
SHOWCCW=true
VERBOSE=false
SHOWSCSI=true
FILTERONLINE=false
FILTEROFFLINE=false
while [ $# -ne 0 ]; do
case $1 in
-h|--help)
PrintUsage
exit 0
;;
--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"
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, "/")
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