#!/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/<module>.map
#               or options to be given to insmod
#
# Returns:   0 success
#            1 failure
#
###################################################################
function InsModWrapper  #  <moduleName> <insmod_options> ..
{
  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/<module>.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  # <moduleName>
{
  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  #  <fsList> [-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  #  <mountPoint> [-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  # <deviceName>
{
  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  # <pathName>
{
  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  # <diskName>
{
  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  # <diskName>
{
  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  # <diskName>
{
  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 -------------

