Vous êtes sur la page 1sur 27

#!/bin/bash # QLogic FC HBA LUN Scan Utility # Copyright (C) 2006 QLogic Corporation (www.qlogic.

com) # #This program is free software; you can redistribute it and/or modify #it under the terms of the GNU General Public License as published by #the Free Software Foundation; either version 2 of the License, or #(at your option) any later version. # #This program is distributed in the hope that it will be useful, #but WITHOUT ANY WARRANTY; without even the implied warranty of #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #GNU General Public License for more details. # #You should have received a copy of the GNU General Public License #along with this program; if not, write to the Free Software #Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #--------------------------------------------------------------------------# #This script is used to scan the QLogic HBAs for all the LUNs. #By default find all QLogic HBAs and start scanning all targets and all LUNs #---------------------------------------------------------------------------# QL_DISABLE_WARNING=0 # This variable set to 1 will disable warning message. QL_ATTR_VALUE="Unknown" #Global for storing value QL_HOST=() #list of QL HBAs QL_TARGETS=() QL_LUNS=() DEVICE_TYPES=(disk tape printer process worm cd\/dvd scanner optical mediumx comms \(0xa\) \(0xb\) storage enclosu "sim dsk" "opti rd" bridge o sd adi \(0x13\) \(0x14\) \(0x15\) \(0x16\) \(0x17\) \(0x18\) \(0x19\) \(0x1a\) \ (0x1b\) \(0x1c\) \(0x1e\) \(0x18\) \(0x19\) \(0x1a\) \(0x1b\) \(0x1c\) \(0x1e\) wlun "no dev") QL_KERNEL_VERSION=`uname -r` QL_K_MAJ_MIN=`echo ${QL_KERNEL_VERSION} | cut -d . -f -2` QL_PROC_SCSI="/proc/scsi" QL_DRIVER="qla2xxx" QL_SCAN_LUNS=256 QL_CHANNEL=0 QL_REFRESH=0 QL_SCAN=0 QL_INTERACTIVE=0 QL_HELP=0 QL_CURRENT_LUNS=0 QL_SYSFS=1 QL_PROCFS=2 QL_FS=$QL_SYSFS QL_CALL_RETURNED=2 QL_CALL_AGAIN=3 NOW_FOUND=() NOW_LOST=() TEST_UNIT_READY=1 QL_DISTRUCTIVE_REFRESH=0 QLU_VERSION=2.3 QLU_LUN_SCAN=$0 QL_SUCCESS=0

QL_FAIL=1 # # # # # # # # # # --------------------------------------------------------qlu_sys_find_all_host() Look into the /sys/bus/pci/drivers/qla*/ dir to find all HBAs in the system Parameter: None Returns: Fill up the QL_HOST array, returns number of hosts found --------------------------------------------------------# # # # # # # # # #

