#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 1997,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 
# @(#)14 1.128.1.3 src/avs/fs/mmfs/ts/admin/mmadddisk.sh, mmfs, avs_rgpfs24, rgpfs24s005a 7/14/06 17:46:24
################################################################################
#
# Usage:
#   mmadddisk Device {"DiskDesc[;DiskDesc...]" | -F DescFile} [-a] [-r]
#     [-v {yes | no}] [-N {all | mount | Node[,Node...] | NodeFile | NodeClass}]
#
# where
#   Device    is the file system device name
#   DiskDesc  is the same syntax as DiskDesc of mmcrfs
#   -r        rebalance stripe group when done
#   -a        if -r specified, command returns before rebalancing is finished
#   -v        make sure the disk does not belong to another file system
#   -N        parallel restripe options:
#               all        - use all of the nodes in the cluster
#               mount      - use only the nodes on which the fs is mounted
#               node list  - use only the nodes in the list
#               node file  - use only the nodes in the file
#               node class - use only the nodes in the class
#
################################################################################

# Include global declarations and service routines.
. /usr/lpp/mmfs/bin/mmglobfuncs
. /usr/lpp/mmfs/bin/mmsdrfsdef
. /usr/lpp/mmfs/bin/mmfsfuncs

sourceFile="mmadddisk.sh"
[[ -n $DEBUG || -n $DEBUGmmadddisk ]] && set -x
$mmTRACE_ENTER "$*"

# Local work files.  Names should be of the form:
#   fn=${tmpDir}fn.${mmcmd}.$$

tsddFile=${tmpDir}tsddFile.${mmcmd}.$$     # tsadddisk format disk descriptors
descfile=${tmpDir}descfile.${mmcmd}.$$     # temp file for descriptors
freeDisks=${tmpDir}freeDisks.${mmcmd}.$$   # available unused disks

LOCAL_FILES=" $tsddFile $descfile $freeDisks "


# Local variables
usageMsg=296
noUsageMsg=0
integer seqNo=0


# Local functions

#####################################################
# This function is called if there is an interrupt
# after some sdr changes are committed.
#####################################################
function localPosttrap
{
  # Restriping may not have finished.
  [[ -n $rflag && -z $aflag ]] &&  \
    printErrorMsg 35 $mmcmd

  # Exit via the standard post trap routine.
  posttrap
}



######################
# Mainline processing
######################


######################################
# Process the command line arguments.
######################################
[[ $arg1 = '-?' || $arg1 = '-h' || $arg1 = '--help' || $arg1 = '--' ]] &&  \
  syntaxError "help" $usageMsg

[[ $argc -lt 2  ]] &&  \
  syntaxError "missingArgs" $usageMsg

# The first argument is always the file system name.
device=$arg1

if [[ $arg2 != "-F" ]]
then
  # If the second argument is not -F, it must be a disk descriptor list.
  desclist=$arg2
  # Ensure that semi-colon is used as a disk name separator.
  [[ "$desclist" = *+([,${BLANKchar}${TABchar}])* ]] &&  \
    syntaxError "badSeparator_notSemicolon" $noUsageMsg

else
  # -F specified.  The third argument must be a file name.
  if [[ -z $arg3 ]]
  then
    syntaxError "missingFile" $usageMsg
  else
    # Verify the existence of the file and create our own copy.
    checkUserFile $arg3 $descfile
    [[ $? -ne 0 ]] && cleanupAndExit
    shift
  fi  # end of if [[ -z $arg3 ]]
fi  # end of if [[ $arg2 != "-F" ]]

# Move past the required parameters.
shift 2

