#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 1999,2005 # All Rights Reserved # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # IBM_PROLOG_END_TAG # @(#)85 1.46 src/avs/fs/mmfs/ts/admin/mmlsdisk.sh, mmfs, avs_rgpfs24, rgpfs240610b 10/6/05 10:56:32 ######################################################################### # # Usage: # # mmlsdisk Device [-d "DiskName[;DiskName]"] [-e] [-L] # # mmlsdisk Device [-d "DiskName[;DiskName]"] {-m | -M} # # where # # -e Display all of the disks that do not have an availability # of up and a status of ready. # # -L Display an extended list of the disk parameters, including # the disk id field and the remarks field. The remarks column # shows the current file system descriptor quorum assignments, # and displays the excluded disks. # # -m Display whether I/O requests to the disk are satisfied on # the local node or via an NSD server. The scope of this # option is the node on which the mmlsdisk command is issued. # # -M Display whether I/O requests to the disk are satisfied on # the local node or via an NSD server. If the I/O is done # via an NSD server, show the NSD server name and the actual # underlying disk name on that server node. # Caution: This is a slow operation! # # # Undocumented options: # # -i Display the disk id values for each of the disks. # ######################################################################### # Include global declarations and service routines. . /usr/lpp/mmfs/bin/mmglobfuncs if [[ $ourUid -eq 0 ]] then . /usr/lpp/mmfs/bin/mmsdrfsdef . /usr/lpp/mmfs/bin/mmfsfuncs fi sourceFile="mmlsdisk.sh" [[ -n $DEBUG || -n $DEBUGmmlsdisk ]] && set -x $mmTRACE_ENTER "$*" # Local work files. Names should be of the form: # fn=${tmpDir}fn.${mmcmd}.$$ tsnsdaccessResult=${tmpDir}tsnsdaccessResult.${mmcmd}.$$ LOCAL_FILES=" $tsnsdaccessResult " # Local variables usageMsg=301 integer rc=0 integer nodeCount=0 argList="" # argList without quotes around disk list argListQ="" # argList with quotes around disk list # underline="----------------------------------------------------------" # underline="${underline}----------------------------------------------" underline="------------ ----------------------- ----------------- ------------" # Local functions ########################################################################### # # Function: Show whether disk I/O takes place on this node or # over an NSD server. If requested, try to determine # the actual disk names to which the I/O is directed. # # Notes: # # - The file system must be mounted on this node. # The scope of the command is the current node only. # # - If the file system is owned by some other cluster, # the underlying disk names cannot be determined; # we cannot run commands on nodes that do not belong # to this cluster. # # Input: $1 - device name as provided by the user # $2 - fully qualified file system device name # $3 - file system home cluster name # $4 - disk name mapping indicator: yes or no # $5 - disk name list (optional); if not specified, # all disks in the file system are assumed # # Output: Formatted disk access information # # Returns: 0 - no errors encountered # 19 (ENODEV) - options line not found # 22 (EINVAL) - device name is not valid # 1 - some other unexpected error # ########################################################################### function displayDiskAccessInfo # device fqDeviceName fsHomeCluster # Moption [diskList] { typeset sourceFile="mmlsdisk.sh" [[ -n $DEBUG || -n $DEBUGdisplayDiskAccessInfo ]] && set -x $mmTRACE_ENTER "$*" typeset device=$1 typeset fqDeviceName=$2 typeset fsHomeCluster=$3 typeset Moption=$4 typeset diskList="$5" typeset rc=0 typeset displayAll="" typeset disksToDisplay diskName diskLine tsnsdaccessLine typeset magicWord nodeIPaddr localDiskName nodeName typeset hostResult availability nodeBelongsToTheCluster typeset diskInfo nsdId nsdSubtype getLocalDiskNameOutput [[ $Moption != M ]] && Moption="" # If disk list is specified, replace the ';' with blanks. if [[ -n $diskList ]] then disksToDisplay=$(print -- "$diskList" | $sed 's/;/ /g') else displayAll=yes fi # Call tsnsdaccess to get the information for all disks in the file system. $tsnsdaccess $fqDeviceName > $tsnsdaccessResult 2> $errMsg rc=$(remapRC $?) # Issue an appropriate message if tsnsdaccess failed. if [[ $rc -eq $MM_DaemonDown ]] then # GPFS is down on this node. printErrorMsg 109 $mmcmd elif [[ $rc -eq $MM_QuorumWait ]] then # GPFS is not ready for commands. printErrorMsg 110 $mmcmd elif [[ $rc -eq $MM_FsNotFound || $rc -eq $MM_RemoteNotFound ]] then # The file system is not mounted on this node. printErrorMsg 563 $mmcmd $device $ourNodeName elif [[ $rc -eq $MM_Remotefs && $fsHomeCluster != $HOME_CLUSTER ]] then # The file system is not owned by the remote cluster. [[ $device != *:* ]] && \ printErrorMsg 111 $mmcmd $device $remoteDevice $fsHomeCluster printErrorMsg 112 $mmcmd $remoteDevice $fsHomeCluster elif [[ ($rc -eq $MM_HostDown || $rc -eq $MM_TimedOut || $rc -eq $MM_SecurityCfg || $rc -eq $MM_AuthorizationFailed || $rc -eq $MM_UnknownCluster) && $fsHomeCluster != $HOME_CLUSTER ]] then # Failed to connect to the remote cluster. [[ $rc -eq $MM_SecurityCfg ]] && \ printErrorMsg 150 $mmcmd [[ $rc -eq $MM_AuthorizationFailed ]] && \ printErrorMsg 151 $mmcmd printErrorMsg 105 $mmcmd $fsHomeCluster elif [[ $rc -eq $MM_ConnectionReset ]] then # An internode connection was reset. printErrorMsg 257 $mmcmd elif [[ $rc -ne 0 ]] then # tsnsdaccess failed. [[ -s $errMsg ]] && $cat $errMsg 1>&2 printErrorMsg 104 "$mmcmd" "tsnsdaccess $fqDeviceName" else : # The command must have worked. fi # end of if [[ $rc -eq $MM_DaemonDown ]] $rm -f $errMsg # Give up if tsnsdaccess failed. [[ $rc -ne 0 ]] && \ return $rc # Extract from the tsnsdaccess output the information for the disks # that we are interested in. Store the result in a separate file. if [[ -n $displayAll ]] then $grep -e "tsnsdaccess:" -e "tsnsdaccess64:" $tsnsdaccessResult > $tmpfile else $rm -rf $tmpfile for diskName in $disksToDisplay do diskLine=$($grep -e "tsnsdaccess:$diskName:" -e "tsnsdaccess64:$diskName:" $tsnsdaccessResult) if [[ -z $diskLine ]] then printErrorMsg 315 $mmcmd $diskName $device return 1 else print -- "$diskLine" >> $tmpfile checkForErrors "writing to file $tmpfile" $? fi done # end for diskName in $disksToDisplay fi # end of if [[ -n $displayAll ]] if [[ ! -s $tmpfile ]] then # Unexpected error. This should not happen at this point. print -u2 "$mmcmd: There is no disk information to display." return 1 fi # Print the header line: # "Disk name IO performed on node Device Availability" header=$(printInfoMsg 506) printf "\n%s\n%.${#header}s\n" "$header" "$underline" # Process the information from the tsnsdaccess call and print the results. exec 3<&- exec 3< $tmpfile while read -u3 tsnsdaccessLine do # Parse the line. IFS=":" set -f ; set -- $tsnsdaccessLine ; set +f IFS="$IFS_sv" magicWord=$1 diskName=$2 localDiskName=$3 nodeIPaddr=$4 nsdSubtype=$5 nsdId=$6 # Determine the node name, local device name, and availability values. if [[ $localDiskName = "unused" ]] then # The disk is not being used on any of the nodes. The only # thing that we know is that (most likely) the disk is down. availability="down" nodeName=$UNRESOLVED localDiskName=$UNRESOLVED elif [[ $localDiskName = "unknown" ]] then # The disk is active but not on this node. The IP address refers # to the NSD server for the disk. That server may or may not be # part of our cluster. If it is not, we will attempt to get its # name using the host command. availability="up" nodeName=$(getNodeInfo \ $REL_HOSTNAME_Field $IPA_Field $nodeIPaddr $HOME_CLUSTER $mmsdrfsFile) if [[ -n $nodeName ]] then nodeBelongsToTheCluster=yes else hostResult=$($host $nodeIPaddr 2>/dev/null) set -f ; set -- $hostResult ; set +f nodeName=$1 nodeBelongsToTheCluster="" fi [[ -z $nodeName ]] && nodeName=$nodeIPaddr if [[ -n $Moption && -n $nodeBelongsToTheCluster ]] then # -M is specified and the NSD server is a member of the cluster. # Find the local device name for the disk on the NSD server node. getLocalDiskNameOutput=$($mmcommon on1 $nodeName \ getLocalDiskName $nsdId $nsdSubtype 2>$errMsg) rc=$? # Parse the output from the getLocalDiskName function. IFS=":" set -f ; set -- $getLocalDiskNameOutput ; set +f magicWord=$1 localDiskName=$2 IFS="$IFS_sv" if [[ -z $localDiskName || $magicWord != getLocalDiskName ]] then localDiskName=$UNRESOLVED fi $rm -f $errMsg else # -M is not specified, or the NSD server is not a member # of our cluster; we do not know the name of the disk. localDiskName=$UNRESOLVED fi # end of if [[ -n $Moption && -n $nodeBelongsToTheCluster ]] else # The I/O takes place on the local node. availability="up" nodeName="localhost" # If this is an AIX environment, replace the /dev/r prefix with /dev/. if [[ $osName = AIX && $localDiskName = +(/)dev+(/)r* ]] then localDiskName=${localDiskName##+(/)dev+(/)r} localDiskName=/dev/$localDiskName fi fi # end of if [[ $localDiskName = "unused" ]] # Put out the results. printf "%-13s %-24s %-18s %s\n" \ "$diskName" "$nodeName" "$localDiskName" "$availability" done # end of while read -u3 tsnsdaccessLine return $rc } #----- end of function displayDiskAccessInfo ---------------- ####################### # Mainline processing ####################### ##################################################################### # Process the command arguments. ##################################################################### [[ $arg1 = '-?' || $arg1 = '-h' || $arg1 = '--help' || $arg1 = '--' ]] && \ syntaxError "help" $usageMsg [[ $argc -lt 1 ]] && \ syntaxError "missingArgs" $usageMsg device=$arg1 # Save stripe group device (always the first parameter). shift 1 # Drop the device name from the parameter list. # Parse the optional parameters. Since the disk names in the -d option # are separated with ';', special care must be taken when creating argList. # For invocations via mmcommon, the disk list must be enclosed in quotes. # For direct (local) invocations of tslsdisk, the disk list must not have # surrounding quotes. if [[ $argc -gt 1 ]] then while getopts :eiLmMd: OPT do case $OPT in e) # Display all disks that are not up and ready. [[ -n $eflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" eflag="-$OPT" [[ -n $mflag || -n $Mflag ]] && \ syntaxError "invalidCombination" $usageMsg $eflag $mflag $Mflag argList="$argList -$OPT" argListQ="$argListQ -$OPT" ;; i) # Display disk ids. [[ -n $iflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" iflag="-$OPT" [[ -n $mflag || -n $Mflag ]] && \ syntaxError "invalidCombination" $usageMsg $iflag $mflag $Mflag argList="$argList -$OPT" argListQ="$argListQ -$OPT" ;; d) # Display information for the specified disks. [[ -n $dflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" diskList="$OPTARG" dflag="-$OPT" [[ "$diskList" = *+([-:,${BLANKchar}${TABchar}])* ]] && \ syntaxError "badSeparator_notSemicolon" $noUsageMsg argList="$argList -$OPT $OPTARG " argListQ="$argListQ -$OPT \"$OPTARG\" " ;; L) # Display disk ids and other information. [[ -n $Lflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Lflag="-$OPT" [[ -n $mflag || -n $Mflag ]] && \ syntaxError "invalidCombination" $usageMsg $Lflag $mflag $Mflag argList="$argList -$OPT" argListQ="$argListQ -$OPT" ;; m) # Display disk I/O path (localhost vs. NSD server). [[ -n $mflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" mflag="-$OPT" Moption="$OPT" [[ -n $Mflag || -n $eflag || -n $iflag || -n $Lflag ]] && \ syntaxError "invalidCombination" $usageMsg $mflag $Mflag $eflag $iflag $Lflag ;; M) # Display disk I/O path (localhost vs. NSD server) and hdisk name. [[ -n $Mflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Mflag="-$OPT" Moption="$OPT" [[ -n $mflag || -n $eflag || -n $iflag || -n $Lflag ]] && \ syntaxError "invalidCombination" $usageMsg $Mflag $mflag $eflag $iflag $Lflag ;; +[eidLmM]) # invalid option specified syntaxError "invalidOption" $usageMsg $OPT ;; :) # missing required value after an option syntaxError "missingValue" $usageMsg $OPTARG ;; *) # invalid option specified syntaxError "invalidOption" $usageMsg $OPTARG ;; esac done # end of while getopts :eiLmMd: OPT shift OPTIND-1 [[ $# != 0 ]] && syntaxError "extraArg" $usageMsg $1 fi # end of if [[ $argc -gt 1 ]] ################################### # Set up trap exception handling. ################################### trap pretrap2 HUP INT QUIT KILL #################################################################### # If invoked by a root user, call the gpfsInit function to ensure # that the local copy of the mmsdrfs file and the rest of the GPFS # system files are up-to-date. There is no need to lock the sdr. # Non-root users are not allowed to invoke commands on other nodes. #################################################################### if [[ $ourUid -eq 0 ]] then gpfsInitOutput=$(gpfsInit nolock) setGlobalVar $? $gpfsInitOutput elif [[ -n $Mflag ]] then # This option requires root authority. printErrorMsg 324 $mmcmd cleanupAndExit fi # end of if [[ $ourUid -eq 0 ]] #################################### # Make sure the file system exists. #################################### # If the invocation is not for an explicitly-remote device, obtain the # needed information about the filesystem from the mmsdrfs file. if [[ $device != *:* ]] then findFSoutput=$(findFS "$device" $mmsdrfsFile) [[ -z $findFSoutput ]] && cleanupAndExit # Parse the output from the findFS function. set -f ; set -- $findFSoutput ; set +f fqDeviceName=$1 deviceName=$2 fsHomeCluster=$3 remoteDevice=$4 # If this is a remote file system, set fqDeviceName appropriately. [[ $fsHomeCluster != $HOME_CLUSTER ]] && \ fqDeviceName="$fsHomeCluster:/dev/$remoteDevice" else fqDeviceName=$device deviceName=${fqDeviceName##*:} fsHomeCluster=${fqDeviceName%%:*} remoteDevice=$deviceName fi # end of if [[ $device != *:* ]] ############################################ # Process the -m and -M options separately. ############################################ if [[ -n $mflag || -n $Mflag ]] then displayDiskAccessInfo $device $fqDeviceName $fsHomeCluster $Moption "$diskList" cleanupAndExit $? fi # end of if [[ -n $mflag || -n $Mflag ]] ######################################################################## # Invoke the command on the local node. # Display any error messages and exit if any of the following are true: # - the command completed successfully # - there is an unacceptable error # (anything other than daemon down or quorum wait) # - the file system is remote # - we are not running as UID 0 # - this is a single node cluster ######################################################################## ${mmcmdDir}/${links}/mmlsdisk $fqDeviceName $argList 2>$errMsg rc=$(remapRC $?) if [[ ($rc -ne $MM_DaemonDown && $rc -ne $MM_QuorumWait) || $fsHomeCluster != $HOME_CLUSTER || $ourUid -ne 0 || $MMMODE = single ]] then if [[ $rc -eq $MM_FsNotFound ]] then if [[ $fsHomeCluster != $HOME_CLUSTER ]] then # The remote cluster does not know anything about this file system. printErrorMsg 108 $mmcmd $remoteDevice $fsHomeCluster else # Unexpected error. printErrorMsg 171 $mmcmd "file system $deviceName not found" $rc fi elif [[ ($rc -eq $MM_HostDown || $rc -eq $MM_TimedOut || $rc -eq $MM_SecurityCfg || $rc -eq $MM_AuthorizationFailed || $rc -eq $MM_UnknownCluster) && $fsHomeCluster != $HOME_CLUSTER ]] then # Failed to connect to the remote cluster. [[ $rc -eq $MM_SecurityCfg ]] && \ printErrorMsg 150 $mmcmd [[ $rc -eq $MM_AuthorizationFailed ]] && \ printErrorMsg 151 $mmcmd printErrorMsg 105 $mmcmd $fsHomeCluster elif [[ $rc -eq $MM_Remotefs && $fsHomeCluster != $HOME_CLUSTER ]] then # The file system is not owned by the remote cluster. [[ $device != *:* ]] && \ printErrorMsg 111 $mmcmd $device $remoteDevice $fsHomeCluster printErrorMsg 112 $mmcmd $remoteDevice $fsHomeCluster elif [[ $rc -eq $MM_DaemonDown ]] then # GPFS is down on this node. printErrorMsg 109 $mmcmd elif [[ $rc -eq $MM_QuorumWait ]] then # GPFS is not ready for commands. printErrorMsg 110 $mmcmd elif [[ $rc -eq $MM_ConnectionReset ]] then # An internode connection was reset. printErrorMsg 257 $mmcmd else # Either the command worked, or it is an unexpected error. if [[ -s $errMsg ]] then # Show the error messages from the daemon. $cat $errMsg 1>&2 elif [[ $rc -ne 0 ]] then # tslsdisk failed. printErrorMsg 104 "$mmcmd" "tslsdisk $fqDeviceName" else : # The command must have worked. fi # end of if [[ -s $errMsg ]] fi # end of if [[ $rc -eq $MM_FsNotFound ]] cleanupAndExit $rc fi # end of if [[ ($rc -ne $MM_DaemonDown && ... ]] $rm -f $errMsg ######################################################################### # We come here if the command was invoked for a local file system but # the local daemon is not available; send the command to an active node. ######################################################################### # Create a file with the reliable names of the nodes in the cluster. nodeCount=$(getNodeFile $REL_HOSTNAME_Field $fsHomeCluster $mmsdrfsFile $nodefile) if [[ $nodeCount -eq 0 ]] then # The cluster is empty; there is nobody to run the command. printErrorMsg 171 $mmcmd "getNodeFile (nodeCount=0)" 1 cleanupAndExit fi # Try the nodes one by one until you find a node that can execute the command. preferredNode=0 # We have no idea where to go first; let mmcommon decide. $mmcommon linkCommand $preferredNode $nodefile \ mmlsdisk $fqDeviceName "$argListQ" rc=$? cleanupAndExit $rc