function qlu_sys_find_all_host() { QL_HOST=( `ls -d /sys/bus/pci/drivers/qla*/*/host* 2> /dev/null | sed -e "s/.*host//"` ) return ${#QL_HOST[@]} } # # # # # # # # # # --------------------------------------------------------qlu_find_all_host() Look into the /proc/scsi/qla2xxx[qla2300] dir to find all HBAs in the system Parameter: None Returns: Fill up the QL_HBA array, returns number of hosts found --------------------------------------------------------# # # # # # # # # #

function qlu_find_all_host() { #look into proc file to find all the #HBAs QL_HOST=( `ls ${QL_PROC_SCSI}/${QL_DRIVER}/ 2> /dev/null | grep -v -i "H BA" 2> /dev/null` ) return ${#QL_HOST[@]} } # --------------------------------------------------------# qlu_is_lun_present() # Check to see if the LUN is already discovered # Parameter: # Host:Channel:Device:Lun # Returns: # QL_SUCCESS: If LUN present # QL_FAIL: If LUN absent # --------------------------------------------------------function qlu_is_lun_present() { local LUN let IN_HOST=$1 let IN_CHANNEL=$2 let IN_DEVICE=$3 let IN_LUN=$4 #check the /proc/scsi/scsi to see if the lun is #present or not #assuming the format of the string would be always # Host: scsi0 Channel: 00 Id: 00 Lun: 00 # # # # # # # # #

if [ ${IN_CHANNEL} -lt 10 ]; then IN_CHANNEL="0${IN_CHANNEL}" fi if [ ${IN_DEVICE} -lt 10 ]; then IN_DEVICE="0${IN_DEVICE}" fi if [ ${IN_LUN} -lt 10 ]; then IN_LUN="0${IN_LUN}" fi LUN_STR="Host: scsi${IN_HOST} Channel: ${IN_CHANNEL} Id: ${IN_DEVICE} Lu n: ${IN_LUN}" #echo "Looking for LUN: $LUN_STR" cat ${QL_PROC_SCSI}/scsi | grep "$LUN_STR" >& /dev/null if [ $? -eq 0 ]; then return $QL_SUCCESS fi return ${QL_FAIL} } # --------------------------------------------------------- # # qlu_add_lun() # # Calls the add-single-device # # Parameter: # # Host:Channel:Device:Lun # # Returns: # # None # # --------------------------------------------------------- # function qlu_add_lun() { echo "scsi add-single-device $*" > $QL_PROC_SCSI/scsi } # --------------------------------------------------------- # # qlu_remove_lun() # # Calls the remove-single-device # # Parameter: # # Host:Channel:Device:Lun # # Returns: # # None # # --------------------------------------------------------- # function qlu_remove_lun() { echo "scsi remove-single-device $*" > $QL_PROC_SCSI/scsi } # --------------------------------------------------------# See if driver scan is done # Parameter: # $1: Proc file name # $2: Host number # Returns: # None # --------------------------------------------------------qlu_scan_done() { # # # # # # # #

local local local local

PROC_FILE=$1 HOST=$2 DELAY=1 ITERATION=10

echo -n "..." while [ $ITERATION -ge 1 ] do #in any case sleep for 2 secs echo -n "." sleep $DELAY #look for ( 0:17): Total reqs 0, Pending reqs 0, flags cat $PROC_FILE | grep -v "\(.*:[[:space:]]\+0\)" | grep "\(.*\): Total.*flags.*\*.*" >& /dev/null if [ $? -eq 0 ]; then break; fi (( ITERATION -= 1 )) done echo -e "" return } # --------------------------------------------------------- # # qlu_scan_host() # # Scans the host and uses "add-single-device" to add the # # device in OS # # Parameter: # # $*: Space separated list of hosts to be scanned # # Returns: # # None # # --------------------------------------------------------- # function qlu_scan_host() { local LUN test -z "$1" && echo "Host list empty." && return 1; for HOST in $* do #2.4 tell driver to do re-scan first echo "Scanning HOST: scsi${HOST}" PROC_FILE=${QL_PROC_SCSI}/${QL_DRIVER}/${HOST} if [ -e "${PROC_FILE}" ]; then echo "scsi-qlascan" > ${PROC_FILE} #call qlu_scan_done to check if scan finished qlu_scan_done ${PROC_FILE} $HOST # get target for this host DEVICES=( `cat ${PROC_FILE} | grep "\-target\-" | sed "s /.*target-\(.*\)=.*/\1/"` ) if [ ${#DEVICES[@]} -eq 0 ]; then echo "No devices attached to HOST: scsi${HOST}" echo "" continue; fi for DEVICE in ${DEVICES[@]} do

echo "Scanning DEVICE: ${DEVICE}" #scan all the luns for ((LUN=0; ${LUN} <= ${QL_SCAN_LUNS}; LUN++)) do #check id LUN present qlu_is_lun_present ${HOST} ${QL_CHANNEL} ${DEVICE} ${LUN} WAS_LUN_PRESENT=$? #does user wants to refresh if [ ${QL_REFRESH} -eq 1 ]; then ql_sg_map_n_sg_tur $HOST $DEVICE $LUN if [ "$TEST_UNIT_READY" != "0" ] ; then qlu_remove_lun ${HOST} $ {QL_CHANNEL} ${DEVICE} ${LUN} fi elif [ ${LUN} -eq 0 ]; then qlu_handle_LUNZ ${HOST} ${QL_CHA NNEL} ${DEVICE} fi qlu_add_lun ${HOST} ${QL_CHANNEL} ${DEVI CE} ${LUN} #check if a new one found qlu_is_lun_present ${HOST} ${QL_CHANNEL} ${DEVICE} ${LUN} if [ ${WAS_LUN_PRESENT} -ne $? ] && [ ${WAS_LUN_PRESENT} -eq ${QL_FAIL} ] ; then echo "Found LUN: ${LUN} on HOST: scsi${HOST}, DEVICE: ${DEVICE}" fi done done else echo "Error: ${PROC_FILE} does not exist..." echo "Skipping scan for HOST: scsi${HOST}..." fi done } # --------------------------------------------------------# qlu_display_host_info # Display the values from /proc/scsi/scsi # Parameter: # $1: Host number # Returns: # None # --------------------------------------------------------function qlu_display_host_info() { DISPLAY_ALL=0 LOCAL_HOST=( ) if [ "$1" = "" ]; then #display all hosts DISPLAY_ALL=1 fi if [ ${DISPLAY_ALL} -eq 1 ]; then #get list of all hosts first # # # # # # # #

if [ $QL_FS -eq $QL_PROCFS ]; then qlu_find_all_host else qlu_sys_find_all_host fi if [ $? -eq 0 ]; then echo "QLogic Host not found..." echo "Please check if QLogic module is loaded or not..." echo "Aborting display information..." return ${QL_FAIL} fi LOCAL_HOST=( ${QL_HOST[@]} ) else LOCAL_HOST=( $1 ) fi #get a local copy of proc cat ${QL_PROC_SCSI}/scsi > ./local_scsi.txt if [ ! -e "./local_scsi.txt" ]; then echo "Unable to create copy of /proc/scsi/scsi" echo "Aborting display information..." return ${QL_FAIL} fi #read /proc/scsi/scsi for each host DISPLAY_NEXT=0 MAX_DISP_COUNT=2 DISPLAY_COUNT=0 DEVICE_FOUND=0 echo "" for HOST in ${LOCAL_HOST[@]} do while read LINE do if [ ${DISPLAY_NEXT} -eq 1 ]; then if [ ${DISPLAY_COUNT} -eq ${MAX_DISP_COU NT} ]; then DISPLAY_NEXT=0 DISPLAY_COUNT=0 else echo "$LINE" ((DISPLAY_COUNT += 1)) fi fi echo "$LINE" | grep "scsi${HOST}" >& /dev/null if [ $? -eq ${QL_SUCCESS} ]; then echo "$LINE" DEVICE_FOUND=1 DISPLAY_NEXT=1 fi done < ./local_scsi.txt #check if device found if [ ${DEVICE_FOUND} -eq 0 ]; then echo "No device found on Host ${HOST}" else #reset DEVICE_FOUND for next host DEVICE_FOUND=0 fi done rm ./local_scsi.txt >& /dev/null echo ""

} ############################## # --------------------------------------------------------# qlu_display_current_luns() # Displays luns present currently # Parameter: None. # Returns: None. # --------------------------------------------------------# # # # # #

function qlu_display_current_luns() { local LUN echo "" echo_b "DEVICE" echo "" echo_b "[H:C:T:L]" echo "" for HOST in ${QL_HOST[@]} do get_targets $HOST for TARGET in ${QL_TARGETS[@]} do get_luns ${HOST} ${TARGET} if [ $? -eq 0 ]; then echo "No LUNs on Host$HOST Target$TARGET" else QL_SORTED_LUNS=(`echo ${QL_LUNS[@]} | sed "s/ /\ \n/g" | sort -n`) for LUN in ${QL_SORTED_LUNS[@]} do echo_b "[$HOST:0:$TARGET:$LUN]" echo "" done fi done done } # --------------------------------------------------------# get_targets () # Detects all the targets connected to given host and fills # QL_TARGETS array # Parameters : # HOST # Returns : # Number of targets # --------------------------------------------------------function get_targets { local HOST=${1} local TARGET local TARGETS=() # # # # # # # # #

if [ -e /sys/class/scsi_host/host$HOST/device/ ]; then cd /sys/class/scsi_host/host$HOST/device/ ls -d rport-$HOST:0-* &> /dev/null if [ $? -eq 0 ]; then

QL_TARGETS=( `ls -d rport-$HOST:0-* | sed "s/rport-$HOST :0-//"` ) fi ls -d target$HOST:0:* &> /dev/null if [ $? -eq 0 ]; then QL_TARGETS=( `ls -d target$HOST:0:* | sed "s/target$HOST :0://"` ) fi ls -d $HOST:0:* &> /dev/null if [ $? -eq 0 ]; then TARGETS=`ls -d $HOST:0:* | sed "s/$HOST:0:\(.*\):.*/\1/" ` for TARGET in ${TARGETS[@]} do echo "${QL_TARGETS[@]}" | grep -w $TARGET >& /de v/null if [ $? -ne 0 ]; then QL_TARGETS=(${QL_TARGETS[@]} $TARGET) fi done fi fi return ${#QL_TARGETS[@]} } # # # # # # # # # --------------------------------------------------------get_proc_targets () Detects all the targets connected to given host and fills QL_TARGETS array. This works proc based Parameters : HOST Returns : Number of targets --------------------------------------------------------# # # # # # # # #

function get_proc_targets { local HOST=$1 local TARGET="" QL_TARGETS=() TARGETS=`cat $HOST | grep "^(.*:" | grep -v "Id:Lun" | sed "s/(\(.*\):.* ).*/\1/"` for TARGET in $TARGETS do echo "${QL_TARGETS[@]}" | grep -w $TARGET >& /dev/null if [ $? -ne 0 ]; then QL_TARGETS=(${QL_TARGETS[@]} $TARGET) fi done return ${#QL_TARGETS[@]} } # --------------------------------------------------------- # # get_proc_luns () # # Detects all the LUNS connected to given TARGET and fills #

# # # # # #

QL_LUNS array, this works on proc based scanning. Parameters : <HOST> <TARGET> Returns : Number of LUNS ---------------------------------------------------------

# # # # # #

function get_proc_luns { local HOST=$1 local TARGET=$2 local LUN QL_LUNS=() LUNS=`cat $HOST | sed "s/ //g" | grep "^(${TARGET}:" | sed "s/(${TARGET}:\(.*\)) .*/\1/"` for LUN in $LUNS do echo "${QL_LUNS}" | grep -w $LUN >& /dev/null if [ $? -ne 0 ]; then QL_LUNS=(${QL_LUNS[@]} $LUN) fi done return ${#QL_LUNS[@]} } # --------------------------------------------------------# get_luns () # Detects all the LUNS connected to given TARGET and fills # QL_LUNS array # Parameters : # <HOST> <TARGET> # Returns : # Number of LUNS # --------------------------------------------------------function get_luns { local HOST=${1} local TARGET=${2} ]; then cd /sys/class/scsi_host/host$HOST/device/target${HOST}:0:${TARGE T}/ elif [ -e /sys/class/scsi_host/host$HOST/device/rport-$HOST:0-$TARGET/ta rget${HOST}:0:${TARGET} ]; then cd /sys/class/scsi_host/host$HOST/device/rport-$HOST:0-$TARGET/t arget${HOST}:0:${TARGET}/ elif [ -e /sys/class/fc_transport/target${HOST}:0:${TARGET}/device ]; th en cd /sys/class/fc_transport/target${HOST}:0:${TARGET}/device/ fi QL_LUNS=( `ls -d $HOST:0:$TARGET:* 2> /dev/null | sed "s/$HOST:0:$TARGET ://"` ) return ${#QL_LUNS[@]} } # --------------------------------------------------------- # # qlu_proc_display_current_luns() # # # # # # # # # #

if [ -e /sys/class/scsi_host/host$HOST/device/target${HOST}:0:${TARGET}

# Displays luns present currently # using proc filesystem # Parameter: None. # Returns: None. # --------------------------------------------------------function qlu_proc_display_current_luns() { local LUN cd /proc/scsi/qla2xxx # # qlu_scan_host "${QL_HOST[@]}" return $?

# # # # #

for HOST in ${QL_HOST[@]} do get_proc_targets $HOST if [ $? -ne 0 ]; then echo "" echo_b "Device " echo "" echo_b "[H:C:T:L]" echo "" fi for TARGET in ${QL_TARGETS[@]} do get_proc_luns $HOST $TARGET if [ $? -ne 0 ]; then QL_SORTED_LUNS=(`echo ${QL_LUNS[@]} | sed "s/ /\\n/g" | sort -n` ) for LUN in ${QL_SORTED_LUNS[@]} do echo_b "[$HOST:0:$TARGET:$LUN]" echo "" done else echo "" return 0 fi done done } ############################## # # # # # # # --------------------------------------------------------echo_b() Prints messages in bold Parameter: $1 Message to be printed Returns: None. --------------------------------------------------------# # # # # # #

function echo_b() { echo -en "\033[1m${1}\033[0m" tput sgr0 } # --------------------------------------------------------- #

# qlu_help () # # Prints the help message LUN scan utility # # Parameter: None # # Returns: None # # --------------------------------------------------------- # function qlu_help() { echo "" echo_b "QLogic Linux LUN Scan Utility v$QLU_VERSION" echo "" echo "" echo "To begin scanning the LUNs issue following command:" echo "" echo " # ${QLU_LUN_SCAN}" echo "" echo "Usage: ${QLU_LUN_SCAN} [OPTIONS]" echo "" echo " -cl, --current-luns" echo " Displays LUNS currently present" echo "" echo " -h, --help, ?" echo " Prints this help message" echo "" echo " -i, --interactive" echo " Use this option to use the menu driven pro gram" echo "" echo " -p, --proc" echo " Use PROC file system for LUN scanning" echo "" echo " -r, --refresh" echo " To refresh, that is remove LUNs that are l ost" echo " use the options \"-r|--refresh\". This wil l" echo " remove the LUNs which no more exist." echo "" echo " -s, --scan [-r|--refresh]" echo " The QLogic LUN scan utility re-scans all t he" echo " devices connected to the QLogic HBA" } # # # # # # # --------------------------------------------------------ql_check_distro () Checks if the driver is not a distro release by checking for "d" in end Parameter: None Returns: QL_FAIL/QL_SUCCESS --------------------------------------------------------# # # # # # #

function ql_check_distro { local HOST=$1 PROC_FILE=${QL_PROC_SCSI}/${QL_DRIVER}/${HOST} if [ -e ${PROC_FILE} ]; then cat /proc/scsi/$QL_DRIVER/$HOST | grep "Driver version" | sed "s/.* version\ //" | grep "d" &> /dev/null return $?

fi } # --------------------------------------------------------# qlu_main () # The main function to scan the hosts # Parameter: None # Returns: Return of scan # --------------------------------------------------------function qlu_main() { # # # # # #

if [ $QL_FS == $QL_PROCFS ]; then qlu_find_all_host if [ $? -eq 0 ]; then echo "QLogic Host not found..." echo "Please check if QLogic module is loaded or not..." exit 1 fi qlu_scan_host "${QL_HOST[@]}" return $? else qlu_sys_find_all_host if [ $? -eq 0 ]; then echo "QLogic Host not found..." echo "Please check if QLogic module is loaded or not..." exit 1 fi for HOST in ${QL_HOST[@]} do PROC_FILE=${QL_PROC_SCSI}/${QL_DRIVER}/${HOST} if [ -e ${PROC_FILE} ]; then echo "scsi-qlascan" > ${PROC_FILE} fi done #ir-respective of /proc/scsi/qla***/* scan for hosts qlu_sys_scan_host "`echo ${QL_HOST[@]}`" fi } #Validate kernel version case ${QL_K_MAJ_MIN} in 2.4) QL_DRIVER="qla2300" QL_FS=$QL_PROCFS ;; 2.6) QL_DRIVER="qla2xxx" ;; * ) echo "Kernel ${QL_KERNEL_VERSION} not yet supported."; exit 1; ;; esac #====Menu Start===== #----------------------------------------# # qlu_hit_any_key()

# Waits for user to hist a key # PARAMETERS : NONE # RETURNS : None #----------------------------------------# function qlu_hit_any_key() { echo -n "Hit any key to continue.........." read -n 1 clear } #----------------------------------------# # qlu_main_screen() # Prints the main menu of the program # PARAMETERS : NONE # RETURNS : QL_SUCCESS or QL #----------------------------------------# function qlu_main_screen() { STATUS="" echo " Welcome to QLogic LUN Scan Utility" echo "====================================" echo "" echo "MAIN MENU" echo " 1: ALL HOSTS SCAN" echo " 2: ALL HOST SCAN & REFRESH" echo " 3: SELECT HOST TO SCAN" echo " 4: SET MAX LUN's TO SCAN (Current: ${QL_SCAN_LUNS})" echo " 5: DISPLAY CURRENT LUNS" echo " 6: QUIT" echo "" echo -n "Please select one of the options above : " read SC1_CHOICE # read user choice for qlu_main_screen case $SC1_CHOICE in 1) echo "" qlu_main echo "" qlu_hit_any_key return $QL_CALL_AGAIN ;; 2) echo "" QL_REFRESH=1 qlu_main echo "" qlu_hit_any_key return $QL_CALL_AGAIN ;; 3) STATUS=$QL_CALL_AGAIN clear while [ $STATUS -eq $QL_CALL_AGAIN ]

do qlu_screen_2 STATUS=$? done if [ $STATUS -eq $QL_CALL_RETURNED ];then clear return $QL_CALL_AGAIN else return $STATUS fi ;; 4) echo -n "Enter the value for maximum LUNs : " read MAXLUN if [ ! -z "$MAXLUN" ]; then echo "$MAXLUN" | grep "[0-9]\+" >& /dev/null RET1=$? RET2=`echo "$MAXLUN" | wc -L` if [ $RET1 -ne 0 ] || [ $RET2 -gt 5 ] || [ $MAXLUN -gt 65536 ] | | [ $MAXLUN -lt 1 ]; then echo "ERROR: Invalid value, enter the value in range [165536]" qlu_hit_any_key else QL_SCAN_LUNS=$MAXLUN clear fi fi return $QL_CALL_AGAIN ;; 5) if [ $QL_FS == $QL_PROCFS ]; then qlu_find_all_host if [ $? -eq 0 ]; then echo "QLogic Host not found..." echo "Please check if QLogic module is loaded or not..." exit 1 else # # qlu_proc_display_current_luns | more fi qlu_scan_host "${QL_HOST[@]}" return $? else qlu_sys_find_all_host if [ $? -eq 0 ]; then echo "QLogic Host not found..." echo "Please check if QLogic module is loaded or not..." exit 1 else # cd /sys/class/scsi_device qlu_display_current_luns | more fi fi qlu_hit_any_key clear

return $QL_CALL_AGAIN ;; 6 | q | Q | quit) exit 0 ;; *) clear return $QL_CALL_AGAIN ;; esac } #----------------------------------------# # qlu_screen_2() # Prints the Host list # PARAMETERS : NONE # RETURNS : NONE #----------------------------------------# function qlu_screen_2() { #HQ=$QL_HOST # HQ for host quantity HQ=( ) LN=1 # LN for Line Number if [ $QL_FS == $QL_PROCFS ]; then qlu_find_all_host RETURN_VAL=$? else qlu_sys_find_all_host RETURN_VAL=$? fi if [ $RETURN_VAL -eq 0 ]; then echo "" echo "" echo "No Host found to display" echo "" echo "" else echo "List of available Hosts" fi HQ=( ${QL_HOST[@]} ) for HOST in ${HQ[@]} do echo " $LN. HOST: scsi${HOST}" LN=$((LN+1)) done if [ $QL_REFRESH -eq 0 ];then SCAN_STATUS="SCAN ONLY" elif [ $QL_REFRESH -eq 1 ];then SCAN_STATUS="SCAN & REFRESH" fi echo " $LN. SET SCAN TYPE (Current : $SCAN_STATUS) " echo " $((LN+1)). GO BACK TO PREVIOUS SCREEN" echo " $((LN+2)). QUIT"

echo -n "Please select one of the options above : " read SC2_CHOICE # read user choice for qlu_screen_2 case $SC2_CHOICE in q | Q | quit ) exit 0 ;; esac echo "$SC2_CHOICE" | grep "[0-9]\+" >& /dev/null if [ $? -ne 0 ];then clear return $QL_CALL_AGAIN fi if [ $SC2_CHOICE -ge 1 ];then if [ $SC2_CHOICE -le $(($LN-1)) ];then if [ $QL_FS == $QL_PROCFS ]; then qlu_scan_host ${HQ[((SC2_CHOICE-1))]} else qlu_sys_scan_host ${HQ[((SC2_CHOICE-1))]} fi echo "" qlu_hit_any_key return $QL_CALL_AGAIN elif [ $SC2_CHOICE -eq $LN ];then STATUS=$QL_CALL_AGAIN clear while [ $STATUS -eq $QL_CALL_AGAIN ] do qlu_screen_4 STATUS=$? done if [ $STATUS -eq $QL_CALL_RETURNED ];then clear return $QL_CALL_AGAIN else return $STATUS fi elif [ $SC2_CHOICE -eq $((LN+1)) ];then return $QL_CALL_RETURNED elif [ $SC2_CHOICE -eq $((LN+2)) ];then exit 0 else return $QL_CALL_AGAIN fi else return $QL_CALL_AGAIN fi } #----------------------------------------# # qlu_screen_32() # Prints the Host list for displaying information # PARAMETERS : Host count $1 # RETURNS : QL_SUCCESS/QL_FAIL #----------------------------------------#

function qlu_screen_32() { LN=1 # LN for Line Number echo "List of available Hosts" if [ $QL_FS == $QL_PROCFS ]; then qlu_find_all_host else qlu_sys_find_all_host fi if [ $? -eq 0 ]; then echo "No QLogic HBA found..." echo "Aborting display information..." return ${QL_FAIL} fi for HOST in ${QL_HOST[@]} do echo " $LN. HOST: scsi${HOST}" LN=$((LN+1)) done echo " $LN. GO BACK TO PREVIOUS SCREEN" echo " $((LN+1)). QUIT" echo -n "Please select one of the options above : " read SC2_CHOICE # read user choice for qlu_screen_2 case $SC2_CHOICE in q | Q | quit ) exit 0 ;; esac if [ $SC2_CHOICE -ge 1 ];then if [ $SC2_CHOICE -le ${#QL_HOST[@]} ];then qlu_display_host_info ${QL_HOST[(($SC2_CHOICE - 1))]} | more qlu_hit_any_key return $QL_CALL_AGAIN elif [ $SC2_CHOICE -eq $LN ];then return $QL_CALL_RETURNED elif [ $SC2_CHOICE -eq $((LN+1)) ];then exit 0 else return $QL_CALL_AGAIN fi else return $QL_CALL_AGAIN fi } #----------------------------------------# # qlu_screen_4() # Sets value of $QL_REFRESHED as asked by # user # PARAMETERS : NONE # RETURNS : NONE #----------------------------------------# function qlu_screen_4() { echo "SELECT SCAN TYPE"

echo echo echo echo read

" 1.HOST SCAN & REFRESH" " 2.HOST SCAN ONLY" " 3.RETURN TO PREVIOUS SCREEN" -n "Please select one of the options above : " SC4_CHOICE

case $SC4_CHOICE in 1) QL_REFRESH=1 echo "SCAN TYPE SET TO \"SCAN & REFRESH\"" qlu_hit_any_key return $QL_CALL_AGAIN ;; 2) QL_REFRESH=0 echo "SCAN TYPE SET TO \"SCAN ONLY\"" qlu_hit_any_key return $QL_CALL_AGAIN ;; 3) return $QL_CALL_RETURNED ;; q | Q | quit) exit 0 ;; *) return $QL_CALL_AGAIN ;; q | Q | quit ) exit 0 ;; esac } #====Menu End==== #===SysFS Menu=== function ql_compile_sg () { if [ -e "`ls | grep -m 1 sg3_utils`" ]; then SG_UTL=`ls | grep -m 1 sg3_utils` if [ -d "$SG_UTL" ]; then cd $SG_UTL else tar zxvf $SG_UTL &> /dev/null SG_UTL_DIR=`echo $SG_UTL | sed "s/\(.*\)\.tgz/\1/"` cd $SG_UTL_DIR fi # Everything is fine till here lets build the source make sg_map sg_turs &> /dev/null return $? else echo "ERROR: SG3 Utility not found" echo "Unable to determine devices to be refreshed." echo "Would you like to explicitly remove all the devices and rescan ? " echo "Note: This may make the system un-usable if the system is using"

