#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2000,2006 # 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 # @(#)12 1.18.6.4 src/avs/fs/mmfs/ts/admin/mmfsfuncs.Linux.sh, mmfs, avs_rgpfs24, rgpfs24s007a 10/24/06 10:23:08 ###################################################################### # # This file contains declarations and functions that are unique # to the Linux operating system environment. # ###################################################################### ################################################################### # # Function: wrapper function for invoking insmod # # Input: $1 module to load # $@ -d generate load map in /var/mmfs/tmp/.map # or options to be given to insmod # # Returns: 0 success # 1 failure # ################################################################### function InsModWrapper # .. { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGInsModWrapper ]] && set -x $mmTRACE_ENTER "$*" # First argument is module name and insmod parameters. # The remaining arguments are insmod options. typeset module="$1" shift typeset opts="$@" typeset name iopts opt debug loadcmd # Strip off insmod parameters to get module name. name="${module%% *}" name="${name%%[0-9][0-9]}" # Check whether the module is loaded already. $lsmod | $grep -qwe ^${name##*/} if [[ $? = 0 ]] then # Informational: The module is already loaded. printErrorMsg 140 $mmcmd ${name##*/} return 0 fi # The "-d" option means that we should generate a load map in /var/mmfs/tmp. iopts="" for opt in $opts do # Linux 2.5 and later do not have /proc/ksyms and insmod -m/-f. [[ -z $version24 && ($opt = "-d" || $opt = "-f") ]] && \ continue if [[ "$opt" = "-d" ]] then # The -m options tells insmod to generate a map. # Currently "insmod -m" is broken on x86_64 w/ RHEL, so skip x86_64 here. if [[ $($uname -m) != 'x86_64' ]] then iopts="$iopts -m" # Write load map to /var/mmfs/tmp/.map module="$module > /var/mmfs/tmp/${name##*/}.map" debug=1 fi else iopts="$iopts $opt" fi done # Load the module. loadcmd="$insmod $iopts $module" eval $loadcmd return $? } #---------- end of function InsModWrapper --------------- ########################################################### # # Function: wrapper function for invoking rmmod # # Input: $1 module to unload # # Returns: return code from rmmod # ########################################################### function RmModWrapper # { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGRmModWrapper ]] && set -x $mmTRACE_ENTER "$*" typeset module="$1" # Check whether the module is loaded. $lsmod | $grep -qwe ^${module##*/} [[ $? = 1 ]] && return 0 # Unload the module. print -- "Unloading module $module" $rmmod $module return $? } #---------- end of function RmModWrapper --------------- ##################################################################### # # Function: Determine kernel configuration and perform # some verification of the mmfslinux module. # # Inout: none # # Output: 'mmfslinux' or '' (empty string when module is missing) # # Returns: 0 - success # 1 - failure # ##################################################################### function verifyModule { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGverifyModule ]] && set -x $mmTRACE_ENTER "$*" typeset kMODULE # If mmfslinux exists, use it. Otherwise, return an error. if [[ -s $mmcmdDir/mmfslinux ]] then kMODULE="mmfslinux" else kMODULE="" # Error: The mmfslinux kernel extension does not exist. printErrorMsg 135 $mmcmd $mmcmdDir/mmfslinux return 1 fi # kMODULE is valid and ready to be loaded. print -- "$kMODULE" return 0 } #---------- end of function verifyModule --------------- ################################################################### # # Function: Unmount the specified file system(s). # # Input: $1 - list of device names or all # $2 - (optional) force unmount option (-f) # # Output: None # # Returns: Always zero. # ################################################################### function unmountFileSystems # [-f] { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGunmountFileSystems ]] && set -x $mmTRACE_ENTER "$*" typeset fsList=$1 typeset forceOption=$2 typeset mountPoint deviceName # Verify the force option. [[ $forceOption != "-f" ]] && forceOption="" # Unmount the requested file system(s). # Important! Do not try to capture, pipe or redirect # in any way stderr from the umount command on Linux. # See Defect 439182 for details. if [[ $fsList = all ]] then # The request is to unmount all GPFS file systems. $umount $forceOption -a -t gpfs # Make sure we do not have any stale mounts. $awk '$3 == "gpfs" { print $2 }' /proc/mounts | \ while read mountPoint do $umount $forceOption $mountPoint done else # The request is to unmount one or more GPFS file systems. IFS=',' for deviceName in $fsList do IFS="$IFS_sv" # Find out the mount point where the file system is mounted. mountPoint=$(findMountpoint $deviceName) # If the file system is mounted, unmount it. [[ -n $mountPoint ]] && \ $umount $forceOption $mountPoint # Move to the next file system. IFS=',' done # end of for deviceName in $fsList IFS="$IFS_sv" fi # end of if [[ $deviceName = all ]] return 0 } #------ end of function unmountFileSystems ------------------ ################################################################### # # Function: Unmount the GPFS file system currently mounted # at the specified mount point. # # Input: $1 - mount point # $2 - (optional) force unmount option (-f) # # Output: None # # Returns: Always zero. # ################################################################### function unmountMountpoint # [-f] { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGunmountMountpoint ]] && set -x $mmTRACE_ENTER "$*" typeset mountPoint=$1 typeset forceOption=$2 typeset fqDeviceName # Verify the force option. [[ $forceOption != "-f" ]] && forceOption="" # See if there is a GPFS file system currently mounted # at the specidfied mount point. fqDeviceName=$($awk ' \ $2 == "'$mountPoint'" && $3 == "gpfs" { print $1 } \ ' /proc/mounts) # If the file system is mounted, unmount it. # Important! Do not try to capture, pipe or redirect # in any way stderr from the umount command on Linux. # See Defect 439182 for details. [[ -n $fqDeviceName ]] && \ $umount $forceOption $mountPoint return 0 } #------ end of function unmountMountpoint ------------------ ##################################################################### # # Function: Unload GPFS kernel extensions. # Always try to unload all extensions, # even if there is an intermediate failure. # # Returns: 0 - success # 1 - failure: at least one extension cannot be unloaded # ##################################################################### function unloadKernelExt { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGunloadKernelExt ]] && set -x $mmTRACE_ENTER "$*" typeset rc=0 typeset force="-f" typeset kMODULE gpl_module ibm_module trc_module typeset trc_device ss_device pid usecount kdump_device expected_mod_count [[ $@ = "-r" ]] && force="" print -- "Unloading modules from $mmcmdDir" # Determine the kernel configuration so the appropriately # configured mmfslinux module may be unloaded. kMODULE=$(verifyModule) if [[ $? -ne 0 || -z $kMODULE ]] then # Error: Unable to verify kernel/module configuration. printErrorMsg 136 $mmcmd return 1 fi # Initialize module names and insmod parameters. gpl_module="$kMODULE" trc_module="tracedev" ibm_module="mmfs" if [[ -n $version24 ]] then ibm_module="mmfs24" fi if [[ -n $version24 ]] then expected_mod_count=0 else expected_mod_count=1 fi # Initialize device names. trc_device="trace" ss_device="ss" kdump_device="kdump" # Make sure the daemon isn't running anymore. cmdout=$($ps -eo "pid args" | $awk '$2 ~ /mmfsd/ && !/this process/ {print $1}') if [[ -n $cmdout ]] then # Error: The GPFS daemon is still running. printErrorMsg 137 $mmcmd return 1 fi # Make sure we don't have any mounts just laying around. unmountFileSystems all $force # Before unloading the $ibm_module, # make sure the $gpl_module can be unloaded as well. usecount=$($lsmod | $grep -w -e ^$gpl_module | $awk '{print $3}') if [[ -n $usecount && $usecount -ne $expected_mod_count && $usecount -ne 0 ]] then # Error: Module $gpl_module is still in use. printErrorMsg 138 $mmcmd $gpl_module rc=1 fi # Invoke rmmod with all arguments we got. RmModWrapper $ibm_module "$@" if [[ $? -ne 0 ]] then # Error unloading module $ibm_module. printErrorMsg 139 $mmcmd $ibm_module rc=1 fi RmModWrapper $gpl_module "$@" if [[ $? -ne 0 ]] then # Error unloading module $gpl_module. printErrorMsg 139 $mmcmd $gpl_module rc=1 else $rm -f /dev/${ss_device}0 /dev/${ss_device} fi RmModWrapper $trc_module "$@" if [[ $? -ne 0 ]] then # Error unloading module $trc_module. printErrorMsg 139 $mmcmd $trc_module rc=1 else # ${trc_module} is the device name also $rm -f /dev/${trc_device}0 /dev/${trc_module} /dev/${kdump_device}0 fi return $rc } #---------- end of function unloadKernelExt --------------- ########################################################### # # Function: load GPFS kernel extensions # # Input: -d - generate load map in /var/mmfs/tmp # $@ - options to give to insmod # # Returns: 0 - success # 1 - failure # ########################################################### function loadKernelExt { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGloadKernelExt ]] && set -x $mmTRACE_ENTER "$*" typeset opts="$@" typeset opt kMODULE gpl_module ibm_module trc_module trc_device ss_device kdump_device typeset debug sysmap major gdbfile module name mapfile textaddr debug=0 for opt in $opts do [[ $opt = "-d" ]] && debug=1 done # Specifically turn on debugging. # We need everything we can get for debugging on linux. if [[ $debug = 0 ]] then debug=1 opts="$opts -d" fi print -- "Loading modules from $mmcmdDir" # Determine the kernel configuration so the appropriately-configured # mmfslinux module may be loaded. kMODULE=$(verifyModule) if [[ $? -ne 0 || -z $kMODULE ]] then # Error: Unable to verify kernel/module configuration. printErrorMsg 136 $mmcmd return 1 fi # Initialize module names and insmod parameters. gpl_module="$kMODULE prog_path=$mmcmdDir" trc_module="tracedev" if [[ -n $version24 ]] then ibm_module="mmfs24" else ibm_module="mmfs26" fi # Initialize device names. trc_device="trace" ss_device="ss" kdump_device="kdump" # Invoke insmod with all arguments we got. InsModWrapper "$mmcmdDir/$trc_module" "$opts" if [[ $? -ne 0 ]] then unloadKernelExt return 1 fi # Load gpl module without forcing insmod. InsModWrapper "$mmcmdDir/$gpl_module" "$opts" if [[ $? -ne 0 ]] then unloadKernelExt return 1 fi InsModWrapper "$mmcmdDir/$ibm_module" "$opts" if [[ $? -ne 0 ]] then unloadKernelExt return 1 fi # Show what we loaded. $lsmod | $grep -w -e ^Module -e ^${trc_module%% *} \ -e ^${gpl_module%% *} -e ^${ibm_module%% *} MAPDIR=/var/mmfs/tmp if [[ $debug = 1 ]] && [[ -r $MAPDIR ]] then # Build one symbol map for kernel and modules and sort it. MMFSLINUX_MAP=$MAPDIR/$kMODULE.map COMPLETE_MAP=$MAPDIR/complete.map TRCDEV_MAP=$MAPDIR/$trc_module.map MMFS_MAP=$MAPDIR/$ibm_module.map SORT_MAP=$MAPDIR/sort.map KSYMS_MAP=$MAPDIR/ksyms.map if [[ -n $version24 ]] then KALLSYMS_MAP="" else KALLSYMS_MAP=/proc/kallsyms fi #------------------------------------------------------ # Clean out tmp files not accessed in the last 3 days. #------------------------------------------------------ SAVEPWD="$PWD" print -- "Removing old $MAPDIR files:" if cd "$MAPDIR" then $find . -type f -atime +3 -exec $rm {} \; -print fi cd "$SAVEPWD" #------------------------------ # Find or create a system map. #------------------------------ SYSTEM_MAP="" activeKernel=$($uname -r 2>/dev/null) if [[ -r /boot/System.map ]] then SYSTEM_MAP="/boot/System.map" elif [[ -r /usr/src/linux/System.map ]] then SYSTEM_MAP="/usr/src/linux/System.map" elif [[ -r /boot/System.map-$activeKernel ]] then SYSTEM_MAP="/boot/System.map-$activeKernel" else # Not the same thing but perhaps useful print -- "Couldn't find System.map. Using /proc/ksyms." SYSTEM_MAP=$KSYMS_MAP $cat /proc/ksyms | $awk '{print $1" ? "$2}' > $SYSTEM_MAP fi #---------------------------------------------------- # Strip and sort other maps into appropriate format. #---------------------------------------------------- $cat $MMFSLINUX_MAP $TRCDEV_MAP $MMFS_MAP 2>/dev/null | \ $awk '/ [TtDdRr] / {print $0}' | $sort -o $SORT_MAP #----------------------------------------------------- # Create a complete.map and latest/previous symlinks. #----------------------------------------------------- SUFFIX="$($date +%Y.%m.%d.%H.%M.%S).$($hostname -s)" $cat $KALLSYMS_MAP $SYSTEM_MAP $SORT_MAP > "${COMPLETE_MAP}.${SUFFIX}" if [[ -L "${COMPLETE_MAP}.previous" ]] then previous=$($ls -l "${COMPLETE_MAP}.previous") previous=${previous##*-\> } $rm -f $previous fi [[ -r "${COMPLETE_MAP}.previous" ]] && $rm -f "${COMPLETE_MAP}.previous" if [[ -L "${COMPLETE_MAP}.latest" ]] then $mv -f "${COMPLETE_MAP}.latest" "${COMPLETE_MAP}.previous" fi [[ -r "${COMPLETE_MAP}.latest" ]] && $rm -f "${COMPLETE_MAP}.latest" $ln -sf $(basename "${COMPLETE_MAP}.${SUFFIX}") "${COMPLETE_MAP}.latest" # Re-initialize syslogd so it can load GPFS module symbols. [[ -s /var/run/syslogd.pid ]] && \ $kill -s SIGHUP $($cat /var/run/syslogd.pid) #----------------------------------------------------------------------- # Generate a gdb script in /var/mmfs/tmp that will load module symbols. #----------------------------------------------------------------------- GDBFILE="$MAPDIR/loadsyms" $rm -f $GDBFILE for module in "$mmcmdDir/$trc_module" "$mmcmdDir/$gpl_module" \ "$mmcmdDir/$ibm_module" do name="${module%% *}" mapfile="$MAPDIR/${name##*/}.map" if [[ -s $mapfile ]] then textaddr=$($awk '/^.text / { print $3 }' $mapfile) $awk 'BEGIN { printf "add-symbol-file '"$name 0x$textaddr"'" } /^Sections:/,/^$/ \ { if (substr($1,1,1) == "." && $1 != ".this" && $1 != ".text" && $1 != ".kmodtab" && $1 != ".kstrtab" && $1 !~ "^.gnu.linkonce.") { sect = $1 addr = $3 # If section name is too long, it gets concatenated # with the address field, so fix that. if (NF == 3 && length(sect) > 15) { sect = substr(sect, 1, length(sect) - 8) addr = $2 } printf " -s %s 0x%s", sect, addr } } END { print "" }' $mapfile >> $GDBFILE fi done $rm -f $SORT_MAP $MMFSLINUX_MAP $MMFS_MAP $TRCDEV_MAP $KSYMS_MAP fi # Get the major number of the ss_device from /proc/devices. # Remove stale ss_device node and replace it. major=$($awk ' $2=="'$ss_device'" {print $1} ' /proc/devices) if [[ -n "$major" ]] then $rm -f /dev/${ss_device}0 # Normal user must be able to open device in read # mode so ioctl() will work. umask 013 $mknod /dev/${ss_device}0 c $major 0 umask $UMASK_sv fi # Get the major number of the trc_device from /proc/devices. # Remove stale trc_device node and replace it. major=$($awk ' $2=="'$trc_device'" {print $1} ' /proc/devices) if [[ -n "$major" ]] then $rm -f /dev/${trc_device}0 umask 077 $mknod /dev/${trc_device}0 c $major 0 umask $UMASK_sv fi # Get the major number of the kdump_device from /proc/devices. # Remove stale kdump_device node and replace it. major=$($awk ' $2=="'$kdump_device'" {print $1} ' /proc/devices) if [[ -n "$major" ]] then $rm -f /dev/${kdump_device}0 umask 077 $mknod /dev/${kdump_device}0 c $major 0 umask $UMASK_sv fi return 0 } #---------- end of function loadKernelExt --------------- ################################################################### # # Function: Determine the mount point at which a file system # is currently mounted. # # Input: $1 - file system device name # # Output: Mount point or null (if not mounted). # # Returns: Always zero. # ################################################################### function findMountpoint # { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGfindMountpoint ]] && set -x $mmTRACE_ENTER "$*" typeset device=$1 typeset deviceName fqDeviceName # Verify the device name. deviceName=${device##+(/)dev+(/)} # name stripped of /dev/ prefix fqDeviceName="/dev/$deviceName" # fully-qualified name with /dev/ prefix # See if the file system is mounted. mountPoint=$($awk ' \ $1 == "'$fqDeviceName'" && $3 == "gpfs" { print $2 } \ ' /proc/mounts) # Print the output and return. print -- "$mountPoint" return 0 } # ---- end of function findMountpoint -------------------- ################################################################### # # Function: Given a path name, find the GPFS file system to which # the object (file, directory, etc.) belongs. # # Input: $1 - fully-qualified path name # # Output: GPFS file system device name or null. # # Returns: 0 - device name determined # 19 (ENODEV) - device not found # 22 (EINVAL) - input path name is not valid # other unexpected errors # ################################################################### function findDeviceName # { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGfindDeviceName ]] && set -x $mmTRACE_ENTER "$*" typeset pathName=$1 typeset deviceID objectDeviceID fqDeviceName mountInfo vfsType # Find the device ID of the specified directory. objectDeviceID=$($perl -e '($dev) = stat "'$pathName'"; printf "%u", $dev;') if [[ -z $objectDeviceID ]] then # Failed to stat the directory. printErrorMsg 454 $mmcmd $pathName return $MM_InvalidName fi # Go down the list of monted file systems. If the vfs type is gpfs, # find the device ID and see if it matches the device ID of our object. exec 5<&- exec 5< /proc/mounts while read -u5 mountInfo do # Parse the line. set -f ; set -- $mountInfo ; set +f fqDeviceName=$1 mountPoint=$2 vfsType=$3 # Skip the line if this is not a GPFS file system. [[ $vfsType != "gpfs" ]] && continue # Find the device ID for the mount point. deviceID=$($perl -e '($dev) = stat "'$mountPoint'"; printf "%u", $dev;') # If this is the file system that we are looking for, # print the device name and return. if [[ $deviceID = $objectDeviceID ]] then print -- "$fqDeviceName" return 0 fi done # end while read -u3 mountInfo # If we get here, the object does not belong to a GPFS file system. printErrorMsg 455 $mmcmd $pathName return $MM_DeviceNotFound } # ---- end of function findDeviceName -------------------- ##################################################################### # # Function: Unfence the specified disks on the local node. # Clear any PR registrations. # # Input: $1 - file with disks to unfence # # Output: A line with the following ':' separated fields: # - magic word 'unfenceDisks' # - function return code # - status # # Returns: Zero if successful, non-zero otherwise. # ##################################################################### function unfenceDisks # { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGunfenceDisks ]] && set -x $mmTRACE_ENTER "$*" typeset disksToUnfence=$1 # This function is a no-op in Linux. print -- "unfenceDisks:0:success:" return 0 } #---- end of function unfenceDisks ---------------- ##################################################################### # # Function: Unfence the specified disk on the local node. # # Input: $1 - name of the disk to unfence. # # Output: None. # # Returns: Zero if successful, non-zero otherwise. # ##################################################################### function unfenceVSDdisk # { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGunfenceVSDdisk ]] && set -x $mmTRACE_ENTER "$*" typeset diskName=$1 # This function is a no-op in Linux. return 0 } #---- end of function unfenceVSDdisk ---------------- #################################################################### # # Function: Determine the NSD subtype, i.e., the type of the disk # used to create the NSD. # # Input: name of the disk whose NSD subtype must be determined # # Output: the NSD subtype for the disk; possible values are: # vpath, powerdisk, generic or file. # # Returns: 0 - success # 1 - error detected # #################################################################### function determineNsdSubtype # { typeset sourceFile="mmfsfuncs.Linux.sh" [[ -n $DEBUG || -n $DEBUGdetermineNsdSubtype ]] && set -x $mmTRACE_ENTER "$*" typeset diskName=$1 typeset nsdSubtype typeset rc=0 # Invoke the nsddevices user exit if it was activated. # If that script is not activated, or if it does not find # the disk, proceed with the normal GPFS disk discovery. if [[ -x $nsddevices ]] then nsdSubtype=$($nsddevices | $awk ' $1 == "'$diskName'" { print $2 } ') if [[ -n $nsdSubtype ]] then # Return the device type from the nsdddevices function. print $nsdSubtype return 0 fi fi # We come here if we could not obtain the device type # from nsddevices. Determine how the disk should be # reported (vpath, EMC powerpath, generic, or file). if [[ $diskName = vpath* ]] then nsdSubtype="vpath" elif [[ $diskName = emcpower* ]] then nsdSubtype="powerdisk" elif [[ $diskName = /* ]] then nsdSubtype="file" else nsdSubtype="generic" fi # Verify that the device exists. if [[ $nsdSubtype = file ]] then if [[ ! -f $diskName ]] then # Error: disk not found. printErrorMsg 524 $mmcmd $diskName return 1 fi else $grep -w $diskName /proc/partitions > /dev/null 2>&1 if [[ $? -ne 0 ]] then # Error: disk not found in /proc/partitions. printErrorMsg 141 $mmcmd $diskName return 1 fi fi # Output the NSD subtype and return. print $nsdSubtype return $rc } #---- end of function determineNsdSubtype -------------