SOURCES: rescan-scsi-bus.sh - update to 1.25: Merge work from Hann...

glen glen at pld-linux.org
Tue Nov 13 14:53:12 CET 2007


Author: glen                         Date: Tue Nov 13 13:53:12 2007 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- update to 1.25: Merge work from Hannes Reinecke to add REPORT_LUNS scan support, and optional LIP reset support

---- Files affected:
SOURCES:
   rescan-scsi-bus.sh (1.5 -> 1.6) 

---- Diffs:

================================================================
Index: SOURCES/rescan-scsi-bus.sh
diff -u SOURCES/rescan-scsi-bus.sh:1.5 SOURCES/rescan-scsi-bus.sh:1.6
--- SOURCES/rescan-scsi-bus.sh:1.5	Tue Nov 13 14:52:55 2007
+++ SOURCES/rescan-scsi-bus.sh	Tue Nov 13 14:53:06 2007
@@ -27,12 +27,16 @@
   if ! ls /sys/class/scsi_host/host* >/dev/null 2>&1; then
     echo "No SCSI host adapters found in sysfs"
     exit 1;
-    #hosts=" 0"
-    #return
   fi 
   for hostdir in /sys/class/scsi_host/host*; do
     hostno=${hostdir#/sys/class/scsi_host/host}
-    hostname=`cat $hostdir/proc_name`
+    if [ -f $hostdir/isp_name ] ; then
+	hostname="qla2xxx"
+    elif [ -f $hostdir/lpfc_drvr_version ] ; then
+	hostname="lpfc"
+    else
+        hostname=`cat $hostdir/proc_name`
+    fi
     hosts="$hosts $hostno"
     echo "Host adapter $hostno ($hostname) found."
   done  
@@ -169,12 +173,13 @@
 # Test if SCSI device is still responding to commands
 testonline ()
 {
+  : testonline
   if test ! -x /usr/bin/sg_turs; then return 0; fi
   sgdevice
   if test -z "$SGDEV"; then return 0; fi
   sg_turs /dev/$SGDEV >/dev/null 2>&1
   RC=$?
-  #echo -e "\e[A\e[A\e[A${yellow}Test existence of $SGDEV = $RC ${norm} \n\n\n"
+  # echo -e "\e[A\e[A\e[A${yellow}Test existence of $SGDEV = $RC ${norm} \n\n\n"
   if test $RC = 1; then return $RC; fi
   # OK, device online, compare INQUIRY string
   INQ=`sg_inq -36 /dev/$SGDEV`
@@ -195,6 +200,7 @@
 # Outputs description from /proc/scsi/scsi, returns SCSISTR 
 testexist ()
 {
+  : testexist
   SCSISTR=
   if procscsiscsi; then
     echo "$SCSISTR" | head -n1
@@ -202,63 +208,191 @@
   fi
 }
 
+# Returns the list of existing channels per host
+chanlist ()
+{
+  local hcil
+  local cil
+  local chan
+  local tmpchan
+
+  for dev in /sys/class/scsi_device/${host}:* ; do
+    hcil=${dev##*/}
+    cil=${hcil#*:}
+    chan=${cil%%:*}
+    for tmpchan in $channelsearch ; do
+      if test "$chan" -eq $tmpchan ; then
+	chan=
+      fi
+    done
+    if test -n "$chan" ; then
+      channelsearch="$channelsearch $chan"
+    fi
+  done
+}
+
+# Returns the list of existing targets per host
+idlist ()
+{
+  local hcil
+  local cil
+  local il
+  local target
+  local tmpid
+
+  for dev in /sys/class/scsi_device/${host}:${channel}:* ; do
+    hcil=${dev##*/}
+    cil=${hcil#*:}
+    il=${cil#*:}
+    target=${il%%:*}
+    for tmpid in $idsearch ; do
+      if test "$target" -eq $tmpid ; then
+	target=
+      fi
+    done
+    if test -n "$target" ; then
+      idsearch="$idsearch $target"
+    fi
+  done
+}
+
+# Returns the list of existing LUNs
+getluns ()
+{
+  if test ! -x /usr/bin/sg_luns; then return ""; fi
+  sgdevice
+  if test -z "$SGDEV"; then return ""; fi
+  sg_luns -d /dev/$SGDEV | sed -n 's/.*lun=\(.*\)/\1/p'
+}
+
+# Perform scan on a single lun
+dolunscan()
+{
+  SCSISTR=
+  devnr="$host $channel $id $lun"
+  echo "Scanning for device $devnr ..."
+  printf "${yellow}OLD: $norm"
+  testexist
+  : f $remove s $SCSISTR
+  if test "$remove" -a "$SCSISTR"; then
+    # Device exists: Test whether it's still online
+    # (testonline returns 1 if it's gone or has changed)
+    testonline
+    if test $? = 1 -o ! -z "$forceremove"; then
+      echo -en "\r\e[A\e[A\e[A${red}REM: "
+      echo "$SCSISTR" | head -n1
+      echo -e "${norm}\e[B\e[B"
+      if test -e /sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device; then
+        echo 1 > /sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device/delete
+        # Try reading, should fail if device is gone
+        echo "$channel $id $lun" > /sys/class/scsi_host/host${host}/scan
+      else
+        echo "scsi remove-single-device $devnr" > /proc/scsi/scsi
+        # Try reading, should fail if device is gone
+        echo "scsi add-single-device $devnr" > /proc/scsi/scsi
+      fi
+    fi
+    printf "\r\x1b[A\x1b[A\x1b[A${yellow}OLD: $norm"
+    testexist
+    if test -z "$SCSISTR"; then
+      printf "\r${red}DEL: $norm\r\n\n"
+      let rmvd+=1;
+    fi
+  fi
+  if test -z "$SCSISTR"; then
+    # Device does not exist, try to add
+    printf "\r${green}NEW: $norm"
+    if test -e /sys/class/scsi_host/host${host}/scan; then
+      echo "$channel $id $lun" > /sys/class/scsi_host/host${host}/scan 2> /dev/null
+    else
+      echo "scsi add-single-device $devnr" > /proc/scsi/scsi
+    fi
+    testexist
+    if test -z "$SCSISTR"; then
+      # Device not present
+      printf "\r\x1b[A";
+      # Optimization: if lun==0, stop here (only if in non-remove mode)
+      if test $lun = 0 -a -z "$remove" -a $optscan = 1; then 
+        break;
+      fi
+    else 
+      let found+=1; 
+    fi
+  fi
+}
+
+# Perform report lun scan
+doreportlun()
+{
+  lun=0
+  SCSISTR=
+  devnr="$host $channel $id $lun"
+  echo "Scanning for device $devnr ..."
+  printf "${yellow}OLD: $norm"
+  testexist
+  if test -z "$SCSISTR"; then
+    # Device does not exist, try to add
+    printf "\r${green}NEW: $norm"
+    if test -e /sys/class/scsi_host/host${host}/scan; then
+      echo "$channel $id $lun" > /sys/class/scsi_host/host${host}/scan 2> /dev/null
+    else
+      echo "scsi add-single-device $devnr" > /proc/scsi/scsi
+    fi
+    testexist
+    if test -z "$SCSISTR"; then
+      # Device not present
+      printf "\r\x1b[A";
+      lunsearch=
+      return
+    fi
+  fi
+  lunsearch=`getluns`
+  lunremove=
+  # Check existing luns
+  for dev in /sys/class/scsi_device/$host\:$channel\:$id\:*; do
+    lun=${dev##*:}
+    newsearch=
+    oldsearch="$lunsearch"
+    for tmplun in $lunsearch; do
+      if test $tmplun -eq $lun ; then
+	# Optimization: don't scan lun 0 again
+	if [ $lun -ne 0 ]; then
+	  dolunscan
+	fi
+      else
+	newsearch="$newsearch $tmplun"
+      fi
+    done
+    if [ "${#oldsearch}" = "${#newsearch}" ] ; then
+	# Stale lun
+	lunremove="$lunremove $lun"
+    fi
+    lunsearch="$newsearch"
+  done
+  # Add new ones and check stale ones
+  for lun in $lunsearch $lunremove; do
+    dolunscan
+  done
+}
+  
 # Perform search (scan $host)
 dosearch ()
 {
+  if test -z "$channelsearch" ; then
+    chanlist
+  fi
   for channel in $channelsearch; do
+    if test -z "$idsearch" ; then
+      idlist
+    fi
     for id in $idsearch; do
-      for lun in $lunsearch; do
-        SCSISTR=
-	devnr="$host $channel $id $lun"
-	echo "Scanning for device $devnr ..."
-	printf "${yellow}OLD: $norm"
-	testexist
-	if test ! -z "$remove" -a ! -z "$SCSISTR"; then
-	  # Device exists: Test whether it's still online
-	  # (testonline returns 1 if it's gone or has changed)
-	  testonline
-	  if test $? = 1 -o ! -z "$forceremove"; then
-	    echo -en "\r\e[A\e[A\e[A${red}REM: "
-	    echo "$SCSISTR" | head -n1
-	    echo -e "${norm}\e[B\e[B"
-	    if test -e /sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device; then
-	      echo 1 > /sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device/delete
-	      # Try readding, should fail if device is gone
-	      echo "$channel $id $lun" > /sys/class/scsi_host/host${host}/scan
-	    else
-	      echo "scsi remove-single-device $devnr" > /proc/scsi/scsi
-	      # Try readding, should fail if device is gone
-	      echo "scsi add-single-device $devnr" > /proc/scsi/scsi
-	    fi
-          fi
-	  printf "\r\x1b[A\x1b[A\x1b[A${yellow}OLD: $norm"
-	  testexist
-	  if test -z "$SCSISTR"; then
-	    printf "\r${red}DEL: $norm\r\n\n\n\n"
-	    let rmvd+=1;
-          fi
-	fi
-	if test -z "$SCSISTR"; then
-	  # Device does not exist, try to add
-	  printf "\r${green}NEW: $norm"
-	  if test -e /sys/class/scsi_host/host${host}/scan; then
-	    echo "$channel $id $lun" > /sys/class/scsi_host/host${host}/scan 2> /dev/null
-	  else
-	    echo "scsi add-single-device $devnr" > /proc/scsi/scsi
-	  fi
-	  testexist
-	  if test -z "$SCSISTR"; then
-	    # Device not present
-	    printf "\r\x1b[A";
-  	    # Optimization: if lun==0, stop here (only if in non-remove mode)
-	    if test $lun = 0 -a -z "$remove" -a $optscan = 1; then 
-	      break;
-	    fi  
-	  else 
-	    let found+=1; 
-	  fi
-	fi
-      done
+      if test -z $lunsearch ; then
+	doreportlun
+      else
+	for lun in $lunsearch; do
+          dolunscan
+        done
+      fi
     done
   done
 }
@@ -272,7 +406,9 @@
     echo " -w      scan for target device IDs 0 .. 15 [default: 0-7]"
     echo " -c      enables scanning of channels 0 1   [default: 0]"
     echo " -r      enables removing of devices        [default: disabled]"
+    echo " -i      issue a FibreChannel LIP reset     [default: disabled]"
     echo "--remove:        same as -r"
+    echo "--issue-lip:     same as -i"
     echo "--forceremove:   Remove and readd every device (DANGEROUS)"
     echo "--nooptscan:     don't stop looking for LUNs is 0 is not found"
     echo "--color:         use coloured prefixes OLD/NEW/DEL"
@@ -318,7 +454,7 @@
 
 # defaults
 unsetcolor
-lunsearch="0"
+lunsearch=""
 idsearch=`seq 0 7`
 channelsearch="0"
 remove=
@@ -340,6 +476,7 @@
     w) idsearch=`seq 0 15` ;;
     c) channelsearch="0 1" ;;
     r) remove=1 ;;
+    i) lipreset=1 ;;
     -remove)      remove=1 ;;
     -forceremove) remove=1; forceremove=1 ;;
     -hosts=*)     arg=${opt#-hosts=};   hosts=`expandlist $arg` ;;
@@ -348,6 +485,7 @@
     -luns=*)  arg=${opt#-luns=};        lunsearch=`expandlist $arg` ;; 
     -color) setcolor ;;
     -nooptscan) optscan=0 ;;