echo "any of the devices attached to the QLogic HBAs" echo -n "Proceed? (Yes/No): " read CHOICE case ${CHOICE} in yes | y | YES ) QL_DISTRUCTIVE_REFRESH=1 return 1 ;; no | n | NO | * ) exit 0 ;; esac return 1 fi } function ql_execute_sg () { TEST_UNIT_READY=1 # Wash out previous value local HOST=$1 local TARGET=$2 local LUN=$3 DISK=`$SG_MAP -x | grep -w "$HOST 0 $TARGET $LUN" | cut -d " " -f 10` if [ "$DISK" != "" ]; then $SG_TURS $DISK &> /dev/null TEST_UNIT_READY=$? else # Fail TUR deliberately for controller LUN TEST_UNIT_READY=1 fi return } function ql_sg_map_n_sg_tur () { local HOST=$1 local TARGET=$2 local LUN=$3 if [ "$QL_DISTRUCTIVE_REFRESH" -eq "1" ]; then TEST_UNIT_READY=1 return fi SG_IS_THERE=0 # Assuming by default SG Utility is installed # Keep record so we dont end up this function in wrong dir CALL_DIR=`pwd` cd $ORG_DIR SG_TURS=`which sg_turs 2> /dev/null` if [ $? -eq 0 ]; then SG_MAP=`which sg_map 2> /dev/null` if [ $? -ne 0 ]; then SG_IS_THERE=1 # map not there fi else

SG_IS_THERE=1 # TUR not there fi if [ $SG_IS_THERE -eq 1 ]; then ql_compile_sg if [ $? -ne 0 ]; then if [ $QL_DISTRUCTIVE_REFRESH -eq 1 ]; then TEST_UNIT_READY=1 fi cd $CALL_DIR return 1 # Neither sg is available nor we are able to compile else SG_TURS="./sg_turs" SG_MAP="./sg_map" fi fi # Check if SG Module is loaded lsmod | cut -d " " -f 1 | grep sg &> /dev/null if [ $? -ne 0 ]; then # Try to load the module modprobe sg fi # Check if TUR ql_execute_sg $HOST $TARGET $LUN cd $CALL_DIR return } # # # # # # # # --------------------------------------------------------qlu_sys_remove_lun() Removes the device by echoing 1 to /device/delete Parameter: HOST number Returns: None --------------------------------------------------------# # # # # # # #

function qlu_sys_remove_lun () { HOST=$1 DIR=`pwd` cd /sys/class/scsi_device/ get_targets $HOST for TARGET in ${QL_TARGETS[@]} do get_luns ${HOST} ${TARGET} if [ $? -eq 0 ]; then echo "No LUNs for this host$HOST,target$TARGET pair" else for ((LUN=0; ${LUN} <= ${QL_SCAN_LUNS}; LUN++)) do echo ${QL_LUNS[@]} | grep -w $LUN &> /dev/null if [ $? -eq 0 ]; then ql_sg_map_n_sg_tur $HOST $TARGET $LUN # Remove only if TUR Fails if [ "$TEST_UNIT_READY" != "0" ]; then echo "1" > $HOST:0:$TARGET:$LUN/delete

fi fi done fi done cd $DIR return } # --------------------------------------------------------- # # ql_issue_lip_n_wait() # # Issues lip and waits for loop state = READY # # /sys/class/scsi_host/host$HOST/scan # # Parameter: # # HOST # # Returns: # # None # # --------------------------------------------------------- # function ql_issue_lip_n_wait { local HOST=$1 #local LOOP_STATE=1 echo "Issuing LIP on host$HOST" if [ -f /sys/class/fc_host/host$HOST/issue_lip ]; then echo "1" > /sys/class/fc_host/host$HOST/issue_lip fi #while [ $LOOP_STATE == 1 ]; #do # cat /proc/scsi/$QL_DRIVER/$HOST | grep "loop state = <READY>" # if [ $? == 0 ]; then # LOOP_STATE=0 # echo -n "DONE" # else # echo -n "." # sleep 1 # fi #done } # # # # # # # # --------------------------------------------------------ql_clean_LUNZ() Removes LUN 0 from the list of array if it's LUNZ (Controller LUN) using proc filesystem Parameter: None. Returns: None. --------------------------------------------------------# # # # # # # #

function ql_clean_LUNZ () { local LUN local MODEL local LUNS_SOURCE=() local LUNS_TEMP=() if [ "$1" == "ORG" ]; then LUNS_SOURCE=( ${LUNS_ORG[@]} ) else

LUNS_SOURCE=( ${LUNS_NEW[@]} ) fi for LUN in ${LUNS_SOURCE[@]} do LUN_NO=`echo $LUN | sed "s/.*:.*:.*:\(.*\)/\1/g" 2> /dev/null` if [ "$LUN_NO" == 0 ]; then MODEL_TEMP=`cat /sys/class/scsi_device/$LUN/device/model 2> /dev/null` MODEL=`echo $MODEL_TEMP | sed "s/\ $//g"` if [ "$MODEL" != LUNZ ]; then LUNS_TEMP=( ${LUNS_TEMP[@]} $LUN ) fi else LUNS_TEMP=( ${LUNS_TEMP[@]} $LUN ) fi done if [ $1 == ORG ]; then LUNS_ORG=( ${LUNS_TEMP[@]} ) else LUNS_NEW=( ${LUNS_TEMP[@]} ) fi } # --------------------------------------------------------# qlu_sys_scan_host() # Scans the host by echoing "- - -" to # /sys/class/scsi_host/host$HOST/scan # Parameter: # HOST/HOST list # Returns: # None # --------------------------------------------------------function qlu_sys_scan_host () { local TARGET local LUN HOST_LIST=(`echo $1`) local DIR=`pwd` cd /sys/class/scsi_device/ for HOST in ${HOST_LIST[@]} do LUNS_ORG=( `ls -d $HOST* 2> /dev/null` ) ql_clean_LUNZ ORG if [ $QL_REFRESH -eq 1 ]; then qlu_sys_remove_lun $HOST else qlu_handle_LUNZ $HOST fi ql_check_distro $HOST if [ $? -eq 0 ]; then ql_issue_lip_n_wait $HOST fi if [ -e /sys/class/scsi_host/host$HOST/scan ]; then echo "Scanning HOST: host${HOST}" PROC_FILE=${QL_PROC_SCSI}/${QL_DRIVER}/${HOST} # # # # # # # # #

if [ -e ${PROC_FILE} ]; then #call qlu_scan_done to check if scan finished qlu_scan_done ${PROC_FILE} $HOST fi #if not equalto default LUNS to scan if [ $QL_SCAN_LUNS -ne 256 ]; then for ((LUN=0; ${LUN} <= ${QL_SCAN_LUNS}; LUN++)) do echo "- - ${LUN}" > /sys/class/scsi_host /host$HOST/scan done else echo '- - -' > /sys/class/scsi_host/host$HOST/sc an fi LUNS_NEW=( `ls -d $HOST* 2> /dev/null` ) ql_clean_LUNZ NEW for LUN in `echo ${LUNS_NEW[@]}` do echo ${LUNS_ORG[@]} | grep -w $LUN &> /dev/null if [ $? -ne 0 ]; then NOW_FOUND=( ${NOW_FOUND[@]} "$LUN\\n" ) fi done for LUN in `echo ${LUNS_ORG[@]}` do echo ${LUNS_NEW[@]} | grep -w $LUN &> /dev/null if [ $? -ne 0 ]; then NOW_LOST=( ${NOW_LOST[@]} "$LUN\\n" ) fi done ls $HOST:0:* &> /dev/null if [ $? -ne 0 ]; then echo "No devices attached to HOST: host${HOST}" fi else echo "Expected Sysfs attribute" echo "/sys/class/scsi_host/host$HOST/scan not found" fi done if [ ${#NOW_FOUND[@]} -ne 0 ]; then echo -e "Found\n ${NOW_FOUND[@]}" fi if [ ${#NOW_LOST[@]} -ne 0 ]; then echo -e "Removed\n ${NOW_LOST[@]}" fi if [ ${#NOW_LOST[@]} -eq 0 ] && [ ${#NOW_FOUND[@]} -eq 0 ]; then echo -e "No changes discovered in existing devices." fi # Clean the arrays NOW_FOUND=()

NOW_LOST=() cd $DIR } # --------------------------------------------------------- # # qlu_handle_LUNZ() # # Parameter: # # HOST/Host:Channel:Device # # Returns: # # None # # --------------------------------------------------------- # function qlu_handle_LUNZ () { local HOST=$1 local DIR=`pwd` if [ $QL_FS != $QL_PROCFS ]; then cd /sys/class/scsi_device/ ls -d $HOST:0:*:0 &> /dev/null if [ $? == 0 ]; then for LUN in `ls -d $HOST:0:*:0` do #if clarion(vendor DGC) remove LUNZ cat ${LUN}/device/vendor | grep -w DGC > /dev/null if [ $? == 0 ]; then cat ${LUN}/device/model | grep -w LUNZ > /dev/nu ll if [ $? == 0 ]; then echo 1 > $LUN/device/delete fi fi done fi cd $DIR else cat /proc/scsi/scsi | grep "scsi$HOST.*Id:[[:space:]].*.*Lun:[[:space:]] 00" -A 1 | grep "Vendor:" | sed "s/Vendor:[[:space:]]\+\(.*\)[[:space:]]\+Model :[[:space:]]\+.*[[:space:]]\+Rev:[[:space:]]\+.*/\1/" | grep -w "DGC" > /dev/nu ll if [ $? -eq 0 ]; then cat /proc/scsi/scsi | grep "scsi$HOST.*Id:[[:space:]].*.*Lun:[[: space:]]00" -A 1 | grep "Vendor:" | sed "s/Vendor:[[:space:]]\+.*[[:space:]]\+M odel:[[:space:]]\+\(.*\)[[:space:]]\+Rev:[[:space:]]\+.*/\1/" | grep -w "LUNZ" > /dev/null if [ $? -eq 0 ]; then qlu_remove_lun ${HOST} ${QL_CHANNEL} ${D EVICE} 0 fi fi fi return } # # # # # # --------------------------------------------------------qlu_warning_msg () Parameter: HOST/HOST list Returns: None # # # # # #

