1*44704f69SBart Van Assche#!/bin/bash 2*44704f69SBart Van Assche# Script to rescan SCSI bus, using the scsi add-single-device mechanism. 3*44704f69SBart Van Assche# (c) 1998--2010 Kurt Garloff <[email protected]>, GNU GPL v2 or v3 4*44704f69SBart Van Assche# (c) 2006--2022 Hannes Reinecke, GNU GPL v2 or later 5*44704f69SBart Van Assche# $Id: rescan-scsi-bus.sh,v 1.57 2012/03/31 14:08:48 garloff Exp $ 6*44704f69SBart Van Assche 7*44704f69SBart Van AsscheVERSION="20220930" 8*44704f69SBart Van AsscheSCAN_WILD_CARD=4294967295 9*44704f69SBart Van Assche 10*44704f69SBart Van AsscheTMPLUNINFOFILE="/tmp/rescan-scsi-mpath-info.txt" 11*44704f69SBart Van Assche 12*44704f69SBart Van Asschesetcolor () 13*44704f69SBart Van Assche{ 14*44704f69SBart Van Assche red="\e[0;31m" 15*44704f69SBart Van Assche green="\e[0;32m" 16*44704f69SBart Van Assche yellow="\e[0;33m" 17*44704f69SBart Van Assche bold="\e[0;1m" 18*44704f69SBart Van Assche norm="\e[0;0m" 19*44704f69SBart Van Assche} 20*44704f69SBart Van Assche 21*44704f69SBart Van Asscheunsetcolor () 22*44704f69SBart Van Assche{ 23*44704f69SBart Van Assche red=""; green="" 24*44704f69SBart Van Assche yellow=""; norm="" 25*44704f69SBart Van Assche} 26*44704f69SBart Van Assche 27*44704f69SBart Van Asscheecho_debug() 28*44704f69SBart Van Assche{ 29*44704f69SBart Van Assche if [ "$debug" -eq 1 ] ; then 30*44704f69SBart Van Assche echo "$1" 31*44704f69SBart Van Assche fi 32*44704f69SBart Van Assche} 33*44704f69SBart Van Assche 34*44704f69SBart Van Assche# Output some text and return cursor to previous position 35*44704f69SBart Van Assche# (only works for simple strings) 36*44704f69SBart Van Assche# Stores length of string in LN and returns it 37*44704f69SBart Van Asscheprint_and_scroll_back () 38*44704f69SBart Van Assche{ 39*44704f69SBart Van Assche STRG="$1" 40*44704f69SBart Van Assche LN=${#STRG} 41*44704f69SBart Van Assche BK="" 42*44704f69SBart Van Assche declare -i cntr=0 43*44704f69SBart Van Assche while [ $cntr -lt "$LN" ] ; do BK="$BK\e[D"; let cntr+=1; done 44*44704f69SBart Van Assche echo -en "$STRG$BK" 45*44704f69SBart Van Assche return "$LN" 46*44704f69SBart Van Assche} 47*44704f69SBart Van Assche 48*44704f69SBart Van Assche# Overwrite a text of length $LN with whitespace 49*44704f69SBart Van Asschewhite_out () 50*44704f69SBart Van Assche{ 51*44704f69SBart Van Assche BK=""; WH="" 52*44704f69SBart Van Assche declare -i cntr=0 53*44704f69SBart Van Assche while [ $cntr -lt "$LN" ] ; do BK="$BK\e[D"; WH="$WH "; let cntr+=1; done 54*44704f69SBart Van Assche echo -en "$WH$BK" 55*44704f69SBart Van Assche} 56*44704f69SBart Van Assche 57*44704f69SBart Van Assche# Return hosts. sysfs must be mounted 58*44704f69SBart Van Asschefindhosts_26 () 59*44704f69SBart Van Assche{ 60*44704f69SBart Van Assche hosts= 61*44704f69SBart Van Assche for hostdir in /sys/class/scsi_host/host* ; do 62*44704f69SBart Van Assche [ -e "$hostdir" ] || continue 63*44704f69SBart Van Assche hostno=${hostdir#/sys/class/scsi_host/host} 64*44704f69SBart Van Assche if [ -f "$hostdir/isp_name" ] ; then 65*44704f69SBart Van Assche hostname="qla2xxx" 66*44704f69SBart Van Assche elif [ -f "$hostdir/lpfc_drvr_version" ] ; then 67*44704f69SBart Van Assche hostname="lpfc" 68*44704f69SBart Van Assche else 69*44704f69SBart Van Assche hostname=$(cat "$hostdir/proc_name") 70*44704f69SBart Van Assche fi 71*44704f69SBart Van Assche hosts="$hosts $hostno" 72*44704f69SBart Van Assche echo_debug "Host adapter $hostno ($hostname) found." 73*44704f69SBart Van Assche done 74*44704f69SBart Van Assche if [ -z "$hosts" ] ; then 75*44704f69SBart Van Assche echo "No SCSI host adapters found in sysfs" 76*44704f69SBart Van Assche exit 1; 77*44704f69SBart Van Assche fi 78*44704f69SBart Van Assche # ensure numeric ordering. No quotes arount $hosts to skip leading space. 79*44704f69SBart Van Assche hosts=$(echo $hosts | tr ' ' '\n' | sort -n) 80*44704f69SBart Van Assche} 81*44704f69SBart Van Assche 82*44704f69SBart Van Assche# Return hosts. /proc/scsi/HOSTADAPTER/? must exist 83*44704f69SBart Van Asschefindhosts () 84*44704f69SBart Van Assche{ 85*44704f69SBart Van Assche hosts= 86*44704f69SBart Van Assche for driverdir in /proc/scsi/*; do 87*44704f69SBart Van Assche driver=${driverdir#/proc/scsi/} 88*44704f69SBart Van Assche if [ "$driver" = scsi ] || [ "$driver" = sg ] || [ "$driver" = dummy ] || [ "$driver" = device_info ] ; then continue; fi 89*44704f69SBart Van Assche for hostdir in $driverdir/*; do 90*44704f69SBart Van Assche name=${hostdir#/proc/scsi/*/} 91*44704f69SBart Van Assche if [ "$name" = add_map ] || [ "$name" = map ] || [ "$name" = mod_parm ] ; then continue; fi 92*44704f69SBart Van Assche num=$name 93*44704f69SBart Van Assche driverinfo=$driver 94*44704f69SBart Van Assche if [ -r "$hostdir/status" ] ; then 95*44704f69SBart Van Assche num=$(printf '%d\n' "$(sed -n 's/SCSI host number://p' "$hostdir/status")") 96*44704f69SBart Van Assche driverinfo="$driver:$name" 97*44704f69SBart Van Assche fi 98*44704f69SBart Van Assche hosts="$hosts $num" 99*44704f69SBart Van Assche echo "Host adapter $num ($driverinfo) found." 100*44704f69SBart Van Assche done 101*44704f69SBart Van Assche done 102*44704f69SBart Van Assche} 103*44704f69SBart Van Assche 104*44704f69SBart Van Asscheprinttype () 105*44704f69SBart Van Assche{ 106*44704f69SBart Van Assche local type=$1 107*44704f69SBart Van Assche 108*44704f69SBart Van Assche case "$type" in 109*44704f69SBart Van Assche 0) echo "Direct-Access" ;; 110*44704f69SBart Van Assche 1) echo "Sequential-Access" ;; 111*44704f69SBart Van Assche 2) echo "Printer" ;; 112*44704f69SBart Van Assche 3) echo "Processor" ;; 113*44704f69SBart Van Assche 4) echo "WORM" ;; 114*44704f69SBart Van Assche 5) echo "CD-ROM" ;; 115*44704f69SBart Van Assche 6) echo "Scanner" ;; 116*44704f69SBart Van Assche 7) echo "Optical-Device" ;; 117*44704f69SBart Van Assche 8) echo "Medium-Changer" ;; 118*44704f69SBart Van Assche 9) echo "Communications" ;; 119*44704f69SBart Van Assche 10) echo "Unknown" ;; 120*44704f69SBart Van Assche 11) echo "Unknown" ;; 121*44704f69SBart Van Assche 12) echo "RAID" ;; 122*44704f69SBart Van Assche 13) echo "Enclosure" ;; 123*44704f69SBart Van Assche 14) echo "Direct-Access-RBC" ;; 124*44704f69SBart Van Assche *) echo "Unknown" ;; 125*44704f69SBart Van Assche esac 126*44704f69SBart Van Assche} 127*44704f69SBart Van Assche 128*44704f69SBart Van Asscheprint02i() 129*44704f69SBart Van Assche{ 130*44704f69SBart Van Assche if [ "$1" = "*" ] ; then 131*44704f69SBart Van Assche echo "00" 132*44704f69SBart Van Assche else 133*44704f69SBart Van Assche printf "%02i" "$1" 134*44704f69SBart Van Assche fi 135*44704f69SBart Van Assche} 136*44704f69SBart Van Assche 137*44704f69SBart Van Assche# Get /proc/scsi/scsi info for device $host:$channel:$id:$lun 138*44704f69SBart Van Assche# Optional parameter: Number of lines after first (default = 2), 139*44704f69SBart Van Assche# result in SCSISTR, return code 1 means empty. 140*44704f69SBart Van Asscheprocscsiscsi () 141*44704f69SBart Van Assche{ 142*44704f69SBart Van Assche if [ -z "$1" ] ; then 143*44704f69SBart Van Assche LN=2 144*44704f69SBart Van Assche else 145*44704f69SBart Van Assche LN=$1 146*44704f69SBart Van Assche fi 147*44704f69SBart Van Assche CHANNEL=$(print02i "$channel") 148*44704f69SBart Van Assche ID=$(print02i "$id") 149*44704f69SBart Van Assche LUN=$(print02i "$lun") 150*44704f69SBart Van Assche if [ -d /sys/class/scsi_device ]; then 151*44704f69SBart Van Assche SCSIPATH="/sys/class/scsi_device/${host}:${channel}:${id}:${lun}" 152*44704f69SBart Van Assche if [ -d "$SCSIPATH" ] ; then 153*44704f69SBart Van Assche SCSISTR="Host: scsi${host} Channel: $CHANNEL Id: $ID Lun: $LUN" 154*44704f69SBart Van Assche if [ "$LN" -gt 0 ] ; then 155*44704f69SBart Van Assche IVEND=$(cat "${SCSIPATH}/device/vendor") 156*44704f69SBart Van Assche IPROD=$(cat "${SCSIPATH}/device/model") 157*44704f69SBart Van Assche IPREV=$(cat "${SCSIPATH}/device/rev") 158*44704f69SBart Van Assche SCSIDEV=$(printf ' Vendor: %-08s Model: %-16s Rev: %-4s' "$IVEND" "$IPROD" "$IPREV") 159*44704f69SBart Van Assche SCSISTR="$SCSISTR 160*44704f69SBart Van Assche$SCSIDEV" 161*44704f69SBart Van Assche fi 162*44704f69SBart Van Assche if [ "$LN" -gt 1 ] ; then 163*44704f69SBart Van Assche ILVL=$(cat "${SCSIPATH}/device/scsi_level") 164*44704f69SBart Van Assche type=$(cat "${SCSIPATH}/device/type") 165*44704f69SBart Van Assche ITYPE=$(printtype "$type") 166*44704f69SBart Van Assche SCSITMP=$(printf ' Type: %-17s ANSI SCSI revision: %02d' "$ITYPE" "$((ILVL - 1))") 167*44704f69SBart Van Assche SCSISTR="$SCSISTR 168*44704f69SBart Van Assche$SCSITMP" 169*44704f69SBart Van Assche fi 170*44704f69SBart Van Assche else 171*44704f69SBart Van Assche return 1 172*44704f69SBart Van Assche fi 173*44704f69SBart Van Assche else 174*44704f69SBart Van Assche grepstr="scsi$host Channel: $CHANNEL Id: $ID Lun: $LUN" 175*44704f69SBart Van Assche SCSISTR=$(grep -A "$LN" -e "$grepstr" /proc/scsi/scsi) 176*44704f69SBart Van Assche fi 177*44704f69SBart Van Assche if [ -z "$SCSISTR" ] ; then 178*44704f69SBart Van Assche return 1 179*44704f69SBart Van Assche else 180*44704f69SBart Van Assche return 0 181*44704f69SBart Van Assche fi 182*44704f69SBart Van Assche} 183*44704f69SBart Van Assche 184*44704f69SBart Van Assche# Find sg device with 2.6 sysfs support 185*44704f69SBart Van Asschesgdevice26 () 186*44704f69SBart Van Assche{ 187*44704f69SBart Van Assche local gendev 188*44704f69SBart Van Assche 189*44704f69SBart Van Assche # if the scsi device has not been added, then there would not 190*44704f69SBart Van Assche # a related sgdev. So it's pointless to scan all sgs to find 191*44704f69SBart Van Assche # a related sg. 192*44704f69SBart Van Assche scsidev=/sys/class/scsi_device/${host}:${channel}:${id}:${lun} 193*44704f69SBart Van Assche if [ ! -e "$scsidev" ]; then 194*44704f69SBart Van Assche SGDEV="" 195*44704f69SBart Van Assche return 196*44704f69SBart Van Assche fi 197*44704f69SBart Van Assche 198*44704f69SBart Van Assche gendev=/sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device/generic 199*44704f69SBart Van Assche if [ -e "$gendev" ] ; then 200*44704f69SBart Van Assche SGDEV=$(basename "$(readlink "$gendev")") 201*44704f69SBart Van Assche return 202*44704f69SBart Van Assche fi 203*44704f69SBart Van Assche SGDEV="" 204*44704f69SBart Van Assche} 205*44704f69SBart Van Assche 206*44704f69SBart Van Assche# Find sg device with 2.4 report-devs extensions 207*44704f69SBart Van Asschesgdevice24 () 208*44704f69SBart Van Assche{ 209*44704f69SBart Van Assche if procscsiscsi 3; then 210*44704f69SBart Van Assche SGDEV=$(echo "$SCSISTR" | grep 'Attached drivers:' | sed 's/^ *Attached drivers: \(sg[0-9]*\).*/\1/') 211*44704f69SBart Van Assche fi 212*44704f69SBart Van Assche} 213*44704f69SBart Van Assche 214*44704f69SBart Van Assche# Find sg device that belongs to SCSI device $host $channel $id $lun 215*44704f69SBart Van Assche# and return in SGDEV 216*44704f69SBart Van Asschesgdevice () 217*44704f69SBart Van Assche{ 218*44704f69SBart Van Assche SGDEV= 219*44704f69SBart Van Assche if [ -d /sys/class/scsi_device ] ; then 220*44704f69SBart Van Assche sgdevice26 221*44704f69SBart Van Assche else 222*44704f69SBart Van Assche DRV=$(grep 'Attached drivers:' /proc/scsi/scsi 2>/dev/null) 223*44704f69SBart Van Assche repdevstat=$((1-$?)) 224*44704f69SBart Van Assche if [ $repdevstat = 0 ]; then 225*44704f69SBart Van Assche echo "scsi report-devs 1" >/proc/scsi/scsi 226*44704f69SBart Van Assche DRV=$(grep 'Attached drivers:' /proc/scsi/scsi 2>/dev/null) 227*44704f69SBart Van Assche [ $? -eq 1 ] && return 228*44704f69SBart Van Assche fi 229*44704f69SBart Van Assche if ! echo "$DRV" | grep -q 'drivers: sg'; then 230*44704f69SBart Van Assche modprobe sg 231*44704f69SBart Van Assche fi 232*44704f69SBart Van Assche sgdevice24 233*44704f69SBart Van Assche if [ $repdevstat = 0 ]; then 234*44704f69SBart Van Assche echo "scsi report-devs 0" >/proc/scsi/scsi 235*44704f69SBart Van Assche fi 236*44704f69SBart Van Assche fi 237*44704f69SBart Van Assche} 238*44704f69SBart Van Assche 239*44704f69SBart Van Assche# Whether or not the RMB (removable) bit has been set in the INQUIRY response. 240*44704f69SBart Van Assche# Uses ${host}, ${channel}, ${id} and ${lun}. Assumes that sg_device() has 241*44704f69SBart Van Assche# already been called. How to test this function: copy/paste this function 242*44704f69SBart Van Assche# in a shell and run 243*44704f69SBart Van Assche# (cd /sys/class/scsi_device && for d in *; do set ${d//:/ }; echo -n "$d $(</sys/class/scsi_device/${d}/device/block/*/removable) <> "; SGDEV=bsg/$d host=$1 channel=$2 id=$3 lun=$4 is_removable; done) 244*44704f69SBart Van Asscheis_removable () 245*44704f69SBart Van Assche{ 246*44704f69SBart Van Assche local b p 247*44704f69SBart Van Assche 248*44704f69SBart Van Assche p=/sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device/inquiry 249*44704f69SBart Van Assche # Extract the second byte of the INQUIRY response and check bit 7 (mask 0x80). 250*44704f69SBart Van Assche b=$(hexdump -n1 -e '/1 "%02X"' "$p" 2>/dev/null) 251*44704f69SBart Van Assche if [ -n "$b" ]; then 252*44704f69SBart Van Assche echo $(((0x$b & 0x80) != 0)) 253*44704f69SBart Van Assche else 254*44704f69SBart Van Assche sg_inq /dev/$SGDEV 2>/dev/null | sed -n 's/^.*RMB=\([0-9]*\).*$/\1/p' 255*44704f69SBart Van Assche fi 256*44704f69SBart Van Assche} 257*44704f69SBart Van Assche 258*44704f69SBart Van Assche# Test if SCSI device is still responding to commands 259*44704f69SBart Van Assche# Return values: 260*44704f69SBart Van Assche# 0 device is present 261*44704f69SBart Van Assche# 1 device has changed 262*44704f69SBart Van Assche# 2 device has been removed 263*44704f69SBart Van Asschetestonline () 264*44704f69SBart Van Assche{ 265*44704f69SBart Van Assche local ctr RC RMB 266*44704f69SBart Van Assche 267*44704f69SBart Van Assche : testonline 268*44704f69SBart Van Assche ctr=0 269*44704f69SBart Van Assche RC=0 270*44704f69SBart Van Assche # Set default values 271*44704f69SBart Van Assche IPTYPE=31 272*44704f69SBart Van Assche IPQUAL=3 273*44704f69SBart Van Assche [ ! -x /usr/bin/sg_turs ] && return 0 274*44704f69SBart Van Assche sgdevice 275*44704f69SBart Van Assche [ -z "$SGDEV" ] && return 0 276*44704f69SBart Van Assche sg_turs /dev/$SGDEV >/dev/null 2>&1 277*44704f69SBart Van Assche RC=$? 278*44704f69SBart Van Assche 279*44704f69SBart Van Assche # Handle in progress of becoming ready and unit attention 280*44704f69SBart Van Assche while [ $RC = 2 -o $RC = 6 ] && [ $ctr -lt $timeout ] ; do 281*44704f69SBart Van Assche if [ $RC = 2 ] && [ "$RMB" != "1" ] && sg_inq /dev/$SGDEV | grep -q -i "PQual=0" ; then 282*44704f69SBart Van Assche echo -n "." 283*44704f69SBart Van Assche let LN+=1 284*44704f69SBart Van Assche sleep 1 285*44704f69SBart Van Assche else 286*44704f69SBart Van Assche sleep 0.02 287*44704f69SBart Van Assche fi 288*44704f69SBart Van Assche let ctr+=1 289*44704f69SBart Van Assche sg_turs /dev/$SGDEV >/dev/null 2>&1 290*44704f69SBart Van Assche RC=$? 291*44704f69SBart Van Assche # Check for removable device; TEST UNIT READY obviously will 292*44704f69SBart Van Assche # fail for a removable device with no medium 293*44704f69SBart Van Assche RMB=$(is_removable) 294*44704f69SBart Van Assche print_and_scroll_back "$host:$channel:$id:$lun $SGDEV ($RMB) " 295*44704f69SBart Van Assche [ $RC = 2 ] && [ "$RMB" = "1" ] && break 296*44704f69SBart Van Assche done 297*44704f69SBart Van Assche if [ $ctr != 0 ] ; then 298*44704f69SBart Van Assche white_out 299*44704f69SBart Van Assche fi 300*44704f69SBart Van Assche # echo -e "\e[A\e[A\e[A${yellow}Test existence of $SGDEV = $RC ${norm} \n\n\n" 301*44704f69SBart Van Assche [ $RC = 1 ] && return $RC 302*44704f69SBart Van Assche # Reset RC (might be !=0 for passive paths) 303*44704f69SBart Van Assche RC=0 304*44704f69SBart Van Assche # OK, device online, compare INQUIRY string 305*44704f69SBart Van Assche INQ=$(sg_inq "$sg_len_arg" /dev/$SGDEV 2>/dev/null) 306*44704f69SBart Van Assche if [ -z "$INQ" ] ; then 307*44704f69SBart Van Assche echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}INQUIRY failed${norm} \n\n\n" 308*44704f69SBart Van Assche return 2 309*44704f69SBart Van Assche fi 310*44704f69SBart Van Assche IVEND=$(echo "$INQ" | grep 'Vendor identification:' | sed 's/^[^:]*: \(.*\)$/\1/') 311*44704f69SBart Van Assche IPROD=$(echo "$INQ" | grep 'Product identification:' | sed 's/^[^:]*: \(.*\)$/\1/') 312*44704f69SBart Van Assche IPREV=$(echo "$INQ" | grep 'Product revision level:' | sed 's/^[^:]*: \(.*\)$/\1/') 313*44704f69SBart Van Assche STR=$(printf " Vendor: %-08s Model: %-16s Rev: %-4s" "$IVEND" "$IPROD" "$IPREV") 314*44704f69SBart Van Assche IPTYPE=$(echo "$INQ" | sed -n 's/.* Device_type=\([0-9]*\) .*/\1/p') 315*44704f69SBart Van Assche if [ -z "$IPTYPE" ]; then 316*44704f69SBart Van Assche IPTYPE=$(echo "$INQ" | sed -n 's/.* PDT=\([0-9]*\) .*/\1/p') 317*44704f69SBart Van Assche fi 318*44704f69SBart Van Assche IPQUAL=$(echo "$INQ" | sed -n 's/ *PQual=\([0-9]*\) Device.*/\1/p') 319*44704f69SBart Van Assche if [ -z "$IPQUAL" ] ; then 320*44704f69SBart Van Assche IPQUAL=$(echo "$INQ" | sed -n 's/ *PQual=\([0-9]*\) PDT.*/\1/p') 321*44704f69SBart Van Assche fi 322*44704f69SBart Van Assche if [ "$IPQUAL" != 0 ] ; then 323*44704f69SBart Van Assche [ -z "$IPQUAL" ] && IPQUAL=3 324*44704f69SBart Van Assche [ -z "$IPTYPE" ] && IPTYPE=31 325*44704f69SBart Van Assche echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}LU not available (PQual $IPQUAL)${norm} \n\n\n" 326*44704f69SBart Van Assche return 2 327*44704f69SBart Van Assche fi 328*44704f69SBart Van Assche 329*44704f69SBart Van Assche TYPE=$(printtype $IPTYPE) 330*44704f69SBart Van Assche if ! procscsiscsi ; then 331*44704f69SBart Van Assche echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV removed. ${norm}\n\n\n" 332*44704f69SBart Van Assche return 2 333*44704f69SBart Van Assche fi 334*44704f69SBart Van Assche TMPSTR=$(echo "$SCSISTR" | grep 'Vendor:') 335*44704f69SBart Van Assche if [ "$ignore_rev" -eq 0 ] ; then 336*44704f69SBart Van Assche if [ "$TMPSTR" != "$STR" ]; then 337*44704f69SBart Van Assche echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}\nfrom:${SCSISTR#* } \nto: $STR ${norm} \n\n\n" 338*44704f69SBart Van Assche return 1 339*44704f69SBart Van Assche fi 340*44704f69SBart Van Assche else 341*44704f69SBart Van Assche # Ignore disk revision change 342*44704f69SBart Van Assche local old_str_no_rev= 343*44704f69SBart Van Assche local new_str_no_rev= 344*44704f69SBart Van Assche 345*44704f69SBart Van Assche old_str_no_rev=${TMPSTR%Rev:*} 346*44704f69SBart Van Assche new_str_no_rev=${STR%Rev:*} 347*44704f69SBart Van Assche if [ "$old_str_no_rev" != "$new_str_no_rev" ]; then 348*44704f69SBart Van Assche echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}\nfrom:${SCSISTR#* } \nto: $STR ${norm} \n\n\n" 349*44704f69SBart Van Assche return 1 350*44704f69SBart Van Assche fi 351*44704f69SBart Van Assche fi 352*44704f69SBart Van Assche TMPSTR=$(echo "$SCSISTR" | sed -n 's/.*Type: *\(.*\) *ANSI.*/\1/p' | sed 's/ *$//g') 353*44704f69SBart Van Assche if [ "$TMPSTR" != "$TYPE" ] ; then 354*44704f69SBart Van Assche echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}\nfrom:${TMPSTR} \nto: $TYPE ${norm} \n\n\n" 355*44704f69SBart Van Assche return 1 356*44704f69SBart Van Assche fi 357*44704f69SBart Van Assche return $RC 358*44704f69SBart Van Assche} 359*44704f69SBart Van Assche 360*44704f69SBart Van Assche# Test if SCSI device $host $channel $id $lun exists 361*44704f69SBart Van Assche# Outputs description from /proc/scsi/scsi (unless arg passed) 362*44704f69SBart Van Assche# Returns SCSISTR (empty if no dev) 363*44704f69SBart Van Asschetestexist () 364*44704f69SBart Van Assche{ 365*44704f69SBart Van Assche : testexist 366*44704f69SBart Van Assche SCSISTR= 367*44704f69SBart Van Assche if procscsiscsi && [ -z "$1" ] ; then 368*44704f69SBart Van Assche echo "$SCSISTR" | head -n1 369*44704f69SBart Van Assche echo "$SCSISTR" | tail -n2 | pr -o4 -l1 370*44704f69SBart Van Assche fi 371*44704f69SBart Van Assche} 372*44704f69SBart Van Assche 373*44704f69SBart Van Assche# Returns the list of existing channels per host 374*44704f69SBart Van Asschechanlist () 375*44704f69SBart Van Assche{ 376*44704f69SBart Van Assche local hcil 377*44704f69SBart Van Assche local cil 378*44704f69SBart Van Assche local chan 379*44704f69SBart Van Assche local tmpchan 380*44704f69SBart Van Assche 381*44704f69SBart Van Assche for dev in /sys/class/scsi_device/${host}:* ; do 382*44704f69SBart Van Assche [ -d "$dev" ] || continue; 383*44704f69SBart Van Assche hcil=${dev##*/} 384*44704f69SBart Van Assche cil=${hcil#*:} 385*44704f69SBart Van Assche chan=${cil%%:*} 386*44704f69SBart Van Assche for tmpchan in $channelsearch ; do 387*44704f69SBart Van Assche if [ "$chan" -eq "$tmpchan" ] ; then 388*44704f69SBart Van Assche chan= 389*44704f69SBart Van Assche fi 390*44704f69SBart Van Assche done 391*44704f69SBart Van Assche if [ -n "$chan" ] ; then 392*44704f69SBart Van Assche channelsearch="$channelsearch $chan" 393*44704f69SBart Van Assche fi 394*44704f69SBart Van Assche done 395*44704f69SBart Van Assche if [ -z "$channelsearch" ] ; then 396*44704f69SBart Van Assche channelsearch="0" 397*44704f69SBart Van Assche fi 398*44704f69SBart Van Assche} 399*44704f69SBart Van Assche 400*44704f69SBart Van Assche# Returns the list of existing targets per host 401*44704f69SBart Van Asscheidlist () 402*44704f69SBart Van Assche{ 403*44704f69SBart Van Assche local tmpid 404*44704f69SBart Van Assche local newid 405*44704f69SBart Van Assche local oldid 406*44704f69SBart Van Assche 407*44704f69SBart Van Assche oldlist=$(find /sys/class/scsi_device -name "${host}:${channel}:*" -printf "%f\n") 408*44704f69SBart Van Assche # Rescan LUN 0 to check if we found new targets 409*44704f69SBart Van Assche echo "${channel} - -" > "/sys/class/scsi_host/host${host}/scan" 410*44704f69SBart Van Assche newlist=$(find /sys/class/scsi_device -name "${host}:${channel}:*" -printf "%f\n") 411*44704f69SBart Van Assche for newid in $newlist ; do 412*44704f69SBart Van Assche oldid=$newid 413*44704f69SBart Van Assche for tmpid in $oldlist ; do 414*44704f69SBart Van Assche if [ "$newid" = "$tmpid" ] ; then 415*44704f69SBart Van Assche oldid= 416*44704f69SBart Van Assche break 417*44704f69SBart Van Assche fi 418*44704f69SBart Van Assche done 419*44704f69SBart Van Assche if [ -n "$oldid" ] ; then 420*44704f69SBart Van Assche if [ -d /sys/class/scsi_device/$oldid ] ; then 421*44704f69SBart Van Assche hcil=${oldid} 422*44704f69SBart Van Assche printf "\r${green}NEW: %s ${norm}" 423*44704f69SBart Van Assche testexist 424*44704f69SBart Van Assche if [ "$SCSISTR" ] ; then 425*44704f69SBart Van Assche incrfound "$hcil" 426*44704f69SBart Van Assche fi 427*44704f69SBart Van Assche fi 428*44704f69SBart Van Assche fi 429*44704f69SBart Van Assche done 430*44704f69SBart Van Assche idsearch=$(find /sys/bus/scsi/devices -name "target${host}:${channel}:*" -printf "%f\n" | cut -f 3 -d :) 431*44704f69SBart Van Assche} 432*44704f69SBart Van Assche 433*44704f69SBart Van Assche# Returns the list of existing LUNs from device $host $channel $id $lun 434*44704f69SBart Van Assche# and returns list to stdout 435*44704f69SBart Van Asschegetluns() 436*44704f69SBart Van Assche{ 437*44704f69SBart Van Assche sgdevice 438*44704f69SBart Van Assche [ -z "$SGDEV" ] && return 1 439*44704f69SBart Van Assche if [ ! -x /usr/bin/sg_luns ] ; then 440*44704f69SBart Van Assche echo 0 441*44704f69SBart Van Assche return 1 442*44704f69SBart Van Assche fi 443*44704f69SBart Van Assche LLUN=$(sg_luns /dev/$SGDEV 2>/dev/null | sed -n 's/ \(.*\)/\1/p') 444*44704f69SBart Van Assche # Added -z $LLUN condition because $? gets the RC from sed, not sg_luns 445*44704f69SBart Van Assche if [ $? -ne 0 ] || [ -z "$LLUN" ] ; then 446*44704f69SBart Van Assche echo 0 447*44704f69SBart Van Assche return 1 448*44704f69SBart Van Assche fi 449*44704f69SBart Van Assche for lun in $LLUN ; do 450*44704f69SBart Van Assche # Swap LUN number 451*44704f69SBart Van Assche l0=0x$lun 452*44704f69SBart Van Assche l1=$(( (l0 >> 48) & 0xffff )) 453*44704f69SBart Van Assche l2=$(( (l0 >> 32) & 0xffff )) 454*44704f69SBart Van Assche l3=$(( (l0 >> 16) & 0xffff )) 455*44704f69SBart Van Assche l4=$(( l0 & 0xffff )) 456*44704f69SBart Van Assche l0=$(( ( ( (l4 * 0xffff) + l3 ) * 0xffff + l2 ) * 0xffff + l1 )) 457*44704f69SBart Van Assche printf "%u\n" $l0 458*44704f69SBart Van Assche done 459*44704f69SBart Van Assche return 0 460*44704f69SBart Van Assche} 461*44704f69SBart Van Assche 462*44704f69SBart Van Assche# Wait for udev to settle (create device nodes etc.) 463*44704f69SBart Van Asscheudevadm_settle() 464*44704f69SBart Van Assche{ 465*44704f69SBart Van Assche local tmo=60 466*44704f69SBart Van Assche if [ -x /sbin/udevadm ] ; then 467*44704f69SBart Van Assche print_and_scroll_back " Calling udevadm settle (can take a while) " 468*44704f69SBart Van Assche # Loop for up to 60 seconds if sd devices still are settling.. 469*44704f69SBart Van Assche # This allows us to continue if udev events are stuck on multipaths in recovery mode 470*44704f69SBart Van Assche while [ $tmo -gt 0 ] ; do 471*44704f69SBart Van Assche if ! /sbin/udevadm settle --timeout=1 | egrep -q sd[a-z]+ ; then 472*44704f69SBart Van Assche break; 473*44704f69SBart Van Assche fi 474*44704f69SBart Van Assche let tmo=$tmo-1 475*44704f69SBart Van Assche done 476*44704f69SBart Van Assche white_out 477*44704f69SBart Van Assche elif [ -x /sbin/udevsettle ] ; then 478*44704f69SBart Van Assche print_and_scroll_back " Calling udevsettle (can take a while) " 479*44704f69SBart Van Assche /sbin/udevsettle 480*44704f69SBart Van Assche white_out 481*44704f69SBart Van Assche else 482*44704f69SBart Van Assche sleep 0.02 483*44704f69SBart Van Assche fi 484*44704f69SBart Van Assche} 485*44704f69SBart Van Assche 486*44704f69SBart Van Assche# Perform scan on a single lun $host $channel $id $lun 487*44704f69SBart Van Asschedolunscan() 488*44704f69SBart Van Assche{ 489*44704f69SBart Van Assche local remappedlun0= 490*44704f69SBart Van Assche local devpath 491*44704f69SBart Van Assche SCSISTR= 492*44704f69SBart Van Assche devnr="$host $channel $id $lun" 493*44704f69SBart Van Assche echo -e " Scanning for device $devnr ... " 494*44704f69SBart Van Assche printf "${yellow}OLD: %s ${norm}" 495*44704f69SBart Van Assche testexist 496*44704f69SBart Van Assche # Device exists: Test whether it's still online 497*44704f69SBart Van Assche # (testonline returns 2 if it's gone and 1 if it has changed) 498*44704f69SBart Van Assche devpath="/sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device" 499*44704f69SBart Van Assche if [ "$SCSISTR" ] ; then 500*44704f69SBart Van Assche testonline 501*44704f69SBart Van Assche RC=$? 502*44704f69SBart Van Assche # Well known lun transition case. Only for Direct-Access devs (type 0) 503*44704f69SBart Van Assche # If block directory exists && and PQUAL != 0, we unmapped lun0 and just have a well-known lun 504*44704f69SBart Van Assche # If block directory doesn't exist && PQUAL == 0, we mapped a real lun0 505*44704f69SBart Van Assche if [ "$lun" -eq 0 ] && [ $IPTYPE -eq 0 ] ; then 506*44704f69SBart Van Assche if [ $RC = 2 ] ; then 507*44704f69SBart Van Assche if [ -e "$devpath" ] ; then 508*44704f69SBart Van Assche if [ -d "$devpath/block" ] ; then 509*44704f69SBart Van Assche remappedlun0=2 # Transition from real lun 0 to well-known 510*44704f69SBart Van Assche else 511*44704f69SBart Van Assche RC=0 # Set this so the system leaves the existing well known lun alone. This is a lun 0 with no block directory 512*44704f69SBart Van Assche fi 513*44704f69SBart Van Assche fi 514*44704f69SBart Van Assche elif [ $RC = 0 ] && [ $IPTYPE -eq 0 ] ; then 515*44704f69SBart Van Assche if [ -e "$devpath" ] ; then 516*44704f69SBart Van Assche if [ ! -d "$devpath/block" ] ; then 517*44704f69SBart Van Assche remappedlun0=1 # Transition from well-known to real lun 0 518*44704f69SBart Van Assche fi 519*44704f69SBart Van Assche fi 520*44704f69SBart Van Assche fi 521*44704f69SBart Van Assche fi 522*44704f69SBart Van Assche fi 523*44704f69SBart Van Assche 524*44704f69SBart Van Assche # Special case: lun 0 just got added (for reportlunscan), 525*44704f69SBart Van Assche # so make sure we correctly treat it as new 526*44704f69SBart Van Assche if [ "$lun" = "0" ] && [ "$1" = "1" ] && [ -z "$remappedlun0" ] ; then 527*44704f69SBart Van Assche SCSISTR="" 528*44704f69SBart Van Assche printf "\r\e[A\e[A\e[A" 529*44704f69SBart Van Assche fi 530*44704f69SBart Van Assche 531*44704f69SBart Van Assche : f "$remove" s $SCSISTR 532*44704f69SBart Van Assche if [ "$remove" ] && [ "$SCSISTR" -o "$remappedlun0" = "1" ] ; then 533*44704f69SBart Van Assche if [ $RC != 0 ] || [ ! -z "$forceremove" ] || [ -n "$remappedlun0" ] ; then 534*44704f69SBart Van Assche if [ "$remappedlun0" != "1" ] ; then 535*44704f69SBart Van Assche echo -en "\r\e[A\e[A\e[A${red}REM: " 536*44704f69SBart Van Assche echo "$SCSISTR" | head -n1 537*44704f69SBart Van Assche echo -e "${norm}\e[B\e[B" 538*44704f69SBart Van Assche fi 539*44704f69SBart Van Assche if [ -e "$devpath" ] ; then 540*44704f69SBart Van Assche # have to preemptively do this so we can figure out the mpath device 541*44704f69SBart Van Assche # Don't do this if we're deleting a well known lun to replace it 542*44704f69SBart Van Assche if [ "$remappedlun0" != "1" ] ; then 543*44704f69SBart Van Assche incrrmvd "$host:$channel:$id:$lun" 544*44704f69SBart Van Assche fi 545*44704f69SBart Van Assche echo 1 > "$devpath/delete" 546*44704f69SBart Van Assche sleep 0.02 547*44704f69SBart Van Assche else 548*44704f69SBart Van Assche echo "scsi remove-single-device $devnr" > /proc/scsi/scsi 549*44704f69SBart Van Assche if [ $RC -eq 1 ] || [ "$lun" -eq 0 ] ; then 550*44704f69SBart Van Assche # Try readding, should fail if device is gone 551*44704f69SBart Van Assche echo "scsi add-single-device $devnr" > /proc/scsi/scsi 552*44704f69SBart Van Assche fi 553*44704f69SBart Van Assche fi 554*44704f69SBart Van Assche fi 555*44704f69SBart Van Assche if [ $RC = 0 ] || [ "$forcerescan" ] ; then 556*44704f69SBart Van Assche if [ -e "$devpath" ] ; then 557*44704f69SBart Van Assche echo 1 > "$devpath/rescan" 558*44704f69SBart Van Assche fi 559*44704f69SBart Van Assche fi 560*44704f69SBart Van Assche printf "\r\e[A\e[A\e[A${yellow}OLD: %s ${norm}" 561*44704f69SBart Van Assche testexist 562*44704f69SBart Van Assche if [ -z "$SCSISTR" ] && [ $RC != 1 ] && [ "$remappedlun0" != "1" ] ; then 563*44704f69SBart Van Assche printf "\r${red}DEL: %s\r\n\n ${norm}" 564*44704f69SBart Van Assche # In the event we're replacing with a well known node, we need to let it continue, to create the replacement node 565*44704f69SBart Van Assche [ "$remappedlun0" != "2" ] && return 2 566*44704f69SBart Van Assche fi 567*44704f69SBart Van Assche fi 568*44704f69SBart Van Assche if [ -z "$SCSISTR" ] || [ -n "$remappedlun0" ] ; then 569*44704f69SBart Van Assche if [ "$remappedlun0" != "2" ] ; then 570*44704f69SBart Van Assche # Device does not exist, try to add 571*44704f69SBart Van Assche printf "\r${green}NEW: %s ${norm}" 572*44704f69SBart Van Assche fi 573*44704f69SBart Van Assche if [ -e "/sys/class/scsi_host/host${host}/scan" ] ; then 574*44704f69SBart Van Assche echo "$channel $id $lun" > "/sys/class/scsi_host/host${host}/scan" 2> /dev/null 575*44704f69SBart Van Assche else 576*44704f69SBart Van Assche echo "scsi add-single-device $devnr" > /proc/scsi/scsi 577*44704f69SBart Van Assche fi 578*44704f69SBart Van Assche testexist 579*44704f69SBart Van Assche if [ -z "$SCSISTR" ] ; then 580*44704f69SBart Van Assche # Device not present 581*44704f69SBart Van Assche printf "\r\e[A"; 582*44704f69SBart Van Assche # Optimization: if lun==0, stop here (only if in non-remove mode) 583*44704f69SBart Van Assche if [ "$lun" = 0 ] && [ -z "$remove" ] && [ "$optscan" = 1 ] ; then 584*44704f69SBart Van Assche return 1; 585*44704f69SBart Van Assche fi 586*44704f69SBart Van Assche else 587*44704f69SBart Van Assche if [ "$remappedlun0" != "2" ] ; then 588*44704f69SBart Van Assche incrfound "$host:$channel:$id:$lun" 589*44704f69SBart Van Assche fi 590*44704f69SBart Van Assche fi 591*44704f69SBart Van Assche fi 592*44704f69SBart Van Assche return 0; 593*44704f69SBart Van Assche} 594*44704f69SBart Van Assche 595*44704f69SBart Van Assche# Perform report lun scan on $host $channel $id using REPORT_LUNS 596*44704f69SBart Van Asschedoreportlun() 597*44704f69SBart Van Assche{ 598*44704f69SBart Van Assche lun=0 599*44704f69SBart Van Assche SCSISTR= 600*44704f69SBart Van Assche devnr="$host $channel $id $lun" 601*44704f69SBart Van Assche echo -en " Scanning for device $devnr ...\r" 602*44704f69SBart Van Assche lun0added= 603*44704f69SBart Van Assche #printf "${yellow}OLD: %s ${norm}" 604*44704f69SBart Van Assche # Phase one: If LUN0 does not exist, try to add 605*44704f69SBart Van Assche testexist -q 606*44704f69SBart Van Assche if [ -z "$SCSISTR" ] ; then 607*44704f69SBart Van Assche # Device does not exist, try to add 608*44704f69SBart Van Assche #printf "\r${green}NEW: %s ${norm}" 609*44704f69SBart Van Assche if [ -e "/sys/class/scsi_host/host${host}/scan" ] ; then 610*44704f69SBart Van Assche echo "$channel $id $lun" > "/sys/class/scsi_host/host${host}/scan" 2> /dev/null 611*44704f69SBart Van Assche udevadm_settle 612*44704f69SBart Van Assche else 613*44704f69SBart Van Assche echo "scsi add-single-device $devnr" > /proc/scsi/scsi 614*44704f69SBart Van Assche fi 615*44704f69SBart Van Assche testexist -q 616*44704f69SBart Van Assche if [ -n "$SCSISTR" ] ; then 617*44704f69SBart Van Assche lun0added=1 618*44704f69SBart Van Assche #testonline 619*44704f69SBart Van Assche else 620*44704f69SBart Van Assche # Device not present 621*44704f69SBart Van Assche # return 622*44704f69SBart Van Assche # Find alternative LUN to send getluns to 623*44704f69SBart Van Assche for dev in /sys/class/scsi_device/${host}:${channel}:${id}:*; do 624*44704f69SBart Van Assche [ -d "$dev" ] || continue 625*44704f69SBart Van Assche lun=${dev##*:} 626*44704f69SBart Van Assche break 627*44704f69SBart Van Assche done 628*44704f69SBart Van Assche fi 629*44704f69SBart Van Assche fi 630*44704f69SBart Van Assche targetluns=$(getluns) 631*44704f69SBart Van Assche REPLUNSTAT=$? 632*44704f69SBart Van Assche lunremove= 633*44704f69SBart Van Assche #echo "getluns reports " $targetluns 634*44704f69SBart Van Assche olddev=$(find /sys/class/scsi_device/ -name "$host:$channel:$id:*" 2>/dev/null | sort -t: -k4 -n) 635*44704f69SBart Van Assche oldtargets="$targetluns" 636*44704f69SBart Van Assche # OK -- if we don't have a LUN to send a REPORT_LUNS to, we could 637*44704f69SBart Van Assche # fall back to wildcard scanning. Same thing if the device does not 638*44704f69SBart Van Assche # support REPORT_LUNS 639*44704f69SBart Van Assche # TODO: We might be better off to ALWAYS use wildcard scanning if 640*44704f69SBart Van Assche # it works 641*44704f69SBart Van Assche if [ "$REPLUNSTAT" = "1" ] ; then 642*44704f69SBart Van Assche if [ -e "/sys/class/scsi_host/host${host}/scan" ] ; then 643*44704f69SBart Van Assche echo "$channel $id -" > "/sys/class/scsi_host/host${host}/scan" 2> /dev/null 644*44704f69SBart Van Assche udevadm_settle 645*44704f69SBart Van Assche else 646*44704f69SBart Van Assche echo "scsi add-single-device $host $channel $id $SCAN_WILD_CARD" > /proc/scsi/scsi 647*44704f69SBart Van Assche fi 648*44704f69SBart Van Assche targetluns=$(find /sys/class/scsi_device/ -name "$host:$channel:$id:*" -printf "%f\n" | cut -d : -f 4) 649*44704f69SBart Van Assche let found+=$(echo "$targetluns" | wc -l) 650*44704f69SBart Van Assche let found-=$(echo "$olddev" | wc -l) 651*44704f69SBart Van Assche fi 652*44704f69SBart Van Assche [ -z "$targetluns" ] && targetluns="$oldtargets" 653*44704f69SBart Van Assche # Check existing luns 654*44704f69SBart Van Assche for dev in $olddev; do 655*44704f69SBart Van Assche [ -d "$dev" ] || continue 656*44704f69SBart Van Assche lun=${dev##*:} 657*44704f69SBart Van Assche newsearch= 658*44704f69SBart Van Assche inlist= 659*44704f69SBart Van Assche # OK, is existing $lun (still) in reported list 660*44704f69SBart Van Assche for tmplun in $targetluns; do 661*44704f69SBart Van Assche if [ "$tmplun" = "$lun" ] ; then 662*44704f69SBart Van Assche inlist=1 663*44704f69SBart Van Assche dolunscan $lun0added 664*44704f69SBart Van Assche [ $? -eq 1 ] && break 665*44704f69SBart Van Assche else 666*44704f69SBart Van Assche newsearch="$newsearch $tmplun" 667*44704f69SBart Van Assche fi 668*44704f69SBart Van Assche done 669*44704f69SBart Van Assche # OK, we have now done a lunscan on $lun and 670*44704f69SBart Van Assche # $newsearch is the old $targetluns without $lun 671*44704f69SBart Van Assche if [ -z "$inlist" ]; then 672*44704f69SBart Van Assche # Stale lun 673*44704f69SBart Van Assche lunremove="$lunremove $lun" 674*44704f69SBart Van Assche fi 675*44704f69SBart Van Assche # $lun removed from $lunsearch 676*44704f69SBart Van Assche targetluns=${newsearch# } 677*44704f69SBart Van Assche done 678*44704f69SBart Van Assche # Add new ones and check stale ones 679*44704f69SBart Van Assche for lun in $targetluns $lunremove; do 680*44704f69SBart Van Assche dolunscan $lun0added 681*44704f69SBart Van Assche [ $? -eq 1 ] && break 682*44704f69SBart Van Assche done 683*44704f69SBart Van Assche} 684*44704f69SBart Van Assche 685*44704f69SBart Van Assche# Perform search (scan $host) 686*44704f69SBart Van Asschedosearch () 687*44704f69SBart Van Assche{ 688*44704f69SBart Van Assche if [ -z "$channelsearch" ] ; then 689*44704f69SBart Van Assche chanlist 690*44704f69SBart Van Assche fi 691*44704f69SBart Van Assche for channel in $channelsearch; do 692*44704f69SBart Van Assche if [ -z "$idsearch" ] ; then 693*44704f69SBart Van Assche if [ -z "$lunsearch" ] ; then 694*44704f69SBart Van Assche idlist 695*44704f69SBart Van Assche else 696*44704f69SBart Van Assche idsearch=$(find /sys/bus/scsi/devices -name "target${host}:${channel}:*" -printf "%f\n" | cut -f 3 -d :) 697*44704f69SBart Van Assche fi 698*44704f69SBart Van Assche fi 699*44704f69SBart Van Assche for id in $idsearch; do 700*44704f69SBart Van Assche if [ -z "$lunsearch" ] ; then 701*44704f69SBart Van Assche doreportlun 702*44704f69SBart Van Assche else 703*44704f69SBart Van Assche for lun in $lunsearch; do 704*44704f69SBart Van Assche dolunscan 705*44704f69SBart Van Assche [ $? -eq 1 ] && break 706*44704f69SBart Van Assche done 707*44704f69SBart Van Assche fi 708*44704f69SBart Van Assche done 709*44704f69SBart Van Assche done 710*44704f69SBart Van Assche} 711*44704f69SBart Van Assche 712*44704f69SBart Van Asscheexpandlist () 713*44704f69SBart Van Assche{ 714*44704f69SBart Van Assche list=$1 715*44704f69SBart Van Assche result="" 716*44704f69SBart Van Assche first=${list%%,*} 717*44704f69SBart Van Assche rest=${list#*,} 718*44704f69SBart Van Assche while [ ! -z "$first" ] ; do 719*44704f69SBart Van Assche beg=${first%%-*}; 720*44704f69SBart Van Assche if [ "$beg" = "$first" ] ; then 721*44704f69SBart Van Assche result="$result $beg"; 722*44704f69SBart Van Assche else 723*44704f69SBart Van Assche end=${first#*-} 724*44704f69SBart Van Assche result="$result $(seq -s ' ' $beg $end)" 725*44704f69SBart Van Assche fi 726*44704f69SBart Van Assche [ "$rest" = "$first" ] && rest="" 727*44704f69SBart Van Assche first=${rest%%,*} 728*44704f69SBart Van Assche rest=${rest#*,} 729*44704f69SBart Van Assche done 730*44704f69SBart Van Assche echo "$result" 731*44704f69SBart Van Assche} 732*44704f69SBart Van Assche 733*44704f69SBart Van Asschesearchexisting() 734*44704f69SBart Van Assche{ 735*44704f69SBart Van Assche local tmpch; 736*44704f69SBart Van Assche local tmpid 737*44704f69SBart Van Assche local match=0 738*44704f69SBart Van Assche local targets= 739*44704f69SBart Van Assche 740*44704f69SBart Van Assche targets=$(find /sys/bus/scsi/devices -name "target${host}:*" -printf "%f\n" | cut -d : -f 2-3) 741*44704f69SBart Van Assche # Nothing came back on this host, so we should skip it 742*44704f69SBart Van Assche [ -z "$targets" ] && return 743*44704f69SBart Van Assche 744*44704f69SBart Van Assche local target=; 745*44704f69SBart Van Assche for target in $targets ; do 746*44704f69SBart Van Assche channel=${target%:*} 747*44704f69SBart Van Assche id=${target#*:} 748*44704f69SBart Van Assche if [ -n "$channelsearch" ] ; then 749*44704f69SBart Van Assche for tmpch in $channelsearch ; do 750*44704f69SBart Van Assche [ $tmpch -eq "$channel" ] && match=1 751*44704f69SBart Van Assche done 752*44704f69SBart Van Assche else 753*44704f69SBart Van Assche match=1 754*44704f69SBart Van Assche fi 755*44704f69SBart Van Assche 756*44704f69SBart Van Assche [ $match -eq 0 ] && continue 757*44704f69SBart Van Assche match=0 758*44704f69SBart Van Assche 759*44704f69SBart Van Assche if [ "$filter_ids" -eq 1 ] ; then 760*44704f69SBart Van Assche for tmpid in $idsearch ; do 761*44704f69SBart Van Assche if [ "$tmpid" = "$id" ] ; then 762*44704f69SBart Van Assche match=1 763*44704f69SBart Van Assche fi 764*44704f69SBart Van Assche done 765*44704f69SBart Van Assche else 766*44704f69SBart Van Assche match=1 767*44704f69SBart Van Assche fi 768*44704f69SBart Van Assche 769*44704f69SBart Van Assche [ $match -eq 0 ] && continue 770*44704f69SBart Van Assche 771*44704f69SBart Van Assche if [ -z "$lunsearch" ] ; then 772*44704f69SBart Van Assche doreportlun 773*44704f69SBart Van Assche else 774*44704f69SBart Van Assche for lun in $lunsearch ; do 775*44704f69SBart Van Assche dolunscan 776*44704f69SBart Van Assche [ $? -eq 1 ] && break 777*44704f69SBart Van Assche done 778*44704f69SBart Van Assche fi 779*44704f69SBart Van Assche done 780*44704f69SBart Van Assche} 781*44704f69SBart Van Assche 782*44704f69SBart Van Asschegetallmultipathinfo() 783*44704f69SBart Van Assche{ 784*44704f69SBart Van Assche local mp= 785*44704f69SBart Van Assche local uuid= 786*44704f69SBart Van Assche local dmtmp= 787*44704f69SBart Van Assche local maj_min= 788*44704f69SBart Van Assche local tmpfile= 789*44704f69SBart Van Assche 790*44704f69SBart Van Assche truncate -s 0 $TMPLUNINFOFILE 791*44704f69SBart Van Assche for mp in $($DMSETUP ls --target=multipath | cut -f 1) ; do 792*44704f69SBart Van Assche [ "$mp" = "No" ] && break; 793*44704f69SBart Van Assche maj_min=$($DMSETUP status "$mp" | cut -d " " -f14) 794*44704f69SBart Van Assche if [ ! -L /dev/mapper/${mp} ]; then 795*44704f69SBart Van Assche echo "softlink /dev/mapper/${mp} not available." 796*44704f69SBart Van Assche continue 797*44704f69SBart Van Assche fi 798*44704f69SBart Van Assche local ret=$(readlink /dev/mapper/$mp 2>/dev/null) 799*44704f69SBart Van Assche if [[ $? -ne 0 || -z "$ret" ]]; then 800*44704f69SBart Van Assche echo "readlink /dev/mapper/$mp failed. check multipath status." 801*44704f69SBart Van Assche continue 802*44704f69SBart Van Assche fi 803*44704f69SBart Van Assche dmtmp=$(basename $ret) 804*44704f69SBart Van Assche uuid=$(cut -f2 -d- "/sys/block/$dmtmp/dm/uuid") 805*44704f69SBart Van Assche echo "$mp $maj_min $dmtmp $uuid" >> $TMPLUNINFOFILE 806*44704f69SBart Van Assche done 807*44704f69SBart Van Assche} 808*44704f69SBart Van Assche 809*44704f69SBart Van Assche# Go through all of the existing devices and figure out any that have been remapped 810*44704f69SBart Van Asschefindremapped() 811*44704f69SBart Van Assche{ 812*44704f69SBart Van Assche local hctl=; 813*44704f69SBart Van Assche local devs= 814*44704f69SBart Van Assche local sddev= 815*44704f69SBart Van Assche local id_serial= 816*44704f69SBart Van Assche local id_serial_old= 817*44704f69SBart Van Assche local remapped= 818*44704f69SBart Van Assche mpaths="" 819*44704f69SBart Van Assche local tmpfile= 820*44704f69SBart Van Assche 821*44704f69SBart Van Assche tmpfile=$(mktemp /tmp/rescan-scsi-bus.XXXXXXXX 2> /dev/null) 822*44704f69SBart Van Assche if [ -z "$tmpfile" ] ; then 823*44704f69SBart Van Assche tmpfile="/tmp/rescan-scsi-bus.$$" 824*44704f69SBart Van Assche rm -f $tmpfile 825*44704f69SBart Van Assche fi 826*44704f69SBart Van Assche 827*44704f69SBart Van Assche # Get all of the ID_SERIAL attributes, after finding their sd node 828*44704f69SBart Van Assche devs=$(ls /sys/class/scsi_device/) 829*44704f69SBart Van Assche for hctl in $devs ; do 830*44704f69SBart Van Assche if [ -d "/sys/class/scsi_device/$hctl/device/block" ] ; then 831*44704f69SBart Van Assche sddev=$(ls "/sys/class/scsi_device/$hctl/device/block") 832*44704f69SBart Van Assche id_serial_old=$(udevadm info -q all -n "$sddev" | grep "ID_SERIAL=" | cut -d"=" -f2) 833*44704f69SBart Van Assche [ -z "$id_serial_old" ] && id_serial_old="none" 834*44704f69SBart Van Assche echo "$hctl $sddev $id_serial_old" >> $tmpfile 835*44704f69SBart Van Assche fi 836*44704f69SBart Van Assche done 837*44704f69SBart Van Assche 838*44704f69SBart Van Assche # Trigger udev to update the info 839*44704f69SBart Van Assche echo -n "Triggering udev to update device information... " 840*44704f69SBart Van Assche /sbin/udevadm trigger 841*44704f69SBart Van Assche udevadm_settle 2>&1 /dev/null 842*44704f69SBart Van Assche echo "Done" 843*44704f69SBart Van Assche 844*44704f69SBart Van Assche getallmultipathinfo 845*44704f69SBart Van Assche 846*44704f69SBart Van Assche # See what changed and reload the respective multipath device if applicable 847*44704f69SBart Van Assche while read -r hctl sddev id_serial_old ; do 848*44704f69SBart Van Assche remapped=0 849*44704f69SBart Van Assche id_serial=$(udevadm info -q all -n "$sddev" | grep "ID_SERIAL=" | cut -d"=" -f2) 850*44704f69SBart Van Assche [ -z "$id_serial" ] && id_serial="none" 851*44704f69SBart Van Assche if [ "$id_serial_old" != "$id_serial" ] ; then 852*44704f69SBart Van Assche remapped=1 853*44704f69SBart Van Assche fi 854*44704f69SBart Van Assche # If udev events updated the disks already, but the multipath device isn't update 855*44704f69SBart Van Assche # check for old devices to make sure we found remapped luns 856*44704f69SBart Van Assche if [ -n "$mp_enable" ] && [ $remapped -eq 0 ]; then 857*44704f69SBart Van Assche findmultipath "$sddev" $id_serial 858*44704f69SBart Van Assche if [ $? -eq 1 ] ; then 859*44704f69SBart Van Assche remapped=1 860*44704f69SBart Van Assche fi 861*44704f69SBart Van Assche fi 862*44704f69SBart Van Assche 863*44704f69SBart Van Assche # if uuid is 1, it's unmapped, so we don't want to treat it as a remap 864*44704f69SBart Van Assche # if remapped flag is 0, just skip the rest of the logic 865*44704f69SBart Van Assche if [ "$id_serial" = "1" ] || [ $remapped -eq 0 ] ; then 866*44704f69SBart Van Assche continue 867*44704f69SBart Van Assche fi 868*44704f69SBart Van Assche printf "${yellow}REMAPPED: %s ${norm}" 869*44704f69SBart Van Assche host=$(echo "$hctl" | cut -d":" -f1) 870*44704f69SBart Van Assche channel=$(echo "$hctl" | cut -d":" -f2) 871*44704f69SBart Van Assche id=$(echo "$hctl" | cut -d":" -f3) 872*44704f69SBart Van Assche lun=$(echo "$hctl" | cut -d":" -f4) 873*44704f69SBart Van Assche procscsiscsi 874*44704f69SBart Van Assche echo "$SCSISTR" 875*44704f69SBart Van Assche incrchgd "$hctl" 876*44704f69SBart Van Assche done < $tmpfile 877*44704f69SBart Van Assche rm -f $tmpfile 878*44704f69SBart Van Assche 879*44704f69SBart Van Assche if [ -n "$mp_enable" ] && [ -n "$mpaths" ] ; then 880*44704f69SBart Van Assche echo "Updating multipath device mappings" 881*44704f69SBart Van Assche flushmpaths 882*44704f69SBart Van Assche $MULTIPATH | grep "create:" 2> /dev/null 883*44704f69SBart Van Assche fi 884*44704f69SBart Van Assche} 885*44704f69SBart Van Assche 886*44704f69SBart Van Asscheincrfound() 887*44704f69SBart Van Assche{ 888*44704f69SBart Van Assche local hctl="$1" 889*44704f69SBart Van Assche if [ -n "$hctl" ] ; then 890*44704f69SBart Van Assche let found+=1 891*44704f69SBart Van Assche FOUNDDEVS="$FOUNDDEVS\t[$hctl]\n" 892*44704f69SBart Van Assche else 893*44704f69SBart Van Assche return 894*44704f69SBart Van Assche fi 895*44704f69SBart Van Assche} 896*44704f69SBart Van Assche 897*44704f69SBart Van Asscheincrchgd() 898*44704f69SBart Van Assche{ 899*44704f69SBart Van Assche local hctl="$1" 900*44704f69SBart Van Assche if [ -n "$hctl" ] ; then 901*44704f69SBart Van Assche if ! echo "$CHGDEVS" | grep -q "\[$hctl\]"; then 902*44704f69SBart Van Assche let updated+=1 903*44704f69SBart Van Assche CHGDEVS="$CHGDEVS\t[$hctl]\n" 904*44704f69SBart Van Assche fi 905*44704f69SBart Van Assche else 906*44704f69SBart Van Assche return 907*44704f69SBart Van Assche fi 908*44704f69SBart Van Assche 909*44704f69SBart Van Assche if [ -n "$mp_enable" ] ; then 910*44704f69SBart Van Assche local sdev 911*44704f69SBart Van Assche 912*44704f69SBart Van Assche sdev=$(findsddev "$hctl") 913*44704f69SBart Van Assche if [ -n "$sdev" ] ; then 914*44704f69SBart Van Assche findmultipath "$sdev" 915*44704f69SBart Van Assche fi 916*44704f69SBart Van Assche fi 917*44704f69SBart Van Assche} 918*44704f69SBart Van Assche 919*44704f69SBart Van Asscheincrrmvd() 920*44704f69SBart Van Assche{ 921*44704f69SBart Van Assche local hctl="$1" 922*44704f69SBart Van Assche if [ -n "$hctl" ] ; then 923*44704f69SBart Van Assche let rmvd+=1; 924*44704f69SBart Van Assche RMVDDEVS="$RMVDDEVS\t[$hctl]\n" 925*44704f69SBart Van Assche else 926*44704f69SBart Van Assche return 927*44704f69SBart Van Assche fi 928*44704f69SBart Van Assche 929*44704f69SBart Van Assche if [ -n "$mp_enable" ] ; then 930*44704f69SBart Van Assche local sdev 931*44704f69SBart Van Assche 932*44704f69SBart Van Assche sdev=$(findsddev "$hctl") 933*44704f69SBart Van Assche if [ -n "$sdev" ] ; then 934*44704f69SBart Van Assche findmultipath "$sdev" 935*44704f69SBart Van Assche fi 936*44704f69SBart Van Assche fi 937*44704f69SBart Van Assche} 938*44704f69SBart Van Assche 939*44704f69SBart Van Asschefindsddev() 940*44704f69SBart Van Assche{ 941*44704f69SBart Van Assche local hctl="$1" 942*44704f69SBart Van Assche local sddev= 943*44704f69SBart Van Assche local blkpath 944*44704f69SBart Van Assche 945*44704f69SBart Van Assche blkpath="/sys/class/scsi_device/$hctl/device/block" 946*44704f69SBart Van Assche if [ -e "$blkpath" ] ; then 947*44704f69SBart Van Assche sddev=$(ls "$blkpath") 948*44704f69SBart Van Assche echo "$sddev" 949*44704f69SBart Van Assche fi 950*44704f69SBart Van Assche} 951*44704f69SBart Van Assche 952*44704f69SBart Van Asscheaddmpathtolist() 953*44704f69SBart Van Assche{ 954*44704f69SBart Van Assche local mp="$1" 955*44704f69SBart Van Assche local mp2= 956*44704f69SBart Van Assche 957*44704f69SBart Van Assche for mp2 in $mpaths ; do 958*44704f69SBart Van Assche # The multipath device is already in the list 959*44704f69SBart Van Assche if [ "$mp2" = "$mp" ] ; then 960*44704f69SBart Van Assche return 961*44704f69SBart Van Assche fi 962*44704f69SBart Van Assche done 963*44704f69SBart Van Assche mpaths="$mpaths $mp" 964*44704f69SBart Van Assche} 965*44704f69SBart Van Assche 966*44704f69SBart Van Asschefindmultipath() 967*44704f69SBart Van Assche{ 968*44704f69SBart Van Assche local dev="$1" 969*44704f69SBart Van Assche local find_mismatch="$2" 970*44704f69SBart Van Assche local mp= 971*44704f69SBart Van Assche local found_dup=0 972*44704f69SBart Van Assche local maj_min= 973*44704f69SBart Van Assche 974*44704f69SBart Van Assche # Need a sdev, and executable multipath and dmsetup command here 975*44704f69SBart Van Assche if [ -z "$dev" ] || [ ! -x "$DMSETUP" ] || [ ! -x "$MULTIPATH" ] ; then 976*44704f69SBart Van Assche return 1 977*44704f69SBart Van Assche fi 978*44704f69SBart Van Assche 979*44704f69SBart Van Assche maj_min=$(cat "/sys/block/$dev/dev") 980*44704f69SBart Van Assche mp=$(cat $TMPLUNINFOFILE | grep -w "$maj_min" | cut -d " " -f1) 981*44704f69SBart Van Assche if [ -n "$mp" ]; then 982*44704f69SBart Van Assche if [ -n "$find_mismatch" ] ; then 983*44704f69SBart Van Assche uuid=$(cat $TMPLUNINFOFILE | grep -w "$maj_min" | cut -d " " -f4) 984*44704f69SBart Van Assche if [ "$find_mismatch" != "$uuid" ] ; then 985*44704f69SBart Van Assche addmpathtolist "$mp" 986*44704f69SBart Van Assche found_dup=1 987*44704f69SBart Van Assche fi 988*44704f69SBart Van Assche else 989*44704f69SBart Van Assche # Normal mode: Find the first multipath with the sdev 990*44704f69SBart Van Assche # and add it to the list 991*44704f69SBart Van Assche addmpathtolist "$mp" 992*44704f69SBart Van Assche return 993*44704f69SBart Van Assche fi 994*44704f69SBart Van Assche fi 995*44704f69SBart Van Assche 996*44704f69SBart Van Assche # Return 1 to signal that a duplicate was found to the calling function 997*44704f69SBart Van Assche if [ $found_dup -eq 1 ] ; then 998*44704f69SBart Van Assche return 1 999*44704f69SBart Van Assche else 1000*44704f69SBart Van Assche return 0 1001*44704f69SBart Van Assche fi 1002*44704f69SBart Van Assche} 1003*44704f69SBart Van Assche 1004*44704f69SBart Van Asschereloadmpaths() 1005*44704f69SBart Van Assche{ 1006*44704f69SBart Van Assche local mpath 1007*44704f69SBart Van Assche if [ ! -x "$MULTIPATH" ] ; then 1008*44704f69SBart Van Assche echo "no -x multipath" 1009*44704f69SBart Van Assche return 1010*44704f69SBart Van Assche fi 1011*44704f69SBart Van Assche 1012*44704f69SBart Van Assche # Pass 1 as the argument to reload all mpaths 1013*44704f69SBart Van Assche if [ "$1" = "1" ] ; then 1014*44704f69SBart Van Assche echo "Reloading all multipath devices" 1015*44704f69SBart Van Assche $MULTIPATH -r > /dev/null 2>&1 1016*44704f69SBart Van Assche return 1017*44704f69SBart Van Assche fi 1018*44704f69SBart Van Assche 1019*44704f69SBart Van Assche # Reload the multipath devices 1020*44704f69SBart Van Assche for mpath in $mpaths ; do 1021*44704f69SBart Van Assche echo -n "Reloading multipath device $mpath... " 1022*44704f69SBart Van Assche if $MULTIPATH -r "$mpath" > /dev/null 2>&1 ; then 1023*44704f69SBart Van Assche echo "Done" 1024*44704f69SBart Van Assche else 1025*44704f69SBart Van Assche echo "Fail" 1026*44704f69SBart Van Assche fi 1027*44704f69SBart Van Assche done 1028*44704f69SBart Van Assche} 1029*44704f69SBart Van Assche 1030*44704f69SBart Van Asscheresizempaths() 1031*44704f69SBart Van Assche{ 1032*44704f69SBart Van Assche local mpath 1033*44704f69SBart Van Assche 1034*44704f69SBart Van Assche for mpath in $mpaths ; do 1035*44704f69SBart Van Assche echo -n "Resizing multipath map $mpath ..." 1036*44704f69SBart Van Assche multipathd -k"resize map $mpath" 1037*44704f69SBart Van Assche let updated+=1 1038*44704f69SBart Van Assche done 1039*44704f69SBart Van Assche} 1040*44704f69SBart Van Assche 1041*44704f69SBart Van Asscheflushmpaths() 1042*44704f69SBart Van Assche{ 1043*44704f69SBart Van Assche local mpath 1044*44704f69SBart Van Assche local remove="" 1045*44704f69SBart Van Assche local i 1046*44704f69SBart Van Assche local flush_retries=5 1047*44704f69SBart Van Assche 1048*44704f69SBart Van Assche if [ -n "$1" ] ; then 1049*44704f69SBart Van Assche for mpath in $($DMSETUP ls --target=multipath | cut -f 1) ; do 1050*44704f69SBart Van Assche [ "$mpath" = "No" ] && break 1051*44704f69SBart Van Assche num=$($DMSETUP status "$mpath" | awk 'BEGIN{RS=" ";active=0}/[0-9]+:[0-9]+/{dev=1}/A/{if (dev == 1) active++; dev=0} END{ print active }') 1052*44704f69SBart Van Assche if [ "$num" -eq 0 ] ; then 1053*44704f69SBart Van Assche remove="$remove $mpath" 1054*44704f69SBart Van Assche fi 1055*44704f69SBart Van Assche done 1056*44704f69SBart Van Assche else 1057*44704f69SBart Van Assche remove="$mpaths" 1058*44704f69SBart Van Assche fi 1059*44704f69SBart Van Assche 1060*44704f69SBart Van Assche for mpath in $remove ; do 1061*44704f69SBart Van Assche i=0 1062*44704f69SBart Van Assche echo -n "Flushing multipath device $mpath... " 1063*44704f69SBart Van Assche while [ $i -lt $flush_retries ] ; do 1064*44704f69SBart Van Assche $DMSETUP message "$mpath" 0 fail_if_no_path > /dev/null 2>&1 1065*44704f69SBart Van Assche if $MULTIPATH -f "$mpath" > /dev/null 2>&1 ; then 1066*44704f69SBart Van Assche echo "Done ($i retries)" 1067*44704f69SBart Van Assche break 1068*44704f69SBart Van Assche elif [ $i -eq $flush_retries ] ; then 1069*44704f69SBart Van Assche echo "Fail" 1070*44704f69SBart Van Assche fi 1071*44704f69SBart Van Assche sleep 0.02 1072*44704f69SBart Van Assche let i=$i+1 1073*44704f69SBart Van Assche done 1074*44704f69SBart Van Assche done 1075*44704f69SBart Van Assche} 1076*44704f69SBart Van Assche 1077*44704f69SBart Van Assche 1078*44704f69SBart Van Assche# Find resized luns 1079*44704f69SBart Van Asschefindresized() 1080*44704f69SBart Van Assche{ 1081*44704f69SBart Van Assche local devs= 1082*44704f69SBart Van Assche local size= 1083*44704f69SBart Van Assche local new_size= 1084*44704f69SBart Van Assche local sysfs_path= 1085*44704f69SBart Van Assche local sddev= 1086*44704f69SBart Van Assche local i= 1087*44704f69SBart Van Assche local m= 1088*44704f69SBart Van Assche local mpathsize= 1089*44704f69SBart Van Assche declare -a mpathsizes 1090*44704f69SBart Van Assche 1091*44704f69SBart Van Assche if [ -z "$lunsearch" ] ; then 1092*44704f69SBart Van Assche devs=$(ls /sys/class/scsi_device/) 1093*44704f69SBart Van Assche else 1094*44704f69SBart Van Assche for lun in $lunsearch ; do 1095*44704f69SBart Van Assche devs="$devs $(cd /sys/class/scsi_device/ && ls -d *:${lun})" 1096*44704f69SBart Van Assche done 1097*44704f69SBart Van Assche fi 1098*44704f69SBart Van Assche 1099*44704f69SBart Van Assche for hctl in $devs ; do 1100*44704f69SBart Van Assche sysfs_path="/sys/class/scsi_device/$hctl/device" 1101*44704f69SBart Van Assche if [ -d "$sysfs_path/block" ] ; then 1102*44704f69SBart Van Assche sddev=$(ls "$sysfs_path/block") 1103*44704f69SBart Van Assche size=$(cat "$sysfs_path/block/$sddev/size") 1104*44704f69SBart Van Assche 1105*44704f69SBart Van Assche echo 1 > "$sysfs_path/rescan" 1106*44704f69SBart Van Assche new_size=$(cat "$sysfs_path/block/$sddev/size") 1107*44704f69SBart Van Assche 1108*44704f69SBart Van Assche if [ "$size" != "$new_size" ] && [ "$size" != "0" ] && [ "$new_size" != "0" ] ; then 1109*44704f69SBart Van Assche printf "${yellow}RESIZED: %s ${norm}" 1110*44704f69SBart Van Assche host=$(echo "$hctl" | cut -d":" -f1) 1111*44704f69SBart Van Assche channel=$(echo "$hctl" | cut -d":" -f2) 1112*44704f69SBart Van Assche id=$(echo "$hctl" | cut -d":" -f3) 1113*44704f69SBart Van Assche lun=$(echo "$hctl" | cut -d":" -f4) 1114*44704f69SBart Van Assche 1115*44704f69SBart Van Assche procscsiscsi 1116*44704f69SBart Van Assche echo "$SCSISTR" 1117*44704f69SBart Van Assche incrchgd "$hctl" 1118*44704f69SBart Van Assche fi 1119*44704f69SBart Van Assche fi 1120*44704f69SBart Van Assche done 1121*44704f69SBart Van Assche 1122*44704f69SBart Van Assche if [ -n "$mp_enable" ] && [ -n "$mpaths" ] ; then 1123*44704f69SBart Van Assche i=0 1124*44704f69SBart Van Assche for m in $mpaths ; do 1125*44704f69SBart Van Assche mpathsizes[$i]="$($MULTIPATH -l "$m" | egrep -o [0-9]+.[0-9]+[KMGT])" 1126*44704f69SBart Van Assche let i=$i+1 1127*44704f69SBart Van Assche done 1128*44704f69SBart Van Assche resizempaths 1129*44704f69SBart Van Assche i=0 1130*44704f69SBart Van Assche for m in $mpaths ; do 1131*44704f69SBart Van Assche mpathsize="$($MULTIPATH -l "$m" | egrep -o [0-9\.]+[KMGT])" 1132*44704f69SBart Van Assche echo "$m ${mpathsizes[$i]} => $mpathsize" 1133*44704f69SBart Van Assche let i=$i+1 1134*44704f69SBart Van Assche done 1135*44704f69SBart Van Assche fi 1136*44704f69SBart Van Assche} 1137*44704f69SBart Van Assche 1138*44704f69SBart Van AsscheFOUNDDEVS="" 1139*44704f69SBart Van AsscheCHGDEVS="" 1140*44704f69SBart Van AsscheRMVDDEVS="" 1141*44704f69SBart Van Assche 1142*44704f69SBart Van Assche# main 1143*44704f69SBart Van Asscheif [ "@$1" = @--help ] || [ "@$1" = @-h ] || [ "@$1" = "@-?" ] ; then 1144*44704f69SBart Van Assche echo "Usage: rescan-scsi-bus.sh [options] [host [host ...]]" 1145*44704f69SBart Van Assche echo "Options:" 1146*44704f69SBart Van Assche echo " -a scan all targets, not just currently existing [default: disabled]" 1147*44704f69SBart Van Assche echo " -c enables scanning of channels 0 1 [default: 0 / all detected ones]" 1148*44704f69SBart Van Assche echo " -d enable debug [default: 0]" 1149*44704f69SBart Van Assche echo " -f flush failed multipath devices [default: disabled]" 1150*44704f69SBart Van Assche echo " -h help: print this usage message then exit" 1151*44704f69SBart Van Assche echo " -i issue a FibreChannel LIP reset [default: disabled]" 1152*44704f69SBart Van Assche echo " -I SECS issue a FibreChannel LIP reset and wait for SECS seconds [default: disabled]" 1153*44704f69SBart Van Assche echo " -l activates scanning for LUNs 0--7 [default: 0]" 1154*44704f69SBart Van Assche echo " -L NUM activates scanning for LUNs 0--NUM [default: 0]" 1155*44704f69SBart Van Assche echo " -m update multipath devices [default: disabled]" 1156*44704f69SBart Van Assche echo " -r enables removing of devices [default: disabled]" 1157*44704f69SBart Van Assche echo " -s look for resized disks and reload associated multipath devices, if applicable" 1158*44704f69SBart Van Assche echo " -t SECS timeout for testing if device is online. Test is skipped if 0 [default: 30]" 1159*44704f69SBart Van Assche echo " -u look for existing disks that have been remapped" 1160*44704f69SBart Van Assche echo " -V print version date then exit" 1161*44704f69SBart Van Assche echo " -w scan for target device IDs 0--15 [default: 0--7]" 1162*44704f69SBart Van Assche echo "--alltargets: same as -a" 1163*44704f69SBart Van Assche echo "--attachpq3: Tell kernel to attach sg to LUN 0 that reports PQ=3" 1164*44704f69SBart Van Assche echo "--channels=LIST: Scan only channel(s) in LIST" 1165*44704f69SBart Van Assche echo "--color: use coloured prefixes OLD/NEW/DEL" 1166*44704f69SBart Van Assche echo "--flush: same as -f" 1167*44704f69SBart Van Assche echo "--forceremove: Remove stale devices (DANGEROUS)" 1168*44704f69SBart Van Assche echo "--forcerescan: Remove and readd existing devices (DANGEROUS)" 1169*44704f69SBart Van Assche echo "--help: print this usage message then exit" 1170*44704f69SBart Van Assche echo "--hosts=LIST: Scan only host(s) in LIST" 1171*44704f69SBart Van Assche echo "--ids=LIST: Scan only target ID(s) in LIST" 1172*44704f69SBart Van Assche echo "--ignore-rev: Ignore the revision change" 1173*44704f69SBart Van Assche echo "--issue-lip: same as -i" 1174*44704f69SBart Van Assche echo "--issue-lip-wait=SECS: same as -I" 1175*44704f69SBart Van Assche echo "--largelun: Tell kernel to support LUNs > 7 even on SCSI2 devs" 1176*44704f69SBart Van Assche echo "--luns=LIST: Scan only lun(s) in LIST" 1177*44704f69SBart Van Assche echo "--multipath: same as -m" 1178*44704f69SBart Van Assche echo "--no-lip-scan: don't scan FC Host with issue-lip" 1179*44704f69SBart Van Assche echo "--nooptscan: don't stop looking for LUNs if 0 is not found" 1180*44704f69SBart Van Assche echo "--remove: same as -r" 1181*44704f69SBart Van Assche echo "--reportlun2: Tell kernel to try REPORT_LUN even on SCSI2 devices" 1182*44704f69SBart Van Assche echo "--resize: same as -s" 1183*44704f69SBart Van Assche echo "--sparselun: Tell kernel to support sparse LUN numbering" 1184*44704f69SBart Van Assche echo "--sync/nosync: Issue a sync / no sync [default: sync if remove]" 1185*44704f69SBart Van Assche echo "--timeout=SECS: same as -t" 1186*44704f69SBart Van Assche echo "--update: same as -u" 1187*44704f69SBart Van Assche echo "--version: same as -V" 1188*44704f69SBart Van Assche echo "--wide: same as -w" 1189*44704f69SBart Van Assche echo "" 1190*44704f69SBart Van Assche echo "Host numbers may thus be specified either directly on cmd line (deprecated)" 1191*44704f69SBart Van Assche echo "or with the --hosts=LIST parameter (recommended)." 1192*44704f69SBart Van Assche echo "LIST: A[-B][,C[-D]]... is a comma separated list of single values and ranges" 1193*44704f69SBart Van Assche echo "(No spaces allowed.)" 1194*44704f69SBart Van Assche exit 0 1195*44704f69SBart Van Asschefi 1196*44704f69SBart Van Assche 1197*44704f69SBart Van Asscheif [ "@$1" = @--version ] || [ "@$1" = @-V ] ; then 1198*44704f69SBart Van Assche echo ${VERSION} 1199*44704f69SBart Van Assche exit 0 1200*44704f69SBart Van Asschefi 1201*44704f69SBart Van Assche 1202*44704f69SBart Van Asscheif [ ! -d /sys/class/scsi_host/ ] && [ ! -d /proc/scsi/ ] ; then 1203*44704f69SBart Van Assche echo "Error: SCSI subsystem not active" 1204*44704f69SBart Van Assche exit 1 1205*44704f69SBart Van Asschefi 1206*44704f69SBart Van Assche 1207*44704f69SBart Van Assche# Make sure sg is there 1208*44704f69SBart Van Asschemodprobe sg >/dev/null 2>&1 1209*44704f69SBart Van Assche 1210*44704f69SBart Van Asscheif [ -x /usr/bin/sg_inq ] ; then 1211*44704f69SBart Van Assche sg_version=$(sg_inq -V 2>&1 | cut -d " " -f 3) 1212*44704f69SBart Van Assche if [ -n "$sg_version" ] ; then 1213*44704f69SBart Van Assche sg_ver_maj=${sg_version:0:1} 1214*44704f69SBart Van Assche sg_version=${sg_version##?.} 1215*44704f69SBart Van Assche let sg_version+=$((100 * sg_ver_maj)) 1216*44704f69SBart Van Assche fi 1217*44704f69SBart Van Assche sg_version=${sg_version##0.} 1218*44704f69SBart Van Assche #echo "\"$sg_version\"" 1219*44704f69SBart Van Assche if [ -z "$sg_version" ] || [ "$sg_version" -lt 70 ] ; then 1220*44704f69SBart Van Assche sg_len_arg="-36" 1221*44704f69SBart Van Assche else 1222*44704f69SBart Van Assche sg_len_arg="--len=36" 1223*44704f69SBart Van Assche fi 1224*44704f69SBart Van Asscheelse 1225*44704f69SBart Van Assche echo "WARN: /usr/bin/sg_inq not present -- please install sg3_utils" 1226*44704f69SBart Van Assche echo " or rescan-scsi-bus.sh might not fully work." 1227*44704f69SBart Van Asschefi 1228*44704f69SBart Van Assche 1229*44704f69SBart Van Assche# defaults 1230*44704f69SBart Van Asscheunsetcolor 1231*44704f69SBart Van Asschedebug=0 1232*44704f69SBart Van Asschelunsearch= 1233*44704f69SBart Van Asscheopt_idsearch=$(seq -s ' ' 0 7) 1234*44704f69SBart Van Asschefilter_ids=0 1235*44704f69SBart Van Asscheopt_channelsearch= 1236*44704f69SBart Van Asscheremove= 1237*44704f69SBart Van Asscheupdated=0 1238*44704f69SBart Van Asscheupdate=0 1239*44704f69SBart Van Asscheresize=0 1240*44704f69SBart Van Asscheforceremove= 1241*44704f69SBart Van Asscheoptscan=1 1242*44704f69SBart Van Asschesync=1 1243*44704f69SBart Van Asscheexisting_targets=1 1244*44704f69SBart Van Asschemp_enable= 1245*44704f69SBart Van Asschelipreset=-1 1246*44704f69SBart Van Asschetimeout=30 1247*44704f69SBart Van Asschedeclare -i scan_flags=0 1248*44704f69SBart Van Asscheignore_rev=0 1249*44704f69SBart Van Asscheno_lip_scan=0 1250*44704f69SBart Van Assche 1251*44704f69SBart Van Assche# Scan options 1252*44704f69SBart Van Asscheopt="$1" 1253*44704f69SBart Van Asschewhile [ ! -z "$opt" ] && [ -z "${opt##-*}" ] ; do 1254*44704f69SBart Van Assche opt=${opt#-} 1255*44704f69SBart Van Assche case "$opt" in 1256*44704f69SBart Van Assche a) existing_targets=;; #Scan ALL targets when specified 1257*44704f69SBart Van Assche c) opt_channelsearch="0 1" ;; 1258*44704f69SBart Van Assche d) debug=1 ;; 1259*44704f69SBart Van Assche f) flush=1 ;; 1260*44704f69SBart Van Assche i) lipreset=0 ;; 1261*44704f69SBart Van Assche I) shift; lipreset=$1 ;; 1262*44704f69SBart Van Assche l) lunsearch=$(seq -s ' ' 0 7) ;; 1263*44704f69SBart Van Assche L) lunsearch=$(seq -s ' ' 0 "$2"); shift ;; 1264*44704f69SBart Van Assche m) mp_enable=1 ;; 1265*44704f69SBart Van Assche r) remove=1 ;; 1266*44704f69SBart Van Assche s) resize=1; mp_enable=1 ;; 1267*44704f69SBart Van Assche t) timeout=$2; shift ;; 1268*44704f69SBart Van Assche u) update=1 ;; 1269*44704f69SBart Van Assche w) opt_idsearch=$(seq -s ' ' 0 15) ;; 1270*44704f69SBart Van Assche -alltargets) existing_targets=;; 1271*44704f69SBart Van Assche -attachpq3) scan_flags=$((scan_flags|0x1000000)) ;; 1272*44704f69SBart Van Assche -channels=*) arg=${opt#-channels=};opt_channelsearch=$(expandlist "$arg") ;; 1273*44704f69SBart Van Assche -color) setcolor ;; 1274*44704f69SBart Van Assche -flush) flush=1 ;; 1275*44704f69SBart Van Assche -forceremove) remove=1; forceremove=1 ;; 1276*44704f69SBart Van Assche -forcerescan) remove=1; forcerescan=1 ;; 1277*44704f69SBart Van Assche -hosts=*) arg=${opt#-hosts=}; hosts=$(expandlist "$arg") ;; 1278*44704f69SBart Van Assche -ids=*) arg=${opt#-ids=}; opt_idsearch=$(expandlist "$arg") ; filter_ids=1;; 1279*44704f69SBart Van Assche -ignore-rev) ignore_rev=1;; 1280*44704f69SBart Van Assche -issue-lip) lipreset=0 ;; 1281*44704f69SBart Van Assche -issue-lip-wait=*) lipreset=${opt#-issue-lip-wait=};; 1282*44704f69SBart Van Assche -largelun) scan_flags=$((scan_flags|0x200)) ;; 1283*44704f69SBart Van Assche -luns=*) arg=${opt#-luns=}; lunsearch=$(expandlist "$arg") ;; 1284*44704f69SBart Van Assche -multipath) mp_enable=1 ;; 1285*44704f69SBart Van Assche -no-lip-scan) no_lip_scan=1 ;; 1286*44704f69SBart Van Assche -nooptscan) optscan=0 ;; 1287*44704f69SBart Van Assche -nosync) sync=0 ;; 1288*44704f69SBart Van Assche -remove) remove=1 ;; 1289*44704f69SBart Van Assche -reportlun2) scan_flags=$((scan_flags|0x20000)) ;; 1290*44704f69SBart Van Assche -resize) resize=1;; 1291*44704f69SBart Van Assche -timeout=*) timeout=${opt#-timeout=};; 1292*44704f69SBart Van Assche -sparselun) scan_flags=$((scan_flags|0x40)) ;; 1293*44704f69SBart Van Assche -sync) sync=2 ;; 1294*44704f69SBart Van Assche -update) update=1;; 1295*44704f69SBart Van Assche -wide) opt_idsearch=$(seq -s ' ' 0 15) ;; 1296*44704f69SBart Van Assche *) echo "Unknown option -$opt !" ;; 1297*44704f69SBart Van Assche esac 1298*44704f69SBart Van Assche shift 1299*44704f69SBart Van Assche opt="$1" 1300*44704f69SBart Van Asschedone 1301*44704f69SBart Van Assche 1302*44704f69SBart Van Asscheif [ -z "$hosts" ] ; then 1303*44704f69SBart Van Assche if [ -d /sys/class/scsi_host ] ; then 1304*44704f69SBart Van Assche findhosts_26 1305*44704f69SBart Van Assche else 1306*44704f69SBart Van Assche findhosts 1307*44704f69SBart Van Assche fi 1308*44704f69SBart Van Asschefi 1309*44704f69SBart Van Assche 1310*44704f69SBart Van Asscheif [ -d /sys/class/scsi_host ] && [ ! -w /sys/class/scsi_host ]; then 1311*44704f69SBart Van Assche echo "You need to run scsi-rescan-bus.sh as root" 1312*44704f69SBart Van Assche exit 2 1313*44704f69SBart Van Asschefi 1314*44704f69SBart Van Assche[ "$sync" = 1 ] && [ "$remove" = 1 ] && sync=2 1315*44704f69SBart Van Asscheif [ "$sync" = 2 ] ; then 1316*44704f69SBart Van Assche echo "Syncing file systems" 1317*44704f69SBart Van Assche sync 1318*44704f69SBart Van Asschefi 1319*44704f69SBart Van Asscheif [ -w /sys/module/scsi_mod/parameters/default_dev_flags ] && [ $scan_flags != 0 ] ; then 1320*44704f69SBart Van Assche OLD_SCANFLAGS=$(cat /sys/module/scsi_mod/parameters/default_dev_flags) 1321*44704f69SBart Van Assche NEW_SCANFLAGS=$((OLD_SCANFLAGS|scan_flags)) 1322*44704f69SBart Van Assche if [ "$OLD_SCANFLAGS" != "$NEW_SCANFLAGS" ] ; then 1323*44704f69SBart Van Assche echo -n "Temporarily setting kernel scanning flags from " 1324*44704f69SBart Van Assche printf "0x%08x to 0x%08x\n" "$OLD_SCANFLAGS" "$NEW_SCANFLAGS" 1325*44704f69SBart Van Assche echo $NEW_SCANFLAGS > /sys/module/scsi_mod/parameters/default_dev_flags 1326*44704f69SBart Van Assche else 1327*44704f69SBart Van Assche unset OLD_SCANFLAGS 1328*44704f69SBart Van Assche fi 1329*44704f69SBart Van Asschefi 1330*44704f69SBart Van AsscheDMSETUP=$(which dmsetup) 1331*44704f69SBart Van Assche[ -z "$DMSETUP" ] && flush= && mp_enable= 1332*44704f69SBart Van AsscheMULTIPATH=$(which multipath) 1333*44704f69SBart Van Assche[ -z "$MULTIPATH" ] && flush= && mp_enable= 1334*44704f69SBart Van Assche 1335*44704f69SBart Van Asscheecho -n "Scanning SCSI subsystem for new devices" 1336*44704f69SBart Van Assche[ -z "$flush" ] || echo -n ", flush failed multipath devices," 1337*44704f69SBart Van Assche[ -z "$remove" ] || echo -n " and remove devices that have disappeared" 1338*44704f69SBart Van Asscheecho 1339*44704f69SBart Van Asschedeclare -i found=0 1340*44704f69SBart Van Asschedeclare -i updated=0 1341*44704f69SBart Van Asschedeclare -i rmvd=0 1342*44704f69SBart Van Assche 1343*44704f69SBart Van Asscheif [ -n "$flush" ] ; then 1344*44704f69SBart Van Assche if [ -x "$MULTIPATH" ] ; then 1345*44704f69SBart Van Assche flushmpaths 1 1346*44704f69SBart Van Assche fi 1347*44704f69SBart Van Asschefi 1348*44704f69SBart Van Assche 1349*44704f69SBart Van Assche# Update existing mappings 1350*44704f69SBart Van Asscheif [ $update -eq 1 ] ; then 1351*44704f69SBart Van Assche echo "Searching for remapped LUNs" 1352*44704f69SBart Van Assche findremapped 1353*44704f69SBart Van Assche # If you've changed the mapping, there's a chance it's a different size 1354*44704f69SBart Van Assche mpaths="" 1355*44704f69SBart Van Assche findresized 1356*44704f69SBart Van Assche# Search for resized LUNs 1357*44704f69SBart Van Asscheelif [ $resize -eq 1 ] ; then 1358*44704f69SBart Van Assche echo "Searching for resized LUNs" 1359*44704f69SBart Van Assche findresized 1360*44704f69SBart Van Assche# Normal rescan mode 1361*44704f69SBart Van Asscheelse 1362*44704f69SBart Van Assche for host in $hosts; do 1363*44704f69SBart Van Assche echo -n "Scanning host $host " 1364*44704f69SBart Van Assche if [ $no_lip_scan -eq 0 ] && [ -e "/sys/class/fc_host/host$host" ] ; then 1365*44704f69SBart Van Assche # It's pointless to do a target scan on FC 1366*44704f69SBart Van Assche issue_lip=/sys/class/fc_host/host$host/issue_lip 1367*44704f69SBart Van Assche if [ -e "$issue_lip" ] && [ "$lipreset" -ge 0 ] ; then 1368*44704f69SBart Van Assche echo 1 > "$issue_lip" 2> /dev/null; 1369*44704f69SBart Van Assche udevadm_settle 1370*44704f69SBart Van Assche [ "$lipreset" -gt 0 ] && sleep "$lipreset" 1371*44704f69SBart Van Assche fi 1372*44704f69SBart Van Assche channelsearch= 1373*44704f69SBart Van Assche idsearch= 1374*44704f69SBart Van Assche else 1375*44704f69SBart Van Assche channelsearch=$opt_channelsearch 1376*44704f69SBart Van Assche idsearch=$opt_idsearch 1377*44704f69SBart Van Assche fi 1378*44704f69SBart Van Assche [ -n "$channelsearch" ] && echo -n "channels $channelsearch " 1379*44704f69SBart Van Assche echo -n "for " 1380*44704f69SBart Van Assche if [ -n "$idsearch" ] ; then 1381*44704f69SBart Van Assche echo -n " SCSI target IDs $idsearch" 1382*44704f69SBart Van Assche else 1383*44704f69SBart Van Assche echo -n " all SCSI target IDs" 1384*44704f69SBart Van Assche fi 1385*44704f69SBart Van Assche if [ -n "$lunsearch" ] ; then 1386*44704f69SBart Van Assche echo ", LUNs $lunsearch" 1387*44704f69SBart Van Assche else 1388*44704f69SBart Van Assche echo ", all LUNs" 1389*44704f69SBart Van Assche fi 1390*44704f69SBart Van Assche 1391*44704f69SBart Van Assche if [ -n "$existing_targets" ] ; then 1392*44704f69SBart Van Assche searchexisting 1393*44704f69SBart Van Assche else 1394*44704f69SBart Van Assche dosearch 1395*44704f69SBart Van Assche fi 1396*44704f69SBart Van Assche done 1397*44704f69SBart Van Assche if [ -n "$OLD_SCANFLAGS" ] ; then 1398*44704f69SBart Van Assche echo "$OLD_SCANFLAGS" > /sys/module/scsi_mod/parameters/default_dev_flags 1399*44704f69SBart Van Assche fi 1400*44704f69SBart Van Asschefi 1401*44704f69SBart Van Assche 1402*44704f69SBart Van Asschelet rmvd_found=$rmvd+$found 1403*44704f69SBart Van Asscheif [ -n "$mp_enable" ] && [ $rmvd_found -gt 0 ] ; then 1404*44704f69SBart Van Assche echo "Attempting to update multipath devices..." 1405*44704f69SBart Van Assche if [ $rmvd -gt 0 ] ; then 1406*44704f69SBart Van Assche udevadm_settle 1407*44704f69SBart Van Assche echo "Removing multipath mappings for removed devices if all paths are now failed... " 1408*44704f69SBart Van Assche flushmpaths 1 1409*44704f69SBart Van Assche fi 1410*44704f69SBart Van Assche if [ $found -gt 0 ] ; then 1411*44704f69SBart Van Assche /sbin/udevadm trigger --sysname-match=sd* 1412*44704f69SBart Van Assche udevadm_settle 1413*44704f69SBart Van Assche if [ -x "$MULTIPATH" ] ; then 1414*44704f69SBart Van Assche echo "Trying to discover new multipath mappings for newly discovered devices... " 1415*44704f69SBart Van Assche $MULTIPATH | grep "create:" 2> /dev/null 1416*44704f69SBart Van Assche fi 1417*44704f69SBart Van Assche fi 1418*44704f69SBart Van Asschefi 1419*44704f69SBart Van Assche 1420*44704f69SBart Van Asscheecho "$found new or changed device(s) found. " 1421*44704f69SBart Van Asscheif [ ! -z "$FOUNDDEVS" ] ; then 1422*44704f69SBart Van Assche echo -e "$FOUNDDEVS" 1423*44704f69SBart Van Asschefi 1424*44704f69SBart Van Asscheecho "$updated remapped or resized device(s) found." 1425*44704f69SBart Van Asscheif [ ! -z "$CHGDEVS" ] ; then 1426*44704f69SBart Van Assche echo -e "$CHGDEVS" 1427*44704f69SBart Van Asschefi 1428*44704f69SBart Van Asscheecho "$rmvd device(s) removed. " 1429*44704f69SBart Van Asscheif [ ! -z "$RMVDDEVS" ] ; then 1430*44704f69SBart Van Assche echo -e "$RMVDDEVS" 1431*44704f69SBart Van Asschefi 1432*44704f69SBart Van Assche 1433*44704f69SBart Van Assche# Local Variables: 1434*44704f69SBart Van Assche# sh-basic-offset: 2 1435*44704f69SBart Van Assche# End: 1436*44704f69SBart Van Assche 1437