#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2004,2007 # 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 # @(#)46 1.55.1.2 src/avs/fs/mmfs/ts/admin/mmremotefs.sh, mmfs, avs_rgpfs24, rgpfs24s012a 5/2/07 15:29:30 ############################################################################### # # Usage: # # mmremotefs add device -f remoteDevice -C remoteClusterName # -T mountPoint [-o mountOptions] [-A yes|no|automount] # # mmremotefs update device [-f remoteDevice] [-C remoteClusterName] # [-T mountPoint] [-o mountOptions] [-A yes|no|automount] # # mmremotefs delete {device | all | -C remoteClusterName} # # mmremotefs show [device | all | -C remoteClusterName] # # where # # device is the local name for the remote file system. # This name must be unique within the local cluster. # The actual name of the file system within its home cluster # may or may not be the same. See the -f parameter. # # -f remoteDevice is the actual device name for the remote file system # within the file system's home cluster. # # -C remoteClusterName is the fully-qualified name for the remote # cluster that owns the file system. # # -T mountPoint is the mount point directory of the file system. # # -o mountOptions is a comma-separated list of mount options. # The default set of options is: rw,nomtime,atime # # -A yes|no|automount controls the automount option. If yes is specified, # the file system is mounted automatically when the GPFS # daemon is started. If no is specified, the file system # can be mounted only with an explicit mount command. # If automount is specified, the mounting of the file # system is controlled by the system automount daemon. # The default setting is no. # ############################################################################### # Include global declarations and service routines. . /usr/lpp/mmfs/bin/mmglobfuncs . /usr/lpp/mmfs/bin/mmsdrfsdef . /usr/lpp/mmfs/bin/mmfsfuncs sourceFile="mmremotefs.sh" [[ -n $DEBUG || -n $DEBUGmmremotefs ]] && set -x $mmTRACE_ENTER "$*" # Local work files. Names should be of the form: # fn=${tmpDir}fn.${mmcmd}.$$ mountCheckList=${tmpDir}mountCheckList.${mmcmd}.$$ LOCAL_FILES=" $mountCheckList " # Local variables usageMsg=385 contactNodesCount=0 # Local functions ########################################################################### # # Function: Process the specified mount options string. # Provide default values for missing options. # # Input: $1 - A comma-separated list of mount options. # # Output: Colon-separated string containing the fields: # rwOption:mtimeOption:atimeOption:quotaOptions:otherOptions: # # Returns: 0 - success # 1 - error encountered # ########################################################################### function parseMountOptions # { typeset sourceFile="mmremotefs.sh" [[ -n $DEBUG || -n $DEBUGparseMountOptions ]] && set -x $mmTRACE_ENTER "$*" typeset optionsString=$1 typeset rc=0 typeset rwOption="rw" typeset mtimeOption="" typeset atimeOption="" typeset quotaOptions="" typeset otherOptions="" # Clear the string if DELETE or DEFAULT is specified. [[ $optionsString = DEFAULT || $optionsString = DELETE ]] && \ optionsString="" # Parse the options string looking for certain options. # All other options are simply passed through. IFS="," for option in $optionsString do case $option in rw | ro | rs ) [[ $option = rs ]] && option=ro rwOption=$option ;; atime* | noatime ) if [[ $option = atime || $option = "atime=1" || $option = "atime=yes" ]] then atimeOption=atime elif [[ $option = noatime || $option = "atime=0" || $option = "atime=no" ]] then atimeOption=noatime else print -u2 "$mmcmd: Invalid mount option specified: $option." return 1 fi ;; mtime* | nomtime ) if [[ $option = mtime || $option = "mtime=1" || $option = "mtime=yes" ]] then mtimeOption=mtime elif [[ $option = nomtime || $option = "mtime=0" || $option = "mtime=no" ]] then mtimeOption=nomtime else print -u2 "$mmcmd: Invalid mount option specified: $option." return 1 fi ;; syncnfs* | nosyncnfs ) if [[ $option = syncnfs || $option = "syncnfs=1" || $option = "syncnfs=yes" ]] then otherOptions="${otherOptions},syncnfs" elif [[ $option = nosyncnfs || $option = "syncnfs=0" || $option = "syncnfs=no" ]] then otherOptions="${otherOptions},nosyncnfs" else print -u2 "$mmcmd: Invalid mount option specified: $option." return 1 fi ;; *quota* ) : # Do nothing; quotas should be controlled with mmchfs -Q. ;; *rootSquash* ) : # Do nothing; root squash is controlled with mmauth grant. ;; * ) otherOptions="${otherOptions},$option" ;; esac # end of case $option in done # end of for option in $optionsString do IFS="$IFS_sv" otherOptions="${otherOptions##+(,)}" # Strip leading commas, if any. otherOptions="${otherOptions%%+(,)}" # Strip trailing commas, if any. # Put out the results and return. print -- "$rwOption:$mtimeOption:$atimeOption:$quotaOptions:$otherOptions" $mmTRACE_EXIT "rc=$rc" return $rc } #------ end of function parseMountOptions ----------------- ####################### # Mainline processing ####################### ####################################### # Process the command line arguments. ####################################### [[ $arg1 = '-?' || $arg1 = '-h' || $arg1 = '--help' || $arg1 = '--' ]] && \ syntaxError "help" $usageMsg action=$arg1 [[ -z $action ]] && \ syntaxError "missingArgs" $usageMsg # Allow "ls" to be used in place of "show". [[ $action = ls ]] && action=show # Process the positional parameters. case $action in add ) [[ $argc -lt 5 ]] && syntaxError "missingArgs" $usageMsg device=$arg2 ;; update ) [[ $argc -lt 3 ]] && syntaxError "missingArgs" $usageMsg device=$arg2 ;; delete ) [[ $argc -lt 2 ]] && syntaxError "missingArgs" $usageMsg if [[ $arg2 = "-C"* ]] then remoteClusterName=${arg2#-C} if [[ -z $remoteClusterName ]] then remoteClusterName=$arg3 [[ -n $arg4 ]] && syntaxError "extraArg" $usageMsg $arg4 else [[ -n $arg3 ]] && syntaxError "extraArg" $usageMsg $arg3 fi [[ -z $remoteClusterName ]] && syntaxError "missingValue" $usageMsg "-C" else device=$arg2 [[ -n $arg3 ]] && syntaxError "extraArg" $usageMsg $arg3 fi ;; show ) if [[ -z $arg2 ]] then device=all elif [[ $arg2 = "-C"* ]] then remoteClusterName=${arg2#-C} if [[ -z $remoteClusterName ]] then remoteClusterName=$arg3 [[ -n $arg4 ]] && syntaxError "extraArg" $usageMsg $arg4 else [[ -n $arg3 ]] && syntaxError "extraArg" $usageMsg $arg3 fi [[ -z $remoteClusterName ]] && syntaxError "missingValue" $usageMsg "-C" else device=$arg2 [[ -n $arg3 ]] && syntaxError "extraArg" $usageMsg $arg3 fi ;; *) # Invalid action specified. syntaxError "keyword" $usageMsg $action ;; esac # Verify the device name. deviceName=${device##+(/)dev+(/)} # name stripped of /dev/ prefix fqDeviceName="/dev/$deviceName" # fully-qualified name (with /dev/ prefix) if [[ $deviceName = /* ]] then printErrorMsg 169 $mmcmd $device cleanupAndExit elif [[ $deviceName = */* ]] then printErrorMsg 170 $mmcmd $device cleanupAndExit else checkName deviceName 255 "$deviceName" [[ $? -ne 0 ]] && cleanupAndExit fi # If action is "add" or "update", there are more options to process. if [[ $action = add || $action = update ]] then shift 2 # Move past the fs name in the parameter list. # Process the individual arguments and the values associated with them. while getopts :A:C:f:k:n:o:T: OPT do case $OPT in A) [[ -n $Aflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Aflag="-$OPT"; Aarg=$OPTARG; [[ $Aarg != yes && $Aarg != no && $Aarg != automount ]] && \ syntaxError "invalidOption" $usageMsg "-$OPT $OPTARG" if [[ $Aarg = yes ]] then Aarg=mmfs elif [[ $Aarg = no ]] then Aarg=false else : # It must be "automount". fi ;; C) [[ -n $Cflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Cflag="-$OPT"; Carg=$OPTARG; ;; f) [[ -n $fflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" fflag="-$OPT"; farg=$OPTARG; ;; o) [[ -n $oflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" oflag="-$OPT"; oarg=$OPTARG; [[ -z $oarg ]] && oarg=DEFAULT ;; T) [[ -n $Tflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Tflag="-$OPT"; Targ=$OPTARG; checkName pathName 1023 "$Targ" [[ $? -ne 0 ]] && cleanupAndExit # Ensure the pathname starts with a slash. [[ $Targ = ${Targ#/} ]] && \ syntaxError "absolutePath" $noUsageMsg $Targ ;; +[ACfknoT) # Invalid option. syntaxError "invalidOption" $usageMsg $OPT ;; :) # Missing argument. syntaxError "missingValue" $usageMsg $OPTARG ;; *) # Invalid option. syntaxError "invalidOption" $usageMsg $OPTARG ;; esac done shift OPTIND-1 [[ $# != 0 ]] && syntaxError "extraArg" $usageMsg $1 # Verify input parameters and assign default values as needed. if [[ $action = add ]] then [[ -z $Carg ]] && syntaxError "missingArgs" $usageMsg [[ -z $Targ ]] && syntaxError "missingArgs" $usageMsg [[ -z $farg ]] && syntaxError "missingArgs" $usageMsg [[ -z $Aarg ]] && Aarg=false if [[ $device = all ]] then # The device name cannot be "all". printErrorMsg 196 $mmcmd cleanupAndExit fi else # action = update if [[ -z $Aarg && -z $Carg && -z $farg && -z $oarg && -z $Targ ]] then # No changes made. printErrorMsg 323 $mmcmd cleanupAndExit fi fi # end of if [[ $action = add ]] # Initialize local variables. remoteDevice=${farg##+(/)dev+(/)} # name stripped of /dev/ prefix if [[ $remoteDevice = /* ]] then printErrorMsg 169 $mmcmd "$farg" cleanupAndExit elif [[ $remoteDevice = */* ]] then printErrorMsg 170 $mmcmd "$farg" cleanupAndExit else checkName deviceName 255 "$remoteDevice" [[ $? -ne 0 ]] && cleanupAndExit fi remoteClusterName=$Carg mountPoint=$Targ automountValue=$Aarg mountOptions=$oarg # Determine the values for the /etc/filesystems stanza lines. sgVFS_Line_Value="mmfs" sgTYPE_Line_Value="mmfs" sgNODENAME_Line_Value="-" sgACCOUNT_Line_Value="false" sgMOUNT_Line_Value=$automountValue # Parse the mount options. parseMountOptionsOutput=$(parseMountOptions $mountOptions) IFS=":" set -f ; set -- $parseMountOptionsOutput ; set +f sgRW_OPT_Value=$1 sgMTIME_OPT_Value=$2 sgATIME_OPT_Value=$3 sgQUOTA_OPT_Value=$4 sgOTHER_OPT_Value=$5 IFS="$IFS_sv" # The mount point cannot be the same as the device name. if [[ $fqDeviceName = $mountPoint ]] then printErrorMsg 305 $mmcmd $mountPoint cleanupAndExit fi fi # end of if [[ $action = add || $action = update ]] ##################################################################### # 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. ##################################################################### if [[ $action = show ]] then trap pretrap2 HUP INT QUIT KILL gpfsInitOutput=$(gpfsInit nolock) rc=$? else trap pretrap HUP INT QUIT KILL gpfsInitOutput=$(gpfsInit $lockId) rc=$? fi setGlobalVar $rc $gpfsInitOutput # Determine the lookup order for resolving host names. [[ $osName != AIX ]] && resolveOrder=$(setHostResolveOrder) ############################################################################# # # Go through the mmsdrfs file. # # If action is "add", extract needed information to ensure that we can # safely add the new remote file system. # # If action is "update", make the needed changes to the mmsdrfs file. # # If action is "delete", remove the appropriate lines from the mmsdrfs file. # # If action is "show", extract and display the relevant information. # ############################################################################# $rm -f $newsdrfs $nodefile $mountCheckList deleteThisFileSystem=no IFS=":" 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 ) # Increment the generation number. newGenNumber=${v[$SDRFS_GENNUM_Field]}+1 v[$SDRFS_GENNUM_Field]=$newGenNumber ourClusterName=${v[$CLUSTER_NAME_Field]} ;; $MEMBER_NODE ) # Add the reliable node name to nodefile. print -- "${v[$REL_HOSTNAME_Field]}" >> $nodefile checkForErrors "writing to file $nodefile" $? # If this is the line for the node that is executing # this command, set the preferredNode variable. [[ ${v[$NODE_NUMBER_Field]} = $ourNodeNumber ]] && \ preferredNode=${v[$REL_HOSTNAME_Field]} ;; $SG_HEADR ) # Processing depends on the specified action: case $action in add ) # Make sure that the file system that we want to create # does not already exist. if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] then printErrorMsg 107 $mmcmd $device cleanupAndExit fi if [[ ${v[$REMOTE_DEV_NAME_Field]} = $remoteDevice && ${v[$NODESETID_Field]} = $remoteClusterName ]] then # The file system on the remote cluster is already defined. printErrorMsg 317 $mmcmd $remoteDevice $remoteClusterName cleanupAndExit fi # Make a list of the used minor numbers. existingMinorNumbers="$existingMinorNumbers ${v[$DEV_MINOR_Field]}" ;; update ) if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] then # We are making changes to this remote file system. fsFound=yes # Generate the fully-qualified name for the file system. fsFullName="${v[$NODESETID_Field]}:${v[$REMOTE_DEV_NAME_Field]}" # Verify that this is indeed a remote file system. if [[ ${v[$FS_TYPE_Field]} != $remotefs ]] then # The file system is not a remote file system known to GPFS. printErrorMsg 252 $mmcmd $device cleanupAndExit fi if [[ -n $remoteDevice ]] then # We are changing the actual name of the file system. v[$REMOTE_DEV_NAME_Field]=$remoteDevice fsMustNotBeMounted=yes fi if [[ -n $remoteClusterName ]] then # We are changing the home cluster name. v[$NODESETID_Field]=$remoteClusterName fsMustNotBeMounted=yes fi fi # end of if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] ;; delete ) if [[ (${v[$DEV_NAME_Field]} = $deviceName || $device = all || ${v[$NODESETID_Field]} = $remoteClusterName) && ${v[$FS_TYPE_Field]} = $remotefs ]] then # This file system is going away. deleteThisFileSystem=yes fsFound=yes # Generate the fully-qualified name for the file system. # Put it, together with the local device name, on the list # of file systems that should not be mounted. fsFullName="${v[$NODESETID_Field]}:${v[$REMOTE_DEV_NAME_Field]}" print -- "$fsFullName $deviceName" >> $mountCheckList checkForErrors "writing to file $mountCheckList" $? else # This file system will remain in place. deleteThisFileSystem="" if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] then # The file system is not a remote file system known to GPFS. printErrorMsg 252 $mmcmd $device cleanupAndExit fi fi # end of if [[ (${v[$DEV_NAME_Field]} = $deviceName ... ]] [[ -n $deleteThisFileSystem ]] && \ printLine=false ;; show ) if [[ (${v[$DEV_NAME_Field]} = $deviceName || $device = all || ${v[$NODESETID_Field]} = $remoteClusterName) && ${v[$FS_TYPE_Field]} = $remotefs ]] then fsFound=yes displayThisFileSystem=yes if [[ -z $headerOut ]] then # Output the header line. header=$(printInfoMsg 490) printf "%s\n" "$header" headerOut=yes fi # Start outputting the individual fields. printf "%-11s %-12s %-22s" "${v[$DEV_NAME_Field]}" \ "${v[$REMOTE_DEV_NAME_Field]}" "${v[$NODESETID_Field]}" else displayThisFileSystem="" if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] then # The file system is not a remote file system known to GPFS. printErrorMsg 252 $mmcmd $device cleanupAndExit fi fi # end of if [[ (${v[$DEV_NAME_Field]} = $deviceName ... ;; *) checkForErrors "unexpected action $action" 1 ;; esac # end case $action in ;; $SG_ETCFS ) # Processing depends on the specified action: case $action in add ) # Make sure that the new mount point is not already used # by some other file system in the nodeset. if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line && ${v[$ETCFS_TEXT_Field]} = $mountPoint ]] then printErrorMsg 107 $mmcmd $mountPoint cleanupAndExit fi # See if any of the existing file systems requires # the system automounter. if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_Line && ${v[$ETCFS_TEXT_Field]} = *automount* ]] then automountMounts=yes fi ;; update ) if [[ -n $mountPoint ]] then # We are changing the mount point. if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line ]] then # This is a mount point line for some file system. # If this is the mount point for our file system, # set it to the new value. Otherwise, add it to # the list of existing mount points. if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] then oldMountPoint=${v[$ETCFS_TEXT_Field]} v[$ETCFS_TEXT_Field]=$mountPoint fsMustNotBeMounted=yes else existingMountPoints="$existingMountPoints ${v[$ETCFS_TEXT_Field]}" fi fi fi # end of if [[ -n $mountPoint ]] if [[ -n $automountValue ]] then # We are changing the automount option. if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_Line ]] then # This is a mount line for some file system, i.e., # the ' mount = ... ' line in etc/filesystems. # See if any file system requires the system automounter. [[ ${v[$ETCFS_TEXT_Field]} = *automount* ]] && \ automountMounts=yes # If this is the mount line for our file system, # set the new value for the mount option. if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] then # If switching to or from automount, # the file system must be unmounted. [[ $automountValue = automount || ${v[$ETCFS_TEXT_Field]} = *automount* ]] && \ fsMustNotBeMounted=yes # Set the new value for the mount option. v[$ETCFS_TEXT_Field]="$MOUNT_Line_Prefix$automountValue" fi # end of if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] fi # end of if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_Line ]] fi # end of if [[ -n $automountValue ]] if [[ -n $remoteClusterName && ${v[$DEV_NAME_Field]} = $deviceName ]] then # We are changing the home cluster name. v[$NODESETID_Field]=$remoteClusterName fi ;; delete ) [[ -n $deleteThisFileSystem ]] && \ printLine=false ;; show ) if [[ -n $displayThisFileSystem ]] then # Output the mount point. [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line ]] && \ printf " %-20s" "${v[$ETCFS_TEXT_Field]}" # Determine the automount value. It will be displayed last. if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_Line ]] then automountSetting=${v[$ETCFS_TEXT_Field]#$MOUNT_Line_Prefix} if [[ $automountSetting = mmfs ]] then automountSetting=yes elif [[ $automountSetting = false ]] then automountSetting=no else : # Leave the value as is. fi fi # end of if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_Line ]] fi # end of if [[ -n $displayThisFileSystem ]] ;; *) checkForErrors "unexpected action $action" 1 ;; esac # end case $action in ;; $SG_MOUNT ) # Processing depends on the specified action: case $action in add ) : # There is nothing to do. ;; update ) if [[ -n $mountOptions && ${v[$DEV_NAME_Field]} = $deviceName ]] then # We are changing the mount options for this remote file system. v[$RW_OPT_Field]=$sgRW_OPT_Value v[$MTIME_OPT_Field]=$sgMTIME_OPT_Value v[$ATIME_OPT_Field]=$sgATIME_OPT_Value v[$QUOTA_OPT_Field]=$sgQUOTA_OPT_Value v[$OTHER_OPT_Field]=$sgOTHER_OPT_Value fi if [[ -n $remoteClusterName && ${v[$DEV_NAME_Field]} = $deviceName ]] then # We are changing the home cluster name. v[$NODESETID_Field]=$remoteClusterName fi ;; delete ) [[ -n $deleteThisFileSystem ]] && \ printLine=false ;; show ) if [[ -n $displayThisFileSystem ]] then # Generate the mount options string. optionsString="${v[$RW_OPT_Field]}" [[ -n ${v[$MTIME_OPT_Field]} ]] && \ optionsString="${optionsString},${v[$MTIME_OPT_Field]}" [[ -n ${v[$ATIME_OPT_Field]} ]] && \ optionsString="${optionsString},${v[$ATIME_OPT_Field]}" [[ -n ${v[$OTHER_OPT_Field]} ]] && \ optionsString="${optionsString},${v[$OTHER_OPT_Field]}" [[ -n ${v[$QUOTA_OPT_Field]} ]] && \ optionsString="${optionsString},quota=${v[$QUOTA_OPT_Field]}" # Put out the last two values and finish the line. printf " %-16s %s\n" "$optionsString" "$automountSetting" fi # end of if [[ -n $displayThisFileSystem ]] ;; *) checkForErrors "unexpected action $action" 1 ;; esac # end case $action in ;; $REM_CLUSTER ) [[ ${v[$NODESETID_Field]} = $remoteClusterName ]] && \ remoteClusterFound=yes ;; * ) # 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 mmsdrfsFile IFS="$IFS_sv" # Restore the default IFS settings. if [[ -z $fsFound && $action != add ]] then if [[ (-z $device || $device = all) && ($action = show || $action = delete) ]] then # There are no remote file systems. printErrorMsg 193 $mmcmd else # Remote file system not found. printErrorMsg 194 $mmcmd $device fi cleanupAndExit fi # end of if [[ -z $clusterFound ]] ######################################### # Additional action-specific processing. ######################################### ############################### # If action is "show", return. ############################### if [[ $action = show ]] then # Return; we are done. cleanupAndExit $rc fi # end of if [[ $action = show ]] ####################################################### # If action is "update", perform final error checking. ####################################################### if [[ $action = update ]] then # If the mount point for a file system is being changed, # ensure that the new mount point is not already in use. if [[ -n $mountPoint ]] then for mpnt in $existingMountPoints do if [[ $mpnt = $mountPoint ]] then # There is already an existing filesystem using this mountpoint. printErrorMsg 107 $mmcmd $mountPoint cleanupAndExit fi done fi # end of if [[ -n $mountPoint ]] # If the home cluster for a file system is being changed, # ensure that the new cluster is already defined. if [[ -n $remoteClusterName && -z $remoteClusterFound ]] then # The remote cluster is not defined. printErrorMsg 263 $mmcmd $remoteClusterName cleanupAndExit fi # If appropriate, put the file system on the list # of file systems that should not be mounted. if [[ -n $fsMustNotBeMounted ]] then print -- "$fsFullName $deviceName" >> $mountCheckList checkForErrors "writing to file $mountCheckList" $? fi fi # end of if [[ $action = update ]] ############################################################################# # If action is "add", generate the needed information for the mmsdrfs file. ############################################################################# if [[ $action = add ]] then # Ensure the remote cluster that we need is already defined. if [[ -z $remoteClusterFound ]] then # The remote cluster was not found. printErrorMsg 188 $mmcmd $remoteClusterName cleanupAndExit fi # end of if [[ -z $remoteClusterFound ]] # Determine what the major number should be. if [[ $osName = Linux ]] then checkVfsNumber devMajor=$currentMajorNumber fi [[ -z $devMajor ]] && devMajor=$defaultMajorNumber # Assign a minor number to the file system. # Keep trying until we get a minor number that is not used by anybody. rc=0 minor="" while [[ -z $minor && $rc -eq 0 ]] do # Assign a minor number to the file system. devMinor=$(assignDevMinor "$existingMinorNumbers") rc=$? if [[ $rc -eq 0 ]] then # Check whether the new device number is being used by somebody. inuse=$($ls -lL /dev 2>/dev/null | $grep "^${fsDeviceType}.* $devMajor, *$devMinor ") if [[ -z $inuse ]] then # The number seems to be free. minor=$devMinor fi # Add the number to the list of existing minor numbers. existingMinorNumbers="$existingMinorNumbers $devMinor" fi # end of if [[ $rc -eq 0 ]] done # end of while [[ -z $minor && $rc -eq 0 ]] if [[ -z $minor ]] then print -u2 "$mmcmd: Cannot assign a minor number for the file system." cleanupAndExit fi # Build the SG-related lines for the new file system. # Note: In order to preserve the tab characters in the /etc/filesystems lines, # we temporarily reset the value of the IFS variable to exclude the tab. IFS=' ' newLine="$remoteClusterName:$SG_HEADR:$deviceName::$minor::$remotefs:$remoteDevice" print -- "$newLine" >> $newsdrfs newLine="$remoteClusterName:$SG_ETCFS:$deviceName:$MOUNT_POINT_Line:$mountPoint:" print -- "$newLine" >> $newsdrfs newLine="$remoteClusterName:$SG_ETCFS:$deviceName:$DEV_Line" newLine="$newLine:$DEV_Line_Prefix$fqDeviceName" print -- "$newLine" >> $newsdrfs newLine="$remoteClusterName:$SG_ETCFS:$deviceName:$VFS_Line" newLine="$newLine:$VFS_Line_Prefix$sgVFS_Line_Value" print -- "$newLine" >> $newsdrfs newLine="$remoteClusterName:$SG_ETCFS:$deviceName:$NODENAME_Line" newLine="$newLine:$NODENAME_Line_Prefix$sgNODENAME_Line_Value" print -- "$newLine" >> $newsdrfs newLine="$remoteClusterName:$SG_ETCFS:$deviceName:$MOUNT_Line" newLine="$newLine:$MOUNT_Line_Prefix$sgMOUNT_Line_Value" print -- "$newLine" >> $newsdrfs newLine="$remoteClusterName:$SG_ETCFS:$deviceName:$TYPE_Line" newLine="$newLine:$TYPE_Line_Prefix$sgTYPE_Line_Value" print -- "$newLine" >> $newsdrfs newLine="$remoteClusterName:$SG_ETCFS:$deviceName:$ACCOUNT_Line" newLine="$newLine:$ACCOUNT_Line_Prefix$sgACCOUNT_Line_Value" print -- "$newLine" >> $newsdrfs newLine="$remoteClusterName:$SG_MOUNT:$deviceName::$sgRW_OPT_Value" newLine="$newLine:$sgMTIME_OPT_Value:$sgATIME_OPT_Value" newLine="$newLine:$sgQUOTA_OPT_Value:$sgOTHER_OPT_Value:" print -- "$newLine" >> $newsdrfs checkForErrors "writing to file $newsdrfs" $? IFS="$IFS_sv" fi # end of if [[ $action = add ]] ######################################################### # If this is the first automountable GPFS file system, # run the automount command on the nodes in the cluster. ######################################################### if [[ $automountValue = "automount" && -z $automountMounts ]] then # Determine the value of the automountDir parameter. automountDir=$(showCfgValue automountDir) [[ -z $automountDir ]] && automountDir=$defaultAutomountDir # Run the automount command on the nodes on which GPFS is active. # On nodes that do not have GPFS running right now, this will be # done by the mmchecksubsys processing when the daemon is started. $mmcommon onactive $preferredNode $nodefile \ $NO_FILE_COPY $NO_MOUNT_CHECK NULL $NO_LINK \ tsdsh $mmremote startAutomounter $automountDir >$tmpfile 2>&1 rc=$? # Ignore errors but show messages from the nodes, if any. if [[ $rc -ne 0 && $rc -ne $MM_DaemonDown && -s $tmpfile ]] then $awk ' \ # Skip the lines with rc values. \ $2 == "rc" { next } \ # Print everything else. \ { print $0 } \ ' $tmpfile fi # end of if [[ -s $tmpfile ]] fi # end of if [[ $automountValue = "automount" && -z $automountMounts ]] ############################################ # Sort the new version of the mmsdrfs file. ############################################ LC_ALL=C $SORT_MMSDRFS $newsdrfs -o $newsdrfs checkForErrors "sorting $newsdrfs" $? ################################################### # Lock the gpfs object to prevent any GPFS daemons # from starting during the commit phase. ################################################### [[ $getCredCalled = no ]] && getCred setRunningCommand "$mmcmd" $primaryServer checkForErrors setRunningCommand $? gpfsLocked=yes ################################################################ # Make sure that file systems that should not be mounted # are indeed not mounted. Note that the scope of the mount # restriction is our own cluster only. It is OK for the file # systems to be mounted elsewhere. ################################################################ if [[ -s $mountCheckList ]] then exec 3<&- exec 3< $mountCheckList while read -u3 mountCheckLine do # Parse the line. set -f ; set -- $mountCheckLine ; set +f fsFullName=$1 localDevName=$2 $mmcommon onactive $preferredNode $nodefile $NO_FILE_COPY \ $fsFullName $ourClusterName $NO_LINK $MOUNT_CHECK_ONLY ldev=$localDevName 2>$errMsg rc=$? if [[ $rc -eq $MM_FsMounted ]] then # The file system is still mounted (messages were issued by mmcommon). $rm -f $errMsg cleanupAndExit elif [[ $rc -eq $MM_FsNotFound || $rc -eq $MM_Remotefs ]] then # The file system was not found, so it cannot be mounted. rc=0 elif [[ $rc -eq $MM_HostDown || $rc -eq $MM_TimedOut || $rc -eq $MM_UnknownCluster || $rc -eq $MM_SecurityCfg || $rc -eq $MM_AuthorizationFailed ]] then # We failed to connect to the remote cluster. rc=0 if [[ $device != all ]] then # There is only one remote cluster, and we could not connect to it. # Exit the loop since none of its file systems can be mounted. break fi elif [[ $rc -eq $MM_DaemonDown ]] then # GPFS is down on all nodes in the local cluster. # There are no mounted file systems, so exit the loop. rc=0 break elif [[ $rc -eq $MM_ConnectionReset ]] then # An internode connection was reset. printErrorMsg 257 $mmcmd elif [[ $rc -ne 0 ]] then if [[ -s $errMsg ]] then # Show the error messages from the daemon. $cat $errMsg 1>&2 else # The mount check failed and there were no messages from the daemon. printErrorMsg 171 $mmcmd "mount check for $fsFullName" $rc fi # The command was unable to determine whether the file system is mounted. printErrorMsg 564 $mmcmd $localDevName cleanupAndExit fi # end of if [[ $rc -eq $MM_FsMounted ]] $rm -f $errMsg done # end of while read -u3 mountCheckLine $rm -f $errMsg fi # end of if [[ -s $mountCheckList ]] ############################################################ # Replace the mmsdrfs file in the sdr with the new version. ############################################################ trap "" HUP INT QUIT KILL gpfsObjectInfo=$(commitChanges \ $nsId $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer) rc=$? if [[ $rc -ne 0 ]] then # The commit step failed; we cannot replace the file in the sdr. printErrorMsg 381 $mmcmd cleanupAndExit fi ############################################################# # Unlock the sdr. ############################################################# freeLockOnServer $primaryServer $ourNodeNumber >/dev/null sdrLocked=no trap posttrap HUP INT QUIT KILL ######################################################################### # Make the new file system visible to the nodes. This includes adding # a stanza to /etc/filesystems and creating the mount point directory. # If the mount point changed, remove the old mount point. # This process is asynchronous. ######################################################################### [[ -n $oldMountPoint && $mountPoint != $oldMountPoint ]] && \ propagateOptions="rmdir$oldMountPoint" propagateSdrfsFile async $nodefile $newsdrfs $newGenNumber $propagateOptions cleanupAndExit 0