# --------------------------------------------------------- # function qlu_warning_msg () { if [ $QL_DISABLE_WARNING == 1 ]; then return fi local CHOICE echo_b "Please make sure there is no active I/O before running this script" echo "" echo_b "Do you want to continue: (yes/no)? " read CHOICE case ${CHOICE} in yes | y | YES ) return ;; no | n | NO | * ) exit 1 ;; esac } #===SysFS Menu End=== # Start if [ "$1" == "-h" ] || [ "$1" == "--help" ] || [ "$1" == "?" ] || [ "$1" == "-cl " ] || [ "$1" == "--current-luns" ]; then QL_DISABLE_WARNING=1 fi qlu_warning_msg # Lets check our current DIR, so needed if we need to complie SG utility ORG_DIR=`pwd` #scan input parameters if [ $# -ne 0 ]; then # need to loop thru the args while [ $# -gt 0 ]; do case "$1" in -p | --proc ) QL_FS=${QL_PROCFS} ;; -h | --help | \? ) QL_HELP=$(($QL_HELP+1)) ;; -i | --interactive ) QL_INTERACTIVE=$((QL_INTERACTIVE+1)) ;; -r | --refresh ) QL_REFRESH=$(($QL_REFRESH+1))

;; -cl | --current-luns ) QL_CURRENT_LUNS=$((QL_CURRENT_LUNS+1)) ;; -s | --scan ) QL_SCAN=$(($QL_SCAN+1)) ;; * ) echo "$1 Option not supported" exit 1 ;; esac shift #Check next set of parameters. done else #by default do the scan QL_SCAN=1 fi QL_OPT_TOTAL=$(($QL_HELP+$QL_INTERACTIVE+$QL_SCAN+$QL_CURRENT_LUNS)) if [ $QL_OPT_TOTAL != "1" ]; then echo "Please select valid combination of option/s" echo "see $0 -h for help" elif [ $QL_SCAN == 1 ]; then qlu_main elif [ $QL_HELP == 1 ]; then clear qlu_help elif [ $QL_CURRENT_LUNS == 1 ]; then if [ $QL_FS == $QL_PROCFS ]; then qlu_find_all_host if [ $? -eq 0 ]; then echo "QLogic Host not found..." echo "Please check if QLogic module is loaded or not..." exit 1 else qlu_proc_display_current_luns | more fi else qlu_sys_find_all_host if [ $? -eq 0 ]; then echo "QLogic Host not found..." echo "Please check if QLogic module is loaded or not..." exit 1 else qlu_display_current_luns | more fi fi elif [ $QL_INTERACTIVE == 1 ]; then STATUS=$QL_CALL_AGAIN QL_REFRESH=0 # ignore refresh if user has selected along with -i clear while [ $STATUS -eq $QL_CALL_AGAIN ] do qlu_main_screen

STATUS=$? done exit 0 fi