# Check the validity of the flags.
while getopts :arv:N: OPT
do
  case $OPT in
    a) [[ -n $aflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
       aflag=yes
       ;;

    r) [[ -n $rflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
       rflag=yes
       ;;

    N) [[ -n $Nflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
       nodeList="$OPTARG"
       Nflag="-N $OPTARG"
       ;;

    v) [[ -n $vflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
       if [[ $OPTARG = yes || $OPTARG = no ]]
       then
         vflag="-v $OPTARG"
       else
         syntaxError "YesNoValue" $noUsageMsg "-$OPT"
       fi
       ;;

    +[arvN])
     syntaxError "invalidOption" $usageMsg $OPT
       ;;

    :) syntaxError "missingValue" $usageMsg $OPTARG
       ;;

    *) syntaxError "invalidOption" $usageMsg $OPTARG
       ;;
  esac
done

shift OPTIND-1
[[ $# != 0 ]] && syntaxError "extraArg" $usageMsg $1


#####################################################################
# Set up trap exception handling and call the gpfsInit function.
# It will ensure that the local copy of the mmsdrfs and the rest of
# the GPFS system files are up-to-date and will obtain the sdr lock.
#####################################################################
trap pretrap HUP INT QUIT KILL
gpfsInitOutput=$(gpfsInit $lockId)
setGlobalVar $? $gpfsInitOutput

# Determine the lookup order for resolving host names.
[[ $osName != AIX ]] && resolveOrder=$(setHostResolveOrder)


###########################################################
# Make sure the specified file system exists and is local.
###########################################################
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
oddState=$5

# Exit with a message if the command was invoked for a remote file system.
if [[ $fsHomeCluster != $HOME_CLUSTER ]]
then
  # Command is not allowed for remote file systems.
  printErrorMsg 106 $mmcmd $device $fsHomeCluster
  cleanupAndExit
fi

# Check whether some of the disks in the file system may be in an odd state.
if [[ $oddState = yes ]]
then
  # Some of the disks in the file system appear to be in an odd state.
  # Reconcile the sdrfs file with the GPFS daemon's view of the filesystem.
  $cp $mmsdrfsFile $newsdrfs
  reconcileSdrfsWithDaemon $deviceName $newsdrfs
  rc=$?
  if [[ $rc -ne 0 ]]
  then
    # reconcileSdrfsWithDaemon failed.
    printErrorMsg 171 $mmcmd reconcileSdrfsWithDaemon $rc
    # Tell the user to run mmcommon recoverfs against the file system.
    printErrorMsg 103 $mmcmd $deviceName $deviceName
    cleanupAndExit
  fi

  # Obtain the generation number from the version line of the new sdrfs file.
  versionLine=$($head -1 $newsdrfs)
  IFS=':'
  set -f ; set -- $versionLine ; set +f
  newGenNumber=$6
  IFS="$IFS_sv"

  # Commit the reconciled version of the sdrfs file to the server
  # so the admin scripts and the daemon are in sync.
  trap "" HUP INT QUIT KILL    # Disable interrupts until the commit is done.
  gpfsObjectInfo=$(commitChanges  \
    $fsHomeCluster $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer)
  if [[ $? -ne 0 ]]
  then
    # We were unable to replace the file in the sdr.
    printErrorMsg 381 $mmcmd
    # Tell the user to run mmcommon recoverfs against the filesystem.
    printErrorMsg 190 $mmcmd $deviceName $deviceName
    printErrorMsg 104 $mmcmd mmadddisk
    cleanupAndExit
  fi
  trap posttrap HUP INT QUIT KILL
fi  # end of if [[ $oddState = yes ]]


#######################################################
# If a list of nodes was specified via the -N option,
# convert it to a verified list of daemon node names.
#######################################################
if [[ -n $Nflag && $nodeList != all && $nodeList != mount ]]
then
  createVerifiedNodefile "$nodeList" $DAEMON_NODENAME_Field no $nodefile
  [[ $? -ne 0 ]] && cleanupAndExit

  # Convert the output data from a file to a comma-separated list.
  newNodeList=$(print -- $(cat $nodefile) | $sed 's/ /,/g')
  Nflag="-N $newNodeList"
fi  # end of if [[ -n $Nflag && $nodeList != all && $nodeList != mount ]]


#########################################################################
# Create a new version of the mmsdrfs file with a new generation number
# for the final commit after the tsadddisk command has succeeded.
# Generate a file with the reliable host names of the affected nodes.
#########################################################################
$rm -f $nodefile $newsdrfs $freeDisks $allQuorumNodes
$touch $freeDisks  # Ensure the file exists even if empty.
IFS=":"            # Change the field separator to ':'.
exec 3<&-
exec 3< $mmsdrfsFile
while read -u3 sdrfsLine
do
  # Parse the line.
  set -f ; set -A v -- - $sdrfsLine ; set +f

  IFS="$IFS_sv"    # Restore the default IFS settings.
  printLine=true   # Assume the line will be printed.

  # Change some of the fields depending on the type of line.
  case ${v[$LINE_TYPE_Field]} in

    $VERSION_LINE )  # This is the global header line.
       # Increment the generation number by 1.
       newGenNumber=${v[$SDRFS_GENNUM_Field]}+1
       v[$SDRFS_GENNUM_Field]=$newGenNumber
       ;;

    $MEMBER_NODE )  # This line describes a node that belongs to some nodeset.
       # Add the reliable node name to nodefile.
       print -- "${v[$REL_HOSTNAME_Field]}" >> $nodefile
       checkForErrors "writing to file $nodefile" $?

       # Create a list of the quorum nodes.
       if [[ ${v[$CORE_QUORUM_Field]} = $quorumNode ]]
       then
         print -- "${v[$REL_HOSTNAME_Field]}" >> $allQuorumNodes
         checkForErrors "writing to file $allQuorumNodes" $?
       fi

       # If the node that is executing this command is part of the nodeset,
       # designate it as a "preferred node".
       [[ ${v[$NODE_NUMBER_Field]} = $ourNodeNumber ]] &&  \
         preferredNode=${v[$REL_HOSTNAME_Field]}
       ;;

    $SG_HEADR )  # This is the header line for some file system.
       # Check whether the filesystem has disks that are in an "odd state".
       if [[ -n ${v[$ODD_STATE_Field]} && ${v[$ODD_STATE_Field]} != no ]]
       then
         # Is this filesystem a different one than the one for which
         # this command was invoked?
         if [[ ${v[$DEV_NAME_Field]} != $deviceName ]]
         then
           # The "odd state" flag is set for a different file system
           # than our filesystem.  Add the name of the file system to a
           # list of filesystems to be reported to the user later.
           fsOddStateList="${fsOddStateList} ${v[$DEV_NAME_Field]}"
         else
           # The "odd state" flag is set for the file system
           # for which this command was invoked.
           :  # Allow the command to proceed, since it may succeed.
              # We will report any failures if it does not.
         fi
       else
         # Is this filesystem the one for which this command was invoked?
         if [[ ${v[$DEV_NAME_Field]} = $deviceName ]]
         then
           # Set the "odd state" field in case we don't succeed.
           # We will reset it later if tsadddisk succeeds.
           v[$ODD_STATE_Field]=mmadddisk
         fi
       fi
       ;;

    $SG_DISKS )  # This line describes a disk that belongs to some file system.
       # If this disk belongs to our file system, make sure the line
       # has a valid sequence number.  Older file systems were created
       # without numbering the lines.  Furthermore, it is possible to add
       # disks from a node that still runs a previous GPFS release and this
       # could result in SG_DISKS lines without a line number.
       if [[ ${v[$DEV_NAME_Field]} = $deviceName ]]
       then
         seqNo=seqNo+1
         v[$LINE_NUMBER_Field]=$seqNo
       fi

       # Collect the SG_DISKS lines for all free disks into a file.
       # These are the disks that are available to the new file system.
       if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]]
       then
         print_newLine >> $freeDisks
         printLine=false
       fi
       ;;

    * )  # Pass all other lines without a change.
       ;;

  esac  # end of "Change some of the fields . . . "

  # Build and write the line to the new mmsdrfs file.
  if [[ $printLine = true ]]
  then
    print_newLine >> $newsdrfs
    checkForErrors "writing to file $newsdrfs" $?
  fi

  IFS=":"  # Change the separator back to ":" for the next iteration.