+    -issue-lip) lipreset=1 ;;
     *) echo "Unknown option -$opt !" ;;
   esac
   shift
@@ -359,15 +497,33 @@
   hosts=$*; 
 fi
 
-echo "Scanning hosts $hosts channels $channelsearch for "
-echo " SCSI target IDs " $idsearch ", LUNs " $lunsearch
+echo "Scanning SCSI subsystem for new devices"
 test -z "$remove" || echo " and remove devices that have disappeared"
 declare -i found=0
 declare -i rmvd=0
-for host in $hosts; do 
-  # YOU MAY NEED TO UNCOMMENT THESE TO ALLOW FOR A RESCAN
-  #test -e /sys/class/fc_host/host$host/issue_lip && echo 1 > /sys/class/fc_host/host$host/issue_lip 2> /dev/null;
-  #echo "- - -" > /sys/class/scsi_host/host$host/scan 2> /dev/null;
+for host in $hosts; do
+  echo -n "Scanning host $host "
+  if test -e /sys/class/fc_host/host$host ; then
+    # It's pointless to do a target scan on FC
+    if test -n "$lipreset" ; then
+      echo 1 > /sys/class/fc_host/host$host/issue_lip 2> /dev/null;
+      echo "- - -" > /sys/class/scsi_host/host$host/scan 2> /dev/null;
+    fi
+    channelsearch=""
+    idsearch=""
+  fi
+  [ -n "$channelsearch" ] && echo -n "channels $channelsearch "
+  echo -n "for "
+  if [ -n "$idsearch" ] ; then
+      echo -n " SCSI target IDs " $idsearch
+  else
+      echo -n " all SCSI target IDs"
+  fi
+  if [ -n "$lunsearch" ] ; then
+      echo ", LUNs " $lunsearch
+  else
+      echo ", all LUNs"
+  fi
   dosearch; 
 done
 echo "$found new device(s) found.               "
================================================================

---- CVS-web:
    http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/SOURCES/rescan-scsi-bus.sh?r1=1.5&r2=1.6&f=u



More information about the pld-cvs-commit mailing list