aboutsummaryrefslogtreecommitdiff
path: root/scripts/rescan-scsi-bus.sh
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2015-04-01 21:45:22 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2015-04-01 21:45:22 +0000
commitbaa91c3f8356cf0b5ff94a778070c3c6714ac5f9 (patch)
tree826c695e97adaba3d4cd421a4fb115014f516b87 /scripts/rescan-scsi-bus.sh
parente65afc2448aee567499271a1a0c904be67f797d4 (diff)
downloadsg3_utils-baa91c3f8356cf0b5ff94a778070c3c6714ac5f9.tar.gz
rescan-scsi-bus.sh+sg_rdac+sg_inq+sg_vpd: updates from Sean Stewart, NetApp
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@640 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'scripts/rescan-scsi-bus.sh')
-rwxr-xr-xscripts/rescan-scsi-bus.sh250
1 files changed, 165 insertions, 85 deletions
diff --git a/scripts/rescan-scsi-bus.sh b/scripts/rescan-scsi-bus.sh
index 51fdfd99..96c06890 100755
--- a/scripts/rescan-scsi-bus.sh
+++ b/scripts/rescan-scsi-bus.sh
@@ -91,8 +91,8 @@ findhosts ()
num=$name
driverinfo=$driver
if test -r $hostdir/status; then
- num=$(printf '%d\n' `sed -n 's/SCSI host number://p' $hostdir/status`)
- driverinfo="$driver:$name"
+ num=$(printf '%d\n' `sed -n 's/SCSI host number://p' $hostdir/status`)
+ driverinfo="$driver:$name"
fi
hosts="$hosts $num"
echo "Host adapter $num ($driverinfo) found."
@@ -147,19 +147,19 @@ procscsiscsi ()
if [ -d "$SCSIPATH" ] ; then
SCSISTR="Host: scsi${host} Channel: $CHANNEL Id: $ID Lun: $LUN"
if [ "$LN" -gt 0 ] ; then
- IVEND=$(cat ${SCSIPATH}/device/vendor)
- IPROD=$(cat ${SCSIPATH}/device/model)
- IPREV=$(cat ${SCSIPATH}/device/rev)
- SCSIDEV=$(printf ' Vendor: %-08s Model: %-16s Rev: %-4s' "$IVEND" "$IPROD" "$IPREV")
- SCSISTR="$SCSISTR
+ IVEND=$(cat ${SCSIPATH}/device/vendor)
+ IPROD=$(cat ${SCSIPATH}/device/model)
+ IPREV=$(cat ${SCSIPATH}/device/rev)
+ SCSIDEV=$(printf ' Vendor: %-08s Model: %-16s Rev: %-4s' "$IVEND" "$IPROD" "$IPREV")
+ SCSISTR="$SCSISTR
$SCSIDEV"
fi
if [ "$LN" -gt 1 ] ; then
- ILVL=$(cat ${SCSIPATH}/device/scsi_level)
- type=$(cat ${SCSIPATH}/device/type)
- ITYPE=$(printtype $type)
- SCSITMP=$(printf ' Type: %-17s ANSI SCSI revision: %02d' "$ITYPE" "$((ILVL - 1))")
- SCSISTR="$SCSISTR
+ ILVL=$(cat ${SCSIPATH}/device/scsi_level)
+ type=$(cat ${SCSIPATH}/device/type)
+ ITYPE=$(printtype $type)
+ SCSITMP=$(printf ' Type: %-17s ANSI SCSI revision: %02d' "$ITYPE" "$((ILVL - 1))")
+ SCSISTR="$SCSISTR
$SCSITMP"
fi
else
@@ -175,14 +175,14 @@ $SCSITMP"
# Find sg device with 2.6 sysfs support
sgdevice26 ()
{
- if test -e /sys/class/scsi_device/$host\:$channel\:$id\:$lun/device/generic; then
+ if test -e /sys/class/scsi_device/$host\:$channel\:$id\:$lun/device/generic; then
SGDEV=`readlink /sys/class/scsi_device/$host\:$channel\:$id\:$lun/device/generic`
SGDEV=`basename $SGDEV`
else
for SGDEV in /sys/class/scsi_generic/sg*; do
DEV=`readlink $SGDEV/device`
if test "${DEV##*/}" = "$host:$channel:$id:$lun"; then
- SGDEV=`basename $SGDEV`; return
+ SGDEV=`basename $SGDEV`; return
fi
done
SGDEV=""
@@ -286,7 +286,7 @@ testonline ()
echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}\nfrom:${SCSISTR#* } \nto: $STR ${norm} \n\n\n"
return 1
fi
- TMPSTR=`echo "$SCSISTR" | sed -n 's/.*Type: *\(.*\) *ANSI.*/\1/p'`
+ TMPSTR=`echo "$SCSISTR" | sed -n 's/.*Type: *\(.*\) *ANSI.*/\1/p' | sed 's/ *$//g'`
if [ "$TMPSTR" != "$TYPE" ] ; then
echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}\nfrom:${TMPSTR} \nto: $TYPE ${norm} \n\n\n"
return 1
@@ -322,7 +322,7 @@ chanlist ()
chan=${cil%%:*}
for tmpchan in $channelsearch ; do
if test "$chan" -eq $tmpchan ; then
- chan=
+ chan=
fi
done
if test -n "$chan" ; then
@@ -348,8 +348,8 @@ idlist ()
newid=$id
for tmpid in $idsearch ; do
if test $id -eq $tmpid ; then
- newid=
- break
+ newid=
+ break
fi
done
if test -n "$newid" ; then
@@ -394,9 +394,17 @@ getluns()
# Wait for udev to settle (create device nodes etc.)
udevadm_settle()
{
+ local tmo=60
if test -x /sbin/udevadm; then
print_and_scroll_back " Calling udevadm settle (can take a while) "
- /sbin/udevadm settle
+ # Loop for up to 60 seconds if sd devices still are settling..
+ # This allows us to continue if udev events are stuck on multipaths in recovery mode
+ while [ $tmo -gt 0 ] ; do
+ if ! /sbin/udevadm settle --timeout=1 | egrep -q sd[a-z]+ ; then
+ break;
+ fi
+ let tmo=$tmo-1
+ done
white_out
elif test -x /sbin/udevsettle; then
print_and_scroll_back " Calling udevsettle (can take a while) "
@@ -465,13 +473,13 @@ dolunscan()
incrrmvd "$host:$channel:$id:$lun"
fi
echo 1 > /sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device/delete
- usleep 20000
+ usleep 20000
else
echo "scsi remove-single-device $devnr" > /proc/scsi/scsi
- if test $RC -eq 1 -o $lun -eq 0 ; then
+ if test $RC -eq 1 -o $lun -eq 0 ; then
# Try readding, should fail if device is gone
echo "scsi add-single-device $devnr" > /proc/scsi/scsi
- fi
+ fi
fi
fi
if test $RC = 0 -o "$forcerescan" ; then
@@ -543,7 +551,7 @@ doreportlun()
# Find alternative LUN to send getluns to
for dev in /sys/class/scsi_device/${host}:${channel}:${id}:*; do
[ -d "$dev" ] || continue
- lun=${dev##*:}
+ lun=${dev##*:}
break
done
fi
@@ -581,10 +589,10 @@ doreportlun()
# OK, is existing $lun (still) in reported list
for tmplun in $targetluns; do
if test $tmplun -eq $lun ; then
- inlist=1
- dolunscan $lun0added
+ inlist=1
+ dolunscan $lun0added
else
- newsearch="$newsearch $tmplun"
+ newsearch="$newsearch $tmplun"
fi
done
# OK, we have now done a lunscan on $lun and
@@ -614,9 +622,9 @@ dosearch ()
fi
for id in $idsearch; do
if test -z "$lunsearch" ; then
- doreportlun
+ doreportlun
else
- for lun in $lunsearch; do
+ for lun in $lunsearch; do
dolunscan
done
fi
@@ -661,12 +669,12 @@ searchexisting()
id=`echo $target | cut -d":" -f 3`
if [ -n "$channelsearch" ] ; then
for tmpch in $channelsearch ; do
- test $tmpch -eq $channel && match=1
+ test $tmpch -eq $channel && match=1
done
else
match=1
fi
-
+
test $match -eq 0 && continue
match=0
@@ -692,6 +700,8 @@ findremapped()
local id_serial=
local id_serial_old=
local sysfs_devpath=
+ local mpath_uuid=
+ local remapped=
mpaths=""
local tmpfile="/tmp/rescan-scsi-bus-`date +s`"
@@ -700,7 +710,7 @@ findremapped()
# Get all of the ID_SERIAL attributes, after finding their sd node
for hctl in $devs ; do
if [ -d /sys/class/scsi_device/$hctl/device/block ] ; then
- sddev=`ls /sys/class/scsi_device/$hctl/device/block`
+ sddev=`ls /sys/class/scsi_device/$hctl/device/block`
id_serial_old=`udevadm info -q all -n $sddev | grep "ID_SERIAL=" | cut -d"=" -f2`
[ -z "$id_serial_old" ] && id_serial_old="none"
echo "$hctl $sddev $id_serial_old" >> $tmpfile
@@ -710,33 +720,46 @@ findremapped()
# Trigger udev to update the info
echo -n "Triggering udev to update device information... "
/sbin/udevadm trigger
- udevadm_settle 2&>1 /dev/null
+ udevadm_settle 2>&1 /dev/null
echo "Done"
# See what changed and reload the respective multipath device if applicable
while read hctl sddev id_serial_old ; do
+ remapped=0
id_serial=`udevadm info -q all -n $sddev | grep "ID_SERIAL=" | cut -d"=" -f2`
[ -z "$id_serial" ] && id_serial="none"
if [ "$id_serial_old" != "$id_serial" ] ; then
- if [ "$id_serial" = "1" ] ; then
- continue # the lun was unmapped and is getting the blank scsi id (1)
+ remapped=1
+ fi
+ # If udev events updated the disks already, but the multipath device isn't update
+ # check for old devices to make sure we found remapped luns
+ if [ -n "$mp_enable" ] && [ $remapped -eq 0 ]; then
+ findmultipath $sddev $id_serial
+ if [ $? -eq 1 ] ; then
+ remapped=1
fi
- printf "${yellow}REMAPPED: $norm"
- host=`echo $hctl | cut -d":" -f1`
- channel=`echo $hctl | cut -d":" -f2`
- id=`echo $hctl | cut -d":" -f3`
- lun=`echo $hctl | cut -d":" -f4`
- procscsiscsi
- echo "$SCSISTR"
- incrchgd "$hctl"
fi
+
+ # if uuid is 1, it's unmapped, so we don't want to treat it as a remap
+ # if remapped flag is 0, just skip the rest of the logic
+ if [ "$id_serial" = "1" ] || [ $remapped -eq 0 ] ; then
+ continue
+ fi
+ printf "${yellow}REMAPPED: $norm"
+ host=`echo $hctl | cut -d":" -f1`
+ channel=`echo $hctl | cut -d":" -f2`
+ id=`echo $hctl | cut -d":" -f3`
+ lun=`echo $hctl | cut -d":" -f4`
+ procscsiscsi
+ echo "$SCSISTR"
+ incrchgd "$hctl"
done < $tmpfile
- rm $tmpfile 2&>1 /dev/null
+ rm $tmpfile 2>&1 /dev/null
if test -n "$mp_enable" -a -n "$mpaths" ; then
echo "Updating multipath device mappings"
flushmpaths
- $MULTIPATH | grep "create:" 2> /dev/null #2&>1 /dev/null
+ $MULTIPATH | grep "create:" 2> /dev/null
fi
}
@@ -755,8 +778,10 @@ incrchgd()
{
local hctl="$1"
if test -n "$hctl" ; then
- let updated+=1
- CHGDEVS="$CHGDEVS\t[$hctl]\n"
+ if ! echo $CHGDEVS | grep -q "\[$hctl\]"; then
+ let updated+=1
+ CHGDEVS="$CHGDEVS\t[$hctl]\n"
+ fi
else
return
fi
@@ -802,30 +827,61 @@ findsddev()
return 0
}
+addmpathtolist()
+{
+ local mp="$1"
+ local mp2=
+
+ for mp2 in $mpaths ; do
+ # The multipath device is already in the list
+ if [ "$mp2" = "$mp" ] ; then
+ return
+ fi
+ done
+ mpaths="$mpaths $mp"
+}
+
findmultipath()
{
local dev="$1"
+ local find_mismatch="$2"
local mp=
local mp2=
+ local found_dup=0
# Need a sdev, and executable multipath and dmsetup command here
- if [ -z "$dev" ] || [ ! -x $DMSETUP ] ; then
+ if [ -z "$dev" ] || [ ! -x $DMSETUP ] || [ ! -x $MULTIPATH ] ; then
return 1
fi
local maj_min=`cat /sys/block/$dev/dev`
for mp in $($DMSETUP ls --target=multipath | cut -f 1) ; do
if $($DMSETUP status $mp | grep -q " $maj_min ") ; then
- for mp2 in $mpaths ; do
- # mp device is already there, return
- if [ "$mp2" = "$mp" ] ; then
- return
+ # With two arguments, look up current uuid from sysfs
+ # if it doesn't match what was passed, this multipath
+ # device is not updated, so this is a remapped LUN
+ if [ -n "$find_mismatch" ] ; then
+ mp2=`$MULTIPATH -l $mp | egrep -o dm-[0-9]+`
+ mp2=`cat /sys/block/$mp2/dm/uuid | cut -f2 -d-`
+ if [ "$find_mismatch" != "$mp2" ] ; then
+ addmpathtolist $mp
+ found_dup=1
fi
- done
- mpaths="$mpaths $mp"
+ continue
+ fi
+ # Normal mode: Find the first multipath with the sdev
+ # and add it to the list
+ addmpathtolist $mp
return
fi
done
+
+ # Return 1 to signal that a duplicate was found to the calling function
+ if [ $found_dup -eq 1 ] ; then
+ return 1
+ else
+ return 0
+ fi
}
reloadmpaths()
@@ -836,51 +892,58 @@ reloadmpaths()
return
fi
+ # Pass 1 as the argument to reload all mpaths
if [ "$1" = "1" ] ; then
echo "Reloading all multipath devices"
- $MULTIPATH -r 2&>1 /dev/null
+ $MULTIPATH -r > /dev/null 2>&1
return
fi
# Reload the multipath devices
for mpath in $mpaths ; do
- echo "Reloading multipath device $mpath"
- $MULTIPATH -r $mpath 2&>1 /dev/null
+ echo -n "Reloading multipath device $mpath... "
+ $MULTIPATH -r $mpath > /dev/null 2>&1
+ if test "$?" = "0" ; then
+ echo "Done"
+ else
+ echo "Fail"
+ fi
done
}
flushmpaths()
{
local mpath
- # Mode: flush only failed
+ local remove=""
+ local i
+ local flush_retries=5
+
if test -n "$1" ; then
for mpath in $($DMSETUP ls --target=multipath | cut -f 1) ; do
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 }')
if [ $num -eq 0 ] ; then
- echo -n "Flushing multipath device $mpath... "
- $DMSETUP message $mpath 0 fail_if_no_path 2&>1 /dev/null
- $MULTIPATH -f $mpath 2&>1 /dev/null
- $DMSETUP status $mpath 2&>1 /dev/null
- if test "$?" = "1" ; then
- echo "Done"
- else
- echo "Fail"
- fi
+ remove="$remove $mpath"
fi
done
- return
+ else
+ remove="$mpaths"
fi
- # Flush all the devs specified in $mpaths
- for mpath in $mpaths ; do
- echo -n "Flushing multipath device $mpath... "
- $DMSETUP message $mpath 0 fail_if_no_path 2&>1 /dev/null
- $MULTIPATH -f $mpath 2&>1 /dev/null
- $DMSETUP status $mpath 2&>1 /dev/null
- if test "$?" = "1" ; then
- echo "Done"
- else
- echo "Fail"
- fi
+
+ for mpath in $remove ; do
+ i=0
+ echo -n "Flushing multipath device $mpath... "
+ while [ $i -lt $flush_retries ] ; do
+ $DMSETUP message $mpath 0 fail_if_no_path > /dev/null 2>&1
+ $MULTIPATH -f $mpath > /dev/null 2>&1
+ if test "$?" = "0" ; then
+ echo "Done ($i retries)"
+ break
+ elif test $i -eq $flush_retries ; then
+ echo "Fail"
+ fi
+ usleep 20000
+ let i=$i+1
+ done
done
}
@@ -893,16 +956,20 @@ findresized()
local new_size=
local sysfs_path=
local sddev=
+ local i=
+ local m=
+ local mpathsize=
+ declare -a mpathsizes
for hctl in $devs ; do
sysfs_path="/sys/class/scsi_device/$hctl/device"
if [ -d "$sysfs_path/block" ] ; then
sddev=`ls $sysfs_path/block`
size=`cat $sysfs_path/block/$sddev/size`
-
+
echo 1 > $sysfs_path/rescan
- new_size=`cat $sysfs_path/block/$sddev/size`
-
+ new_size=`cat $sysfs_path/block/$sddev/size`
+
if [ "$size" != "$new_size" ] && [ "$size" != "0" ] && [ "$new_size" != "0" ] ; then
printf "${yellow}RESIZED: $norm"
host=`echo $hctl | cut -d":" -f1`
@@ -918,7 +985,18 @@ findresized()
done
if test -n "$mp_enable" -a -n "$mpaths" ; then
+ i=0
+ for m in $mpaths ; do
+ mpathsizes[$i]="`$MULTIPATH -l $m | egrep -o [0-9]+.[0-9]+[KMGT]`"
+ let i=$i+1
+ done
reloadmpaths
+ i=0
+ for m in $mpaths ; do
+ mpathsize="`$MULTIPATH -l $m | egrep -o [0-9\.]+[KMGT]`"
+ echo "$m ${mpathsizes[$i]} => $mpathsize"
+ let i=$i+1
+ done
fi
}
@@ -976,7 +1054,7 @@ fi
if test ! -d /sys/class/scsi_host/ -a ! -d /proc/scsi/; then
echo "Error: SCSI subsystem not active"
exit 1
-fi
+fi
# Make sure sg is there
modprobe sg >/dev/null 2>&1
@@ -1114,6 +1192,9 @@ fi
if [ $update -eq 1 ] ; then
echo "Searching for remapped LUNs"
findremapped
+ # If you've changed the mapping, there's a chance it's a different size
+ mpaths=""
+ findresized
# Search for resized LUNs
elif [ $resize -eq 1 ] ; then
echo "Searching for resized LUNs"
@@ -1164,13 +1245,12 @@ let rmvd_found=$rmvd+$found
if test -n "$mp_enable" -a $rmvd_found -gt 0 ; then
echo "Attempting to update multipath devices..."
if test $rmvd -gt 0 ; then
- /sbin/udevadm trigger
udevadm_settle
echo "Removing multipath mappings for removed devices if all paths are now failed... "
flushmpaths 1
fi
if test $found -gt 0 ; then
- /sbin/udevadm trigger
+ /sbin/udevadm trigger --sysname-match=sd*
udevadm_settle
echo "Trying to discover new multipath mappings for newly discovered devices... "
$MULTIPATH | grep "create:" 2> /dev/null
@@ -1181,7 +1261,7 @@ echo "$found new or changed device(s) found. "
if test ! -z "$FOUNDDEVS" ; then
printf "$FOUNDDEVS"
fi
-echo "$updated remapped or resized device(s) found. "
+echo "$updated remapped or resized device(s) found."
if test ! -z "$CHGDEVS" ; then
printf "$CHGDEVS"
fi