done  # end while read -u3 sdrfsLine

IFS="$IFS_sv"  # Restore the default IFS settings.


###########################################################
# If a descriptor list is specified on the command line,
# create a file with one disk descriptor per line.
# Note:  If the input is in a file, descfile was created
#        by the checkUserFile function.
###########################################################
if [[ -n $desclist ]]
then
  # Copy the descriptors into a temporary file.
  $rm -f $descfile
  IFS=";"
  for diskDesc in $desclist
  do
    [[ -z $diskDesc ]] && continue
    print -- "$diskDesc" >> $descfile
    checkForErrors "writing to file $descfile" $?
  done  # end for diskDesc in $desclist
  IFS="$IFS_sv"
fi  # end of if [[ -n $desclist ]]


##########################################################
# Make sure that there is at least one free disk line.
##########################################################
if [[ ! -s $freeDisks ]]
then
  # There are no available free disks.
  printErrorMsg 470 $mmcmd $mmcmd mmcrnsd
  cleanupAndExit
fi


#########################################################################
# Process the descriptors for the new disks.  If all of the information
# is correct, the descriptor is converted into the format recognized by
# the tsadddisk command.
#########################################################################
$rm -f $tsddFile
foundErrors=false
exec 3<&-
exec 3< $descfile
while read -u3 mmDiskDesc
do
  # Skip empty and comment lines.
  [[ $mmDiskDesc = *([$BLANKchar$TABchar])   ]] && continue
  [[ $mmDiskDesc = *([$BLANKchar$TABchar])#* ]] && continue

  # Parse mmDiskDesc to get the name of the disk.
  IFS=':'
  set -f ; set -- $mmDiskDesc ; set +f
  diskName=$1
  IFS="$IFS_sv"

  if [[ -z $diskName ]]
  then
    # The disk name must be specified in the disk descriptor.
    printErrorMsg 23 $mmcmd

    # Show the bad descriptor.
    printErrorMsg 386 $mmcmd "$mmDiskDesc"

    # The command will fail, but before giving up, we will check the
    # remainder of the descriptors to flush out as many errors as possible.
    foundErrors=true
    [[ $sdrLocked = yes ]] &&  \
      freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
    sdrLocked=no

    # Move to the next descriptor.
    continue
  fi

  # Locate and extract the FREE_DISK line for this disk.
  $rm -f $tmpfile
  seqNo=seqNo+1
  freeDiskLine=$($awk -F: '                                                   \
    # If the line is for our disk, assign it to freeDiskLine.                 \
    # Do not put the line in the temp file.                                   \
    $'$DISK_NAME_Field' == "'$diskName'"  {                                   \
        { $'$LINE_NUMBER_Field' = "'$seqNo'" }                                \
        { print  $1":" $2":" $3":" $4":" $5":" $6":" $7":" $8":" $9":"$10":"  \
                $11":"$12":"$13":"$14":"$15":"$16":"$17":"$18":"$19":"$20":"  \
                $21":"$22":"$23":"$24":"$25":"$26":"$27":" }                  \
        { next }                                                              \
     }                                                                        \
    # If the line is for some other disk, add it to tmpfile.                  \
    { print $0 >> "'$tmpfile'" }                                              \
  ' $freeDisks)
  checkForErrors awk $?

  # Prepare the freeDisks file for the next iteration.
  # It will contain all of its original lines except the line
  # that describes the disk that is currently being processed.
  $touch $tmpfile    # Ensure file exists even if empty.
  $mv $tmpfile $freeDisks
  checkForErrors "mv $tmpfile $freeDisks" $?

  # If not found, issue an appropriate error message.
  if [[ -z $freeDiskLine ]]
  then
    # Check whether the disk already belongs to some file system.
    fileSystem=$(findFSforDisk "$diskName" $newsdrfs)
    if [[ -n $fileSystem ]]
    then
      # The disk is already assigned to a file system.
      # This may be because the disk was specified more than once as input,
      # or because the disk was assigned to the file system in the past.
      printErrorMsg 265 $mmcmd $diskName $fileSystem
      # Show the bad descriptor.
      printErrorMsg 386 $mmcmd "$mmDiskDesc"
    else
      # Print error stating disk descriptor should refer to an existing NSD.
      printErrorMsg 415 $mmcmd "$mmDiskDesc"
    fi

    # The command will fail, but before giving up, we will check the
    # remainder of the descriptors to flush out as many errors as possible.
    foundErrors=true
    [[ $sdrLocked = yes ]] &&  \
      freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
    sdrLocked=no

    # Move to the next descriptor.
    continue
  fi  # end of if [[ -z $freeDiskLine ]]

  # Check the correctness of the disk descriptor.  If everything is OK,
  # validateAndConvertNsdDescriptor will convert the descriptor into its
  # tsadddisk format and will create the SG_DISKS line for the new disk.
  validateDescriptorOutput=$(validateAndConvertNsdDescriptor "$mmDiskDesc"  \
                             $freeDiskLine $deviceName $fsHomeCluster mmadd)
  rc=$?
  if [[ $rc -ne 0 ]]
  then
    # If an error was found, the validate routine issued a message.
    # We will now print the entire descriptor to help the guy some more.
    printErrorMsg 386 $mmcmd "$mmDiskDesc"

    # The command will fail, but before giving up, we will check the remainder
    # of the descriptors to flush out as many errors as possible.
    foundErrors=true
    [[ $sdrLocked = yes ]] &&  \
      freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
    sdrLocked=no

    # Move to the next descriptor.
    continue
  fi   # end of if [[ $rc -ne 0 ]]

  # If the descriptor seems to be OK, parse the output
  # from the validateAndConvertNsdDescriptor routine.
  set -f ; set -- $validateDescriptorOutput ; set +f
  updatedDiskLine="$1"
  tsDiskDesc="$2"
  diskUsage="$3"

  # Add the converted descriptor to the input for tsadddisk.
  print -- $tsDiskDesc >> $tsddFile
  checkForErrors "writing to file $tsddFile" $?

  # Add the SG_DISKS line for the new disk to the mmsdrfs file.
  print -- $updatedDiskLine >> $newsdrfs
  checkForErrors "writing to file $newsdrfs" $?

done   # end of while read -u3 mmDiskDesc

# Give up if there were errors with one or more of the descriptors.
if [[ $foundErrors = true ]]
then
  # Command failed.
  printErrorMsg 389 $mmcmd
  cleanupAndExit
fi

# If there are any SG_DISKS lines for remaining free disks,
# put them back in the mmsdrfs file.
if [[ -s $freeDisks ]]
then
  $cat $freeDisks >> $newsdrfs
  checkForErrors "cat $freeDisks >> $newsdrfs" $?
fi

# Make a copy of the current mmsdrfs file.  It may be needed
# to restore the mmsdrfs file if the tsadddisk command fails.
$cp $mmsdrfsFile $oldsdrfs
checkForErrors cp $?


############################################################################
# Do the "pre-commit" of the sdrfs file.  The most important changes
# being recorded are the indication that an mmadddisk is in progress and
# the free disks that have been changed to belong to the file system with
# a disk status of mmadd to indicate they are being added by mmadddisk.
############################################################################
# Sort the new version of the mmsdrfs file.
LC_ALL=C $SORT_MMSDRFS $newsdrfs -o $newsdrfs
checkForErrors "sorting $newsdrfs" $?

trap "" HUP INT QUIT KILL    # Disable interrupts until the commit is done.
gpfsObjectInfo=$(commitChanges  \
  $fsHomeCluster $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer)
rc=$?
if [[ $rc -ne 0 ]]
then
  # We were unable to replace the file in the sdr.
  printErrorMsg 381 $mmcmd
  cleanupAndExit
fi
trap localPosttrap HUP INT QUIT KILL


################################
# Invoke the tsadddisk command.
################################
$mmcommon onactive $preferredNode $nodefile                      \
                   $tsddFile $NO_MOUNT_CHECK NULL $NO_LINK       \
                   tsadddisk "$fqDeviceName -F $tsddFile $vflag"
rc=$?
if [[ $rc -ne 0 ]]
then
  # tsadddisk failed.
  printErrorMsg 104 $mmcmd tsadddisk

  # Was the GPFS daemon up anywhere for tsadddisk to run?
  if [[ $rc -eq $MM_DaemonDown ]]
  then
    # tsadddisk was never attempted because the daemon was not up anywhere.
    # Make a modified version of the original sdrfs file with the generation
    # number in the global header incremented by 2 but no other changes.
    $rm -f $newsdrfs
    newGenNumber=$($awk -F:  '                                                 \
      BEGIN { gen = 0 }                                                        \
      # If this is the global header line, increment the gen number.           \
      /^'$GLOBAL_ID:$VERSION_LINE:'/ {                                         \
        { gen = $'$SDRFS_GENNUM_Field' + 2 }                                   \
        { $'$SDRFS_GENNUM_Field' = gen }                                       \
        { print  $1":" $2":" $3":" $4":" $5":" $6":" $7":" $8":" $9":"$10":"   \
                $11":"$12":"$13":"$14":"$15":"$16":"$17":"$18":"$19":"$20":"   \
                $21":"$22":"$23":"$24":"$25":"$26":"$27":" >> "'$newsdrfs'" }  \
        { next }                                                               \
      }                                                                        \
      # All other lines are printed without change.                            \
      { print $0 >> "'$newsdrfs'" }                                            \
      END { print gen }                                                        \
    ' $oldsdrfs)
    checkForErrors awk $?
  else
    # Since tsadddisk was attempted but failed, reconcile the
    # sdrfs file with the GPFS daemon's view of the filesystem.
    reconcileSdrfsWithDaemon $deviceName $newsdrfs
    rc2=$?
    if [[ $rc2 -ne 0 ]]
    then
      # reconcileSdrfsWithDaemon failed.
      printErrorMsg 171 $mmcmd reconcileSdrfsWithDaemon $rc2
      # Tell the user to run mmcommon recoverfs against the filesystem.
      printErrorMsg 190 $mmcmd $deviceName $deviceName
      cleanupAndExit $rc
    fi
    # Obtain the generation number from the version line of the new sdrfs file.
    versionLine=$($head -1 $newsdrfs)
    IFS=':'
    set -f ; set -- $versionLine ; set +f
    newGenNumber=$6
    IFS="$IFS_sv"
  fi  # end of if [[ $rc -eq $MM_DaemonDown ]]

  # Commit the modified version of the sdrfs file to the server.
  trap "" HUP INT QUIT KILL    # Disable interrupts until the commit is done.
  gpfsObjectInfo=$(commitChanges  \
    $fsHomeCluster $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer)
  if [[ $? -ne 0 ]]
  then
    # We were unable to replace the file in the sdr.
    printErrorMsg 381 $mmcmd
    # Tell the user to run mmcommon recoverfs against the filesystem.
    printErrorMsg 190 $mmcmd $deviceName $deviceName
  fi

  # Unlock the sdr.
  [[ $sdrLocked = yes ]] &&  \
    freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
  sdrLocked=no
  trap localPosttrap HUP INT QUIT KILL

  # Propagate the new mmsdrfs file.  This process is asynchronous.
  propagateSdrfsFile async $nodefile $newsdrfs $newGenNumber

  # Exit.
  cleanupAndExit $rc
fi


###################################################################
# If here, tsadddisk was successful.
# Invoke routine to reset the "odd state" flag on the filesystem's
# SG_HEADR line and change the SG_DISKS lines with a disk status
# of mmadd to a regular (null) disk status.  The new mmsdrfs file
# is then committed.  This makes the new disks visible to future
# mm commands and to the mmcommon getEFOptions function.
###################################################################
# Reset the status fields of the disks we just added.
resetDiskStatus $deviceName $newsdrfs mmadd
checkForErrors updateDiskStatus $?

# Obtain the generation number from the version line of the new sdrfs file.
versionLine=$($head -1 $newsdrfs)
IFS=':'
set -f ; set -- $versionLine ; set +f
newGenNumber=$6
IFS="$IFS_sv"

# Commit the new mmsdrfs file.
trap "" HUP INT QUIT KILL    # Disable interrupts until the commit is done.
gpfsObjectInfo=$(commitChanges  \
   $fsHomeCluster $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer)
rc=$?
if [[ $rc -ne 0 ]]
then
  # We were unable to replace the file in the sdr.
  printErrorMsg 381 $mmcmd
  # Tell the user to run mmcommon recoverfs against the filesystem.
  printErrorMsg 190 $mmcmd $deviceName $deviceName
  cleanupAndExit
fi


##################
# Unlock the sdr.
##################
[[ $sdrLocked = yes ]] &&  \
  freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
sdrLocked=no
trap localPosttrap HUP INT QUIT KILL


######################################################################
# Tell the daemon to invalidate its currently-cached mount options.
######################################################################
$mmcommon onactive $preferredNode $allQuorumNodes  \
                   $NO_FILE_COPY $NO_MOUNT_CHECK NULL $NO_LINK  \
                   tsctl resetEFOptions $fqDeviceName > $errMsg 2>&1
rc=$?
[[ $rc = $MM_DaemonDown ]] && rc=0
[[ $rc -ne 0 && -s $errMsg ]] && cat $errMsg 2>&1
$rm -f $errMsg


#################################################################
# Propagate the new mmsdrfs file.  This process is asynchronous.
#################################################################
propagateSdrfsFile async $nodefile $newsdrfs $newGenNumber


###################################################
# If installed, invoke the syncfsconfig user exit.
###################################################
if [[ -x $syncfsconfig ]]
then
   print -- "$mmcmd:  Starting $syncfsconfig ..."
   $syncfsconfig
   print -- "$mmcmd:  $syncfsconfig finished."
fi


#########################################
# Restripe the file system if requested.
#########################################
if [[ -n $rflag ]]
then
  if [[ -n $aflag ]]
  then
    $ln $nodefile ${nodefile}async2
    $mmcommon onactive_async $preferredNode  \
      ${nodefile}async2 $NO_FILE_COPY $NO_MOUNT_CHECK NULL $NO_LINK  \
      tsrestripefs "$fqDeviceName -b $Nflag" >/dev/null 2>/dev/null &
  else
    # Start restriping the file system.
    printInfoMsg 95 $device
    $mmcommon onactive  \
        $preferredNode $nodefile $NO_FILE_COPY $NO_MOUNT_CHECK NULL $NO_LINK  \
        tsrestripefs "$fqDeviceName -b $Nflag"
    rc=$?
    if [[ $rc -ne 0 ]]
    then
      # The restripe step failed.
      printErrorMsg 104 $mmcmd tsrestripefs
      # Warning:  File system may be unbalanced.
      printErrorMsg 313 $mmcmd
      cleanupAndExit
    else
      # Disable error message in localPosttrap.
      rflag="r"
      # Finished restriping.
      printInfoMsg 99
    fi
  fi  # end if [[ -n $aflag ]]
fi  # end if [[ -n $rflag ]]


#####################################################################
# If an "odd state" flag was encountered for any other file systems
# in the mmsdrfs file, tell the user to issue commands to reconcile
# the mmsdrfs file with the GPFS daemon's view of the filesystems.
#####################################################################
for fsname in $fsOddStateList
do
  # Tell the user to run mmcommon recoverfs against the file system.
  printErrorMsg 103 $mmcmd $fsname $fsname
done

cleanupAndExit 0

