source: gpfs_3.1_ker2.6.20/lpp/mmfs/bin/mmcommon @ 223

Last change on this file since 223 was 16, checked in by rock, 17 years ago
  • Property svn:executable set to *
File size: 103.6 KB
Line 
1#!/bin/ksh
2# IBM_PROLOG_BEGIN_TAG
3# This is an automatically generated prolog.
4
5
6
7# Licensed Materials - Property of IBM
8
9# (C) COPYRIGHT International Business Machines Corp. 1997,2006
10# All Rights Reserved
11
12# US Government Users Restricted Rights - Use, duplication or
13# disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
14
15# IBM_PROLOG_END_TAG
16# @(#)76 1.83.1.177 src/avs/fs/mmfs/ts/admin/mmcommon.sh, mmfs, avs_rgpfs24, rgpfs24s008a 11/8/06 12:34:03
17#############################################################################
18#
19# Usage:  mmcommon keyword <arguments>
20#
21#############################################################################
22
23# Include global declarations and service routines.
24. /usr/lpp/mmfs/bin/mmglobfuncs
25. /usr/lpp/mmfs/bin/mmsdrfsdef
26. /usr/lpp/mmfs/bin/mmfsfuncs
27
28sourceFile="mmcommon.sh"
29[[ -n $DEBUG || -n $DEBUGmmcommon ]] && set -x
30$mmTRACE_ENTER "$*"
31
32# Local work files.  Names should be of the form:
33#   fn=${tmpDir}fn.${mmcmd}.$$
34
35LOCAL_FILES=" "
36
37
38# Local variables
39typeset -l kword_lc
40typeset -l arg3_lc
41integer n
42rc=0
43
44# Local functions
45
46#####################################################################
47#
48# Function:  Runs the specified command on the first active node
49#            (i.e., node on which the GPFS daemon is running)
50#            it finds in the list of nodes provided by the caller.
51#
52# Input:     $1 - name of the node to try first, or 0
53#            $2 - file with reliable node names
54#            $3 - file to copy on the remote node, or _NO_FILE_COPY_
55#            $4 - file system that cannot be mounted, or _NO_MOUNT_CHECK_
56#            $5 - scope of mount checking
57#            $6 - symbolic link indicator: _LINK_ or _NO_LINK_
58#            $7 - command to execute; must be mmremote or tsxxxxxxx
59#            $8 - argument list for the remote command
60#
61# Output:    Depends on the particular remote command
62#
63# Returns:   0 - command completed successfully
64#            return code from the remote command
65#
66#####################################################################
67function runRemoteCommand  # <preferredNode> <nodeFile> <fileToCopy>
68                           # <fsToCheck> <symLink> <scope> <command> <args>
69{
70  typeset sourceFile="mmcommon.sh"
71  [[ -n $DEBUG || -n $DEBUGrunRemoteCommand ]] && set -x
72  $mmTRACE_ENTER "$*"
73  typeset preferredNode=$1
74  typeset nodeFile=$2
75  typeset fileToCopy=$3
76  typeset fsToCheck=$4
77  typeset scope=$5
78  typeset symLink=$6
79  typeset command=$7
80  typeset args=$8
81
82  typeset rc=0
83  typeset nodeName rcInfo lsrc
84
85  # If this is a single node environment, assure that
86  # the command will be executed locally.
87  [[ $MMMODE = single ]] && preferredNode=$ourNodeName
88
89  # If there is no preferred node, see if the local node is in the list.
90  [[ $preferredNode = "0" ]] &&  \
91    preferredNode=$($grep -w $ourNodeName $nodeFile)
92
93  # Try the nodes one by one until the command is executed somewhere.
94  # Always start with the local node first, if it is in the list.
95  [[ -z $preferredNode ]] && preferredNode="$BLANKchar"
96  for nodeName in $(print -- "$preferredNode" ; $grep -v -w "$preferredNode" $nodeFile)
97  do
98    # If nodeName refers to the node that we are running on,
99    # try to execute the command locally.
100    if [[ $nodeName = $ourNodeName ]]
101    then
102      runLocalCommand $fsToCheck $scope $symLink $command "$args"
103      rc=$?
104      # If this is a single node environment, there is nothing more to do.
105      [[ $MMMODE = single ]] && break
106
107      # If acceptable error (daemon not up or waiting for quorum),
108      # try to find some other node to run the command.  Otherwise,
109      # the command was executed and either succeeded or failed.
110      # Either way, pass the result to the caller.
111      if [[ $rc -eq $MM_DaemonDown || $rc -eq $MM_QuorumWait ]]
112      then
113        continue
114      else
115        return $rc
116      fi
117    fi  # end of if [[ $nodeName = $ourNodeName ]]
118
119    # Invoke mmdsh to run the command on the remote node.
120    $rm -f $tmpDir$command$$.*
121    $mmdsh -svL $nodeName $mmremote onbehalf $ourNodeName $command$$  \
122      $MMMODE $fileToCopy $fsToCheck $scope $symLink $command "$args"
123    rc=$?
124
125    #----------------------------------------------------------------------
126    #
127    # Determine the return code from the remote command.
128    #
129    # This is not an easy task because rsh and different versions of
130    # ssh treat the return codes from the remote command differently.
131    # For example, rsh does not propagate back the return code, while
132    # at least some of the ssh versions pass back the return code.
133    # This also makes it very difficult to distinguish between failures
134    # of rsh/ssh itself and failures of the remote command.
135    #
136    # Our solution is to pass back the return code by creating a special
137    # file that has the return code appended at the end of its name.
138    # If we do not see this file on our side, we will assume that mmdsh
139    # returned the return code from the remote command.  Although this is
140    # not necessarily always the case (there could have been a problem
141    # with the touch command that creates the special file) it is the best
142    # we can do under the circumstances.
143    #----------------------------------------------------------------------
144
145    # Look for the return code to be encoded in a special file name.
146    rcInfo=$($ls $tmpDir$command$$.* 2> /dev/null)
147    $rm -f $tmpDir$command$$.*
148    if [[ -n $rcInfo ]]
149    then
150      # The return code was passed back via the empty file mechanism.
151      # Extract the return code from the file name.
152      rc=${rcInfo#$tmpDir$command$$\.}
153
154      # If acceptable error (daemon not up or waiting for quorum),
155      # try to find some other node to run the command.  Otherwise,
156      # the command was executed and either succeeded or failed.
157      # Either way, pass the result to the caller.
158      if [[ $rc -eq $MM_DaemonDown || $rc -eq $MM_QuorumWait ]]
159      then
160        continue
161      else
162        return $rc
163      fi
164    fi  # end if [[ -n $rcInfo ]]
165
166    # Assume mmdsh returned the return code from the remote command.
167    if [[ $rc -eq $MM_DaemonDown     ||
168          $rc -eq $MM_QuorumWait     ||
169          $rc -eq $MM_HostDown       ||
170          $rc -eq $MM_ConnectTimeout ]]
171    then
172      # If the daemon is not up, if it is waiting for quorum, or if mmdsh
173      # could not get to the node, try another node to run the command.
174      continue
175    fi
176
177    if [[ $rc -ne 0 ]]
178    then
179      # The command failed.
180      printErrorMsg 104 "runRemoteCommand" "$nodeName: $command $args"
181    fi
182
183    # Whether the command executed successfully or not,
184    # return to the caller with the return code.
185    return $rc
186
187  done  # end for nodeName in $(print -- "$preferredNode" ; $cat $nodeFile)
188
189  if [[ $MMMODE = single       &&
190        $rc -ne $MM_DaemonDown &&
191        $rc -ne $MM_QuorumWait ]]
192  then
193    return $rc
194  fi
195
196  # If we ever get here, all nodes were tried, but the command could not be
197  # executed.  Either all nodes are down, or the daemon is down on all nodes.
198  [[ $command != $MOUNT_CHECK_ONLY ]] &&  \
199    printErrorMsg 312 $mmcmd $command
200  rc=$MM_DaemonDown
201
202  return $rc
203
204}  #----- end of function runRemoteCommand -----------------------
205
206
207#############################################################################
208#
209# Function:  Generate a list of all disk devices known to this node.
210#
211# Input:     None.
212#
213# Output:    For each device, a line is generated containing the following:
214#              device_name device_type
215#
216# Returns:   Always zero.  Errors are ignored.
217#
218#############################################################################
219function getDiskDevices  #
220{
221  typeset sourceFile="mmcommon.sh"
222  [[ -n $DEBUG || -n $DEBUGgetDiskDevices ]] && set -x
223  $mmTRACE_ENTER "$*"
224
225  # Get the names of all disks, vpaths, etc.
226  if [[ $osName = AIX ]]
227  then
228    LC_ALL=C $getlvodm -F 2>/dev/null |                 \
229      $awk '                                            \
230        /hdiskpower/  { print $1 " powerdisk" ; next }  \
231        /dlmfdrv/     { print $1 " dlmfdrv"   ; next }  \
232        /vpath/       { print $1 " vpath"     ; next }  \
233        /hdisk/       { print $1 " hdisk"     ; next }  \
234      '
235
236  elif [[ $osName = Linux ]]
237  then
238    $awk '                                                                 \
239      /emcpower/   { if (NF > 3 && $3 > 1) print $4 " powerdisk" ; next }  \
240      /vpath/      { if (NF > 3 && $3 > 1) print $4 " vpath"     ; next }  \
241      /[sh]d/      { if (NF > 3 && $3 > 1) print $4 " generic"   ; next }  \
242    ' /proc/partitions 2>/dev/null
243
244  else
245    print -u2  " Unknown operating system $osName "
246    cleanupAndExit
247  fi
248
249  return 0
250
251}  #----- end of function getDiskDevices ------------------------
252
253
254#############################################################################
255#
256# Function:  Generate a file correlating node numbers, IP addresses,
257#            and reliable node names for nodes in the cluster.
258#            The values are obtained from the latest mmsdrfs file.
259#
260# Input:     $1 - name of the node data file to create
261#            $2 - (optional) nodeset for which to return information.
262#                 If missing, or if GLOBAL_ID specified, return all
263#                 nodes in the cluster.
264#
265# Output:    Each record of the output file consists of the following
266#            fields (separated with a single blank character):
267#
268#              node_number ip_address adapter_type reliable_hostname  \
269#                 switch_node_number adapter_type hags_node_number
270#
271# Returns:   0 - file created successfully
272#            If an error is encountered, this function invokes the
273#            cleanupAndExit routine which terminates execution.
274#
275#############################################################################
276function getNodeDataFromSdrfs  # <fileName> [<nodesetId>]
277{
278  typeset sourceFile="mmcommon.sh"
279  [[ -n $DEBUG || -n $DEBUGgetNodeDataFromSdrfs ]] && set -x
280  $mmTRACE_ENTER "$*"
281  typeset outfile=$1
282  typeset nodesetId=$2
283
284  typeset gpfsInitOutput
285
286  [[ -z $outfile ]] &&  \
287    checkForErrors "getNodeDataFromSdrfs - Missing output file parameter" 1
288
289  # Ensure the GPFS system data is up to date.
290  gpfsInitOutput=$(gpfsInit nolock)
291  setGlobalVar $? $gpfsInitOutput
292
293  [[ ! -f $mmsdrfsFile ]] && return 0
294
295  # If a nodeset id is not specified, or if the global id is specified,
296  # clear the variable so that we can look at all MEMBER_NODE lines.
297  # Otherwise, prepend the '^' char to ensure a correct nodesetId match.
298  [[ $nodesetId = "." ]] && nodesetId="$nsId"
299  [[ $nodesetId = 0 ]] && return 0
300  [[ $nodesetId = $GLOBAL_ID ]] && nodesetId=""
301  [[ -n $nodesetId ]] && nodesetId="^$nodesetId"
302
303  # Generate a list with the requested node information.
304  $rm -f $outfile
305  $awk -F: '                                                 \
306    /'$nodesetId:$MEMBER_NODE:'/ {                           \
307        # If this is an older cluster, the value for the     \
308        # HAGS number may not be in the mmsdrfs file yet.    \
309        if ( $'$GS_NODE_NUMBER_Field' == "" ) {              \
310          { gsNodeNumber = $'$NODE_NUMBER_Field' }           \
311        } else {                                             \
312          { gsNodeNumber = $'$GS_NODE_NUMBER_Field' }        \
313        }                                                    \
314        # Write the information to the specified file.       \
315        { print $'$NODE_NUMBER_Field' " "                    \
316                $'$IPA_Field' " "                            \
317                $'$ADAPTER_TYPE_Field' " "                   \
318                $'$REL_HOSTNAME_Field' " "                   \
319                $'$SWITCH_NODE_NUMBER_Field' " "             \
320                $'$ADAPTER_TYPE_Field' " "                   \
321                gsNodeNumber  >> "'$outfile'" }              \
322    }                                                        \
323  ' $mmsdrfsFile
324  checkForErrors awk $?
325
326  return 0
327
328}  #----- end of function getNodeDataFromSdrfs --------------------
329
330
331#############################################################################
332#
333# Function:  Generate a node list file showing the node number, IP address,
334#            node name, and attributes (quorum/nonquorum, manager/client,
335#            new) for all nodes in the cluster.
336#            The values are obtained from the latest mmsdrfs file.
337#            Since this routine is used by the daemon to obtain node data,
338#            the node name returned is the one used by the GPFS daemons,
339#            not the one used by the admin commands, although these are
340#            usually the same.
341#
342# Input:     $1 - name of the node data file to create
343#            $2 - (optional) assume cached data is current
344#
345# Output:    Each record of the output file consists of the following
346#            fields (separated with a single blank character):
347#
348#              node_number ip_address nodename attributes...
349#
350#            where "attributes..." is a string containing a set of
351#            comma-separated attribute values.
352#
353# Returns:   0 - file created successfully
354#            If an error is encountered, this function invokes the
355#            cleanupAndExit routine which terminates execution.
356#
357#############################################################################
358function getNodeListFromSdrfs  # <fileName> [norefresh]
359{
360  typeset sourceFile="mmcommon.sh"
361  [[ -n $DEBUG || -n $DEBUGgetNodeListFromSdrfs ]] && set -x
362  $mmTRACE_ENTER "$*"
363  typeset outfile=$1
364  typeset -l refreshArg=$2
365
366  typeset gpfsInitOutput
367
368  [[ -z $outfile ]] &&  \
369    checkForErrors "getNodeListFromSdrfs - Missing output file parameter" 1
370
371  # Ensure the GPFS system data is up to date.
372  if [[ $refreshArg != "norefresh" ]]
373  then
374    gpfsInitOutput=$(gpfsInit nolock)
375    setGlobalVar $? $gpfsInitOutput
376  fi
377
378  [[ ! -f $mmsdrfsFile ]] &&  \
379    checkForErrors "getNodeListFromSdrfs - Missing /var/mmfs/gen/mmsdrfs" 1
380
381  # Generate a file with the requested node information.
382  $rm -f $outfile
383  $awk -F: '                                                  \
384    BEGIN { separator = "," }                                 \
385    /'$HOME_CLUSTER:$MEMBER_NODE:'/ {                         \
386      # Collect all attributes for this node.                 \
387      { attrs = $'$DESIGNATION_Field' }                       \
388      if ( $'$CORE_QUORUM_Field' == "'$quorumNode'" ) {       \
389        { attrs = attrs separator "'$QUORUM'" }               \
390      }                                                       \
391      if ( $'$ADDNODE_STATE_Field' != "" ) {                  \
392        { attrs = attrs separator $'$ADDNODE_STATE_Field' }   \
393      }                                                       \
394      if ( $'$DAEMON_NODENAME_Field' == "" ) {                \
395        { nodename = $'$REL_HOSTNAME_Field' }                 \
396      } else {                                                \
397        { nodename = $'$DAEMON_NODENAME_Field' }              \
398      }                                                       \
399      # Write the information to the specified file.          \
400      { print $'$NODE_NUMBER_Field'  " "                      \
401              $'$IPA_Field'          " "                      \
402              nodename " " attrs >> "'$outfile'" }            \
403    }                                                         \
404  ' $mmsdrfsFile
405  checkForErrors awk $?
406
407  return 0
408
409}  #----- end of function getNodeListFromSdrfs --------------------
410
411
412#######################################################################
413#
414# Function:  Generate a file with the global group names and size of
415#            all known VSDs, as well as their primary and secondary
416#            servers and recovery state.
417#
418# Input:     $1 - name of file for the VSD information
419#
420# Output:    Each record of the output file consists of the following
421#            colon-separated fields:
422#
423#   group_name:vsd_name:size:primary_node:secondary_node:recovery:vgname
424#
425# Returns:   0 - file created successfully
426#            If error is encountered, this function invokes the
427#            cleanupAndExit routine which terminates execution.
428#
429#######################################################################
430function getVSDdataSDR
431{
432  typeset sourceFile="mmcommon.sh"
433  [[ -n $DEBUG || -n $DEBUGgetVSDdataSDR ]] && set -x
434  $mmTRACE_ENTER "$*"
435  typeset joinedFile=$1
436
437  # Get the name, size, and global group name of all VSDs.
438  $SDRGetObjects -d ':' -x  VSD_Table  \
439     global_group_name VSD_name size_in_MB >$vsdNamesFile
440  checkForErrors SDRGetObjects $?
441
442  # Sort the output.
443  $sort -t: -k 1,1 $vsdNamesFile -o $vsdNamesFile
444  checkForErrors sort $?
445
446  # Get the primary and secondary nodes for the global group names.
447  $SDRGetObjects -d ':' -x  VSD_Global_Volume_Group global_group_name  \
448    primary_node secondary_node recovery local_group_name >$volGroupFile
449  checkForErrors SDRGetObjects $?
450
451  # Sort the output.
452  $sort -t: -k 1,1 $volGroupFile -o $volGroupFile
453  checkForErrors sort $?
454
455  # Create one common file with all of the information.
456  $join -t: $vsdNamesFile $volGroupFile >$joinedFile
457  checkForErrors join $?
458
459  $rm -f $vsdNamesFile $volGroupFile
460  return 0
461
462}  #----- end of function getVSDdataSDR --------------------------
463
464
465##########################################################################
466#
467# Function:  Generate a file with the global group names and size of
468#            all known VSDs, as well as their primary and secondary
469#            servers and recovery state.
470#
471# Input:     $1 - name of file for the VSD information
472#
473# Output:    Each record of the output file consists of the following
474#            colon-separated fields:
475#
476#   group_name:vsd_name:size:primary_node:secondary_node:recovery:vgname
477#
478# Returns:   0 - file created successfully
479#            If error is encountered, this function invokes the
480#            cleanupAndExit routine which terminates execution.
481#
482##########################################################################
483function getVSDdataRPD
484{
485  typeset sourceFile="mmcommon.sh"
486  [[ -n $DEBUG || -n $DEBUGgetVSDdataRPD ]] && set -x
487  $mmTRACE_ENTER "$*"
488  typeset joinedFile=$1
489
490  # Get the name, size, and global group name of all VSDs.
491  $lsrsrcapi -o "IBM.vsdtable::::::VSD_name::global_group_name::logical_volume_name::size_in_MB" >$vsdNamesFile
492  checkForErrors "getVSDdataRPD: lsrsrc-api -o IBM.vsdtable::::::VSD_name::global_group_name::logical_volume_name::size_in_MB" $?
493
494  # Sort the output
495  $sort -t: -k 3,3 $vsdNamesFile -o $vsdNamesFile
496  checkForErrors sort $?
497
498  # Get the primary and secondary nodes for the global group names.
499  $lsrsrcapi -o "IBM.vsdgvg::::::global_group_name::local_group_name::primary_node::secondary_node::recovery" >$volGroupFile
500  checkForErrors "getVSDdataRPD: lsrsrc-api -o IBM.vsdgvg::::::global_group_name::local_group_name::primary_node::secondary_node::recovery" $?
501
502  # Sort the output.
503  $sort -t: -k 1,1 $volGroupFile -o $volGroupFile
504  checkForErrors sort $?
505
506  # Create one common file with all of the information.
507  $join -t: -1 3 -2 1 -o 1.3,1.1,1.7,2.5,2.7,2.9,2.3 $vsdNamesFile $volGroupFile >$joinedFile
508  checkForErrors join $?
509
510  $rm -f $vsdNamesFile $volGroupFile
511  return 0
512
513}  #----- end of function getVSDdataRPD ---------------------------
514
515
516#########################################################################
517#
518# Function:  Generate a file with the node number and node name for
519#            all known VSD nodes.
520#
521# Input:     $1 - name of the file for storing the VSD node information
522#
523# Output:    Each record of the output file consists of the following
524#            colon-separated fields:
525#
526#              node_number:node_name
527#
528# Returns:   0 - file created successfully
529#            If an error is encountered, this function invokes the
530#            cleanupAndExit routine which terminates execution.
531#
532#########################################################################
533function getVsdNodeDataSDR
534{
535  typeset sourceFile="mmcommon.sh"
536  [[ -n $DEBUG || -n $DEBUGgetVsdNodeDataSDR ]] && set -x
537  $mmTRACE_ENTER "$*"
538  typeset outputFile=$1
539
540  # Get the number and name of each of the VSD nodes.
541  $SDRGetObjects -d ':' -x Node node_number reliable_hostname >$outputFile
542  checkForErrors "getVsdNodeDataSDR: SDRGetObjects" $?
543
544  # Sort the output.
545  $sort -t: -k 1,1 $outputFile -o $outputFile
546  checkForErrors sort $?
547
548  return 0
549
550}  #----- end of function getVsdNodeDataSDR ---------------------
551
552
553########################################################################
554#
555# Function:  Generate a file with the node number and node name for
556#            all known VSD nodes.
557#
558# Input:     $1 - name of the file for storing the VSD node information
559#
560# Output:    Each record of the output file consists of the following
561#            colon-separated fields:
562#
563#              node_number:node_name
564#
565# Returns:   0 - file created successfully
566#            If an error is encountered, this function invokes the
567#            cleanupAndExit routine which terminates execution.
568#
569########################################################################
570function getVsdNodeDataRPD
571{
572  typeset sourceFile="mmcommon.sh"
573  [[ -n $DEBUG || -n $DEBUGgetVsdNodeDataRPD ]] && set -x
574  $mmTRACE_ENTER "$*"
575  typeset outputFile=$1
576
577  # Get the number and name of each of the VSD nodes.
578  $lsrsrcapi -D ":" -o "IBM.vsdnode::::::VSD_nodenum::NodeNameList" |  \
579    $sed -e 's/{//g' | $sed -e 's/}//g' >$outputFile
580  checkForErrors "getVsdNodeDataRPD: lsrsrc-api -o IBM.vsdnode::::::VSD_nodenum::NodeNameList" $?
581
582  # Sort the output.
583  $sort -t: -k 1,1 $outputFile -o $outputFile
584  checkForErrors sort $?
585
586  return 0
587
588}  #----- end of function getVsdNodeDataRPD -----------------------
589
590
591###############################################################################
592#
593# Function:  Correlate GPFS node numbers with the corresponding RSCT
594#            node numbers (if any).
595#
596# Input:     None.
597#
598# Output:    For each node in the cluster that can access VSD disks,
599#            the following two fields (colon-separated, one pair per line)
600#            are displayed on stdout:
601#
602#              GPFSnodeNumber:RSCTnodeNumber
603#
604# Notes:     GPFS nodes that are not part of the RSCT peer domain are omitted.
605#
606# Returns:   0 - no errors encountered.
607#            If an error is encountered, this function invokes the
608#            cleanupAndExit routine which terminates execution.
609#
610###############################################################################
611function getVsdNodeNumbers  #
612{
613  typeset sourceFile="mmcommon.sh"
614  [[ -n $DEBUG || -n $DEBUGgetVsdNodeNumbers ]] && set -x
615  $mmTRACE_ENTER "$*"
616
617  typeset gpfsNumbers=$tmpfile
618  typeset vsdNumbers=$tmpfile2
619  typeset vsdPath
620
621  # This function makes no sense on Linux.
622  [[ $osName = Linux ]] && return 1
623
624  # Processing depends on which type of VSD code (PSSP or RSCT) is in use.
625  vsdPath=$(LC_ALL=C $ls -l $vsdatalst 2>/dev/null)
626  if [[ $vsdPath = *${vsdatalstPSSP}* && -x $vsdatalstPSSP ]]
627  then
628    # Find the PSSP node numbers and map them to the GPFS nodes.
629
630    # Get the PSSP node numbers and IP addresses.
631    $SDRGetObjects -d ':' -x Adapter node_number netaddr > $adfile
632    checkForErrors "getPSSPvsdNumbers: SDRGetObjects Adapter" $?
633
634    # Add multi-link adapters information from the Aggregate_IP class.
635    # If the class does not exist, ignore the error.
636    $SDRGetObjects -d ':' -x Aggregate_IP node_number ip_address >> $adfile 2>/dev/null
637    [[ ! -s $adfile ]] &&  \
638      checkForErrors "getVsdNodeNumbers: invalid SDR Adapter data; check SDR" 1
639
640    # Sort the output based on the IP address.
641    $sort -t: -k 2,2 $adfile -o $vsdNumbers
642    checkForErrors "getPSSPvsdNumbers: sort" $?
643
644  elif [[ $vsdPath = *${vsdatalstRSCT}* && -x $vsdatalstRSCT ]]
645  then
646    # Find the RSCT peer domain node numbers and map them to the GPFS nodes.
647
648    # Create a file correlating RSCT node identifiers with IP addresses.
649    $lsrsrcapi -o  \
650       "IBM.NetworkInterface::::::NodeIDs::IPAddress::" > $adfile 2> /dev/null
651    checkForErrors "getVsdNodeNumbers:  lsrsrc-api -o IBM.NetworkInterface::::::NodeIDs::IPAddress::" $?
652    [[ ! -s $adfile ]] &&  \
653      checkForErrors "getVsdNodeNumbers: invalid IBM.NetworkInterface data; check RSCT Peer Domain" 1
654
655    # Sort the output based on the NodeID values.
656    $sort -b -k 1,1 $adfile -o $adfile
657    checkForErrors "getVsdNodeNumbers: sort" $?
658
659    # Create a file correlating RSCT node identifiers with RSCT node numbers.
660    $lsrsrcapi -o "IBM.PeerNode::::::NodeIDs::NodeList" > $rnfile 2> /dev/null
661    checkForErrors "getVsdNodeNumbers:  lsrsrc-api -o IBM.PeerNode::::::NodeIDs::NodeList " $?
662    [[ ! -s $rnfile ]] &&  \
663      checkForErrors "getVsdNodeNumbers: invalid IBM.PeerNode output; check RSCT Peer Domain" 1
664
665    # Sort the output based on the NodeID values.
666    $sort -b -k 1,1 $rnfile -o $rnfile
667    checkForErrors "getVsdNodeNumbers: sort" $?
668
669    # Create one common file correlating IP addresses with RSCT node numbers.
670    $join -1 1 -2 1 -t : -o 2.3,1.3 $adfile $rnfile > $vsdNumbers
671    checkForErrors "getVsdNodeNumbers: join" $?
672
673    # Sort the output based on the IP address.
674    $sort -t: -k 2,2 $vsdNumbers -o $vsdNumbers
675    checkForErrors "getVsdNodeNumbers: sort" $?
676
677  else
678    # VSD not installed.
679    printErrorMsg 320 "getVSDdata"
680    cleanupAndExit
681  fi  # end of if [[ $? = 0 && -x $vsdatalstPSSP ]]
682
683  # Create a file correlating GPFS node numbers with IP addresses.
684  $awk -F: '                                               \
685    /':$MEMBER_NODE:'/ {                                   \
686        { print $'$NODE_NUMBER_Field' ":" $'$IPA_Field' }  \
687    }                                                      \
688  ' $mmsdrfsFile | $sort -t: -b -k 2,2 -o $gpfsNumbers
689  checkForErrors "getVsdNodeNumbers: awk_sort" $?
690
691  # Correlate the GPFS and RSCT node numbers, sort and display them on stdout.
692  $join -1 2 -2 2 -t : -o 1.1,2.1 $gpfsNumbers $vsdNumbers | $sort -t: -k 1,1n
693
694  return 0
695
696}  #----- end of function getVsdNodeNumbers -----------------------
697
698
699#############################################################################
700#
701# Function:  get NSD data for the caller
702#
703# Input:     $1 - file system name
704#            (if $GLOBAL_ID or not specified, return data for all NSDs)
705#
706# Output:    For each NSD satisfying the input criteria, a colon-delimited
707#            line of output of the following format is printed:
708#
709#   diskName:pvid:nsdSubtype:nsdSubtypeDiskname:primaryServer:backupServer
710#
711# Note:  Since this data is for the daemon, the server node names returned
712#        are the node adapter names used by the daemon, not the admin ones.
713#
714# Returns:   0
715#
716#############################################################################
717function getNsdData  # <fsname>
718{
719  typeset sourceFile="mmcommon.sh"
720  [[ -n $DEBUG || -n $DEBUGgetNsdData ]] && set -x
721  $mmTRACE_ENTER "$*"
722  typeset fsname=$1
723
724  typeset deviceName nsdSubtype server backup
725  typeset needToDetermineDaemonNames=no
726
727  # If a file system was passed, calculate the device name value.
728  [[ -n $fsname && $fsname != $GLOBAL_ID ]] &&  \
729    deviceName=${fsname##+(/)dev+(/)}
730
731  # Loop through the mmsdrfs file to obtain the NSD data for the caller.
732  $rm -f $tmpfile
733  IFS=":"
734  exec 3<&-
735  exec 3< $mmsdrfsFile
736  while read -u3 sdrfsLine
737  do
738    # Parse the line.
739    set -f ; set -A v -- - $sdrfsLine ; set +f
740    IFS="$IFS_sv"
741
742    case ${v[$LINE_TYPE_Field]} in
743
744      $SG_DISKS )  # This line describes a disk.
745        # Is this an NSD with a valid PVID value?
746        if [[ ${v[$DISK_TYPE_Field]} = nsd && -n ${v[$PVID_Field]} ]]
747        then
748          # Is this a disk in which we are interested?
749          if [[ -z $fsname || $fsname = $GLOBAL_ID  ||
750                $deviceName = ${v[$DEV_NAME_Field]} ]]
751          then
752            # Determine the nsd subtype value.
753            if [[ -z ${v[$NSD_SUBTYPE_Field]} ]]
754            then
755              nsdSubtype="generic"
756            else
757              nsdSubtype=${v[$NSD_SUBTYPE_Field]}
758            fi
759
760            # Check whether the daemon node name has been recorded for
761            # each NSD server.  If not, set a flag and exit the loop.
762            if [[ ( -n ${v[$NSD_PRIMARY_NODE_Field]} &&      \
763                    -z ${v[$DAEMON_NSD_PRIMARY_Field]} ) ||  \
764                  ( -n ${v[$NSD_BACKUP_NODE_Field]} &&       \
765                    -z ${v[$DAEMON_NSD_BACKUP_Field]} ) ]]
766            then
767              needToDetermineDaemonNames=yes
768              break
769            fi
770
771            # Output the data for this NSD.
772            print -- ${v[$DISK_NAME_Field]}:${v[$PVID_Field]}:$nsdSubtype:${v[$NSD_SUBTYPE_DISKNAME_Field]}:${v[$DAEMON_NSD_PRIMARY_Field]}:${v[$DAEMON_NSD_BACKUP_Field]} >> $tmpfile
773
774          fi  # end of if [[ -z $fsname || $fsname = $GLOBAL_ID  || ... ]]
775
776        fi  # end of if (v[$DISK_TYPE_Field] == "nsd" && -n v[$PVID_Field])
777        ;;
778
779      * )  # We are not interested in any other lines.
780        ;;
781
782    esac  # end of case ${v[$LINE_TYPE_Field]} in
783
784    IFS=":"  # Change the separator back to ":" for the next iteration.
785
786  done  # end of while read -u3 sdrfsLine do
787
788  IFS="$IFS_sv"  # Restore the default IFS setting.
789
790  # If all of the NSD servers had daemon names, we are done;
791  # output the data and return to the caller.
792  if [[ $needToDetermineDaemonNames = no ]]
793  then
794    [[ -s $tmpfile ]] && $cat $tmpfile
795    return 0
796  fi
797
798  # If we get here, at least one of the NSD servers did not have a
799  # daemon node name.  This is probably because the cluster migrated
800  # from an earlier level of GPFS in which they did not exist,
801  # and no one has issued mmchconfig release=LATEST to update the
802  # mmsdrfs file.  We can still get the NSD data, but it will require
803  # more time, since we must look at the MEMBER_NODE lines of the
804  # mmsdrfs file as well as the SG_DISKS lines.
805  # The mmsdrfs file will be updated with the daemon node names for
806  # the NSD servers when the user issues mmchconfig release=LATEST;
807  # it cannot be done in this code path.
808
809  # Go through the current mmsdrfs file to obtain the NSD data.
810  IFS=":"
811  exec 3<&-
812  exec 3< $mmsdrfsFile
813  while read -u3 sdrfsLine
814  do
815    # Parse the line.
816    set -f ; set -A v -- - $sdrfsLine ; set +f
817    IFS="$IFS_sv"
818
819    case ${v[$LINE_TYPE_Field]} in
820
821      $SG_DISKS )  # This line describes a disk.
822        # Is this an NSD with a valid PVID value?
823        if [[ ${v[$DISK_TYPE_Field]} = nsd && -n ${v[$PVID_Field]} ]]
824        then
825          # If a file system was passed, calculate the device name value.
826          [[ -n $fsname && $fsname != $GLOBAL_ID ]] &&  \
827            deviceName=${fsname##+(/)dev+(/)}
828
829          # Is this a disk in which we are interested?
830          if [[ -z $fsname || $fsname = $GLOBAL_ID  ||
831                $deviceName = ${v[$DEV_NAME_Field]} ]]
832          then
833            # Determine the nsd subtype value.
834            if [[ -z ${v[$NSD_SUBTYPE_Field]} ]]
835            then
836              nsdSubtype="generic"
837            else
838              nsdSubtype=${v[$NSD_SUBTYPE_Field]}
839            fi
840
841            # If a server node was specified, check that it is valid
842            # and convert it if necessary to a daemon adapter name.
843            server=${v[$NSD_PRIMARY_NODE_Field]}
844            if [[ -n $server ]]
845            then
846              server=$(checkAndConvertNodeValue $server $DAEMON_NODENAME_Field)
847            fi
848            backup=${v[$NSD_BACKUP_NODE_Field]}
849            if [[ -n $backup ]]
850            then
851              backup=$(checkAndConvertNodeValue $backup $DAEMON_NODENAME_Field)
852            fi
853
854            # Output the data for this NSD.
855            print -- ${v[$DISK_NAME_Field]}:${v[$PVID_Field]}:$nsdSubtype:${v[NSD_SUBTYPE_DISKNAME_Field]}:$server:$backup
856
857          fi  # end of if [[ -z $fsname || $fsname = $GLOBAL_ID  || ... ]]
858
859        fi  # end of if (v[$DISK_TYPE_Field] == "nsd" && -n v[$PVID_Field])
860        ;;
861
862      * )  # We are not interested in any other lines.
863        ;;
864
865    esac  # end of case ${v[$LINE_TYPE_Field]} in
866
867    IFS=":"  # Change the separator back to ":" for the next iteration.
868
869  done  # end of while read -u3 sdrfsLine
870
871  IFS="$IFS_sv"  # Restore the default IFS setting.
872
873  return 0
874
875}  #----- end of function getNsdData ----------------------------
876
877
878###########################################################################
879#
880# Function:  Determine whether a given cluster is authorized
881#            to access the specified file system.
882#
883# Input:     $1 - cluster name
884#            $2 - file system device name
885#
886# Output:    accessType [rootSquash=uid:gid]
887#
888# Returns:    0           - access level determined successfully
889#             2 (ENOENT)  - cluster not defined (not allowed to connect)
890#            13 (EACCES)  - access denied
891#            19 (ENODEV)  - device not found
892#            22 (EINVAL)  - device name is not valid
893#            93 (EREMOTE) - device name is for a remote fs
894#            other unexpected errors
895#
896###########################################################################
897function checkAuth  # <clusterName> <device> [norefresh]
898{
899  typeset sourceFile="mmcommon.sh"
900  [[ -n $DEBUG || -n $DEBUGcheckAuth ]] && set -x
901  $mmTRACE_ENTER "$*"
902  typeset clusterName=$1
903  typeset device=$2
904  typeset refreshArg=$3
905
906  typeset deviceName accessType allowRemoteConnections
907  typeset accessTypeString rsquashUid rsquashGid
908  typeset rsquashOption=""
909  typeset rc=0
910
911  [[ ! -f $mmsdrfsFile ]] &&  \
912    checkForErrors "checkAuth - Missing /var/mmfs/gen/mmsdrfs" 1
913
914  # Strip away any /dev/ prefix from the device id.
915  deviceName=${device##+(/)dev+(/)}
916
917  # Verify the device name.
918  if [[ $deviceName = /* ]]
919  then
920    printErrorMsg 169 $mmcmd "$device"
921    rc=$MM_InvalidName
922    return $rc
923  elif [[ $deviceName = */* ]]
924  then
925    printErrorMsg 170 $mmcmd "$device"
926    rc=$MM_InvalidName
927    return $rc
928  fi
929
930  # Ensure the GPFS system data is up to date.
931  if [[ $refreshArg != "norefresh" ]]
932  then
933    gpfsInitOutput=$(gpfsInit nolock)
934    setGlobalVar $? $gpfsInitOutput
935  fi
936
937  # If the cluster does not utilize secure connections,
938  # rw access is allowed to all of its file systems.
939  allowRemoteConnections=$(showCfgValue allowRemoteConnections)
940  if [[ $allowRemoteConnections = yes ]]
941  then
942    print -- "rw"
943    return 0
944  fi
945
946  # Find out the maximum allowed access for the file system.
947  accessTypeString=$($awk -F: '                               \
948    BEGIN {                                                   \
949      # Assume the file system does not exist.                \
950      { fsNotFound = 1 }                                      \
951      # Assume "mmauth add" was not issued for the cluster.   \
952      { remoteClusterNotFound = 1 }                           \
953      # Assume file system access not allowed (EACCES).       \
954      { rc = '$MM_AccessDenied' }                             \
955    }                                                         \
956                                                              \
957    $'$LINE_TYPE_Field' == "'$VERSION_LINE'" {                \
958      # If the request is for the local cluster,              \
959      # access is granted by default to all file systems.     \
960      if ( $'$CLUSTER_NAME_Field' == "'$clusterName'" ||      \
961           "'$clusterName'" == "." ) {                        \
962        { print "rw:::" }                                     \
963        { remoteClusterNotFound = 0 }                         \
964        { fsNotFound = 0 }                                    \
965        { rc = 0 }                                            \
966        { exit }                                              \
967      }                                                       \
968    }                                                         \
969                                                              \
970    $'$NODESETID_Field' == "'$clusterName'"       &&          \
971    $'$LINE_TYPE_Field' == "'$AUTHORIZED_CLUSTER'" {          \
972      # This is the overall authorization record for          \
973      # the desired cluster (created by "mmauth add").        \
974      { remoteClusterNotFound = 0 }                           \
975    }                                                         \
976                                                              \
977    $'$LINE_TYPE_Field' == "'$SG_HEADR'"  &&                  \
978    $'$DEV_NAME_Field'  == "'$deviceName'" {                  \
979      # This is the header line for the file system.          \
980      if ( $'$FS_TYPE_Field' == "'$remotefs'" ) {             \
981        # If it is a remote file system, return an error.     \
982        { rc = '$MM_Remotefs' }                               \
983        { exit }                                              \
984      } else {                                                \
985        # Otherwise, keep looking for an AUTHORIZED_FS line.  \
986        # Note that it is OK for such a record not to exist.  \
987        # All that means is that the given cluster cannot     \
988        # access the file system.                             \
989        { fsNotFound = 0 }                                    \
990      }                                                       \
991    }                                                         \
992                                                              \
993    $'$NODESETID_Field' == "'$clusterName'"   &&              \
994    $'$LINE_TYPE_Field' == "'$AUTHORIZED_FS'" &&              \
995    $'$DEV_NAME_Field'  == "'$deviceName'"     {              \
996      # This is the auth record for the desired cluster and   \
997      # file system.  Return the max allowed level of access. \
998      { print $'$ACCESS_TYPE_Field'    ":"                    \
999              $'$ROOTSQUASH_UID_Field' ":"                    \
1000              $'$ROOTSQUASH_GID_Field' ":"  }                 \
1001      { rc = 0 }                                              \
1002      { exit }                                                \
1003    }                                                         \
1004                                                              \
1005    END {                                                     \
1006      if ( fsNotFound ) {                                     \
1007        { rc = '$MM_FsNotFound' }                             \
1008      }                                                       \
1009      if ( remoteClusterNotFound ) {                          \
1010        { rc = '$MM_RemoteNotFound' }                         \
1011      }                                                       \
1012      { exit rc }                                             \
1013    }                                                         \
1014  ' $mmsdrfsFile)
1015  rc=$?
1016  if [[ $rc -ne 0 && $rc -ne $MM_AccessDenied ]]
1017  then
1018    if [[ $rc -eq $MM_FsNotFound ]]
1019    then
1020      # File system not found.
1021      printErrorMsg 288 $mmcmd "$device"
1022    elif [[ $rc -eq $MM_RemoteNotFound ]]
1023    then
1024      # The remote cluster is not authorized to access this cluster.
1025      printErrorMsg 259 $mmcmd $clusterName
1026    elif [[ $rc -eq $MM_Remotefs ]]
1027    then
1028      # Command is not allowed for remote file systems.
1029      printErrorMsg 238 $mmcmd
1030    else
1031      # Unexpected error.
1032      checkForErrors awk $rc
1033    fi
1034    return $rc
1035  fi
1036
1037  # Parse the result.
1038  IFS=":"
1039  set -f ; set -- $accessTypeString ; set +f
1040  accessType=$1
1041  rsquashUid=$2
1042  rsquashGid=$3
1043  IFS="$IFS_sv"
1044
1045  [[ -n $rsquashUid ]] && rsquashOption=" rootSquash=${rsquashUid}:${rsquashGid}"
1046  [[ -z $accessType ]] && accessType="none"
1047
1048  # Put out the result and return.
1049  print -- "${accessType}${rsquashOption}"
1050  return $rc
1051
1052}  #----- end of function checkAuth -----------------------------
1053
1054
1055######################################################################
1056#
1057# Function:  Generate a /etc/filesystems type options line.
1058#
1059# Input:     $1 - file system device name
1060#            $2 - skipMountPointCheck or doMountPointCheck
1061#
1062# Output:    The first line contains a comma-separated list of
1063#            mount options and the names of up to 50 disks.
1064#            The second line contains the mount point.
1065#
1066# Returns:   0 - options line generated successfully
1067#            19 (ENODEV) - options line not found
1068#            22 (EINVAL) - device name is not valid
1069#            1 - some other unexpected error
1070#
1071######################################################################
1072function getEFOptions  # <device> <checkMountPointOpt>
1073{
1074  typeset sourceFile="mmcommon.sh"
1075  [[ -n $DEBUG || -n $DEBUGgetEFOptions ]] && set -x
1076  $mmTRACE_ENTER "$*"
1077  typeset device=$1
1078  typeset checkMountPointOpt=$2
1079
1080  typeset rc=0
1081  typeset fsLine efOptions minorNumber nodesetId mountPoint fsType
1082  typeset fsType fsHomeCluster
1083
1084  [[ ! -f $mmsdrfsFile ]] &&  \
1085    checkForErrors "getEFOptions - Missing /var/mmfs/gen/mmsdrfs" 1
1086
1087  # Strip away any /dev/ prefix from the device id.
1088  deviceName=${device##+(/)dev+(/)}
1089
1090  # Verify the device name.
1091  if [[ $deviceName = /* ]]
1092  then
1093    printErrorMsg 169 $mmcmd "$device"
1094    rc=$MM_InvalidName
1095    return $rc
1096  elif [[ $deviceName = */* ]]
1097  then
1098    printErrorMsg 170 $mmcmd "$device"
1099    rc=$MM_InvalidName
1100    return $rc
1101  fi
1102
1103  # Make sure the mmsdrfs file is current.  To avoid undesired side effects,
1104  # tell gpfsInit to restrict mount point checking to only the file system
1105  # that is subject to the current getEFOptions call.  This is done only if
1106  # the checkMountPointOpt parameter is set to "doMountPointCheck" or "yes".
1107  [[ $checkMountPointOpt = "doMountPointCheck" || $checkMountPointOpt = "yes" ]] && \
1108    export MOUNT_POINT_CHECK="$deviceName"
1109  gpfsInit nolock >/dev/null
1110  checkForErrors gpfsInit $?
1111  unset MOUNT_POINT_CHECK
1112
1113  # The script looks for the SG_MOUNT line for the file system.
1114  # It examines the individual fields and if they have a value,
1115  # adds the value to the list.  The fields are comma-separated.
1116  # After the mount options are processed, the script looks for
1117  # SG_DISKS lines and puts out the names of the first 50 disks.
1118  # Disks that are excluded from SG descr operations are skipped.
1119  # At the end, if a SG_MOUNT line was found, the script returns 0.
1120  # Otherwise, the return code is set to 19 (ENODEV).
1121  fsLine=$($awk -F: '                                               \
1122    BEGIN {                                                         \
1123      { n = 0 }                                                     \
1124      { mountPoint = "" }                                           \
1125      { fsType     = "" }                                           \
1126      { exclOption = "" }                                           \
1127    }                                                               \
1128                                                                    \
1129    $'$LINE_TYPE_Field' == "'$SG_HEADR'"  &&                        \
1130    $'$DEV_NAME_Field'  == "'$deviceName'" {                        \
1131      { printf $'$NODESETID_Field' " " }                            \
1132      if ( $'$DEV_MINOR_Field' != "" ) {                            \
1133        { printf $'$DEV_MINOR_Field' " " }                          \
1134      }                                                             \
1135      else {                                                        \
1136        { printf "NULL " }                                          \
1137      }                                                             \
1138      if ( $'$FS_TYPE_Field' == "'$remotefs'" ) {                   \
1139        { fsType = "remotefs" }                                     \
1140        { remoteDevName = $'$REMOTE_DEV_NAME_Field' }               \
1141      }                                                             \
1142      else {                                                        \
1143        { fsType = "localfs" }                                      \
1144      }                                                             \
1145      { printf fsType " " }                                         \
1146    }                                                               \
1147                                                                    \
1148    $'$LINE_TYPE_Field'   == "'$SG_ETCFS'"        &&                \
1149    $'$DEV_NAME_Field'    == "'$deviceName'"      &&                \
1150    $'$LINE_NUMBER_Field' == "'$MOUNT_POINT_Line'" {                \
1151      { mountPoint = $'$ETCFS_TEXT_Field'":" }                      \
1152    }                                                               \
1153                                                                    \
1154    $'$LINE_TYPE_Field' == "'$SG_MOUNT'"  &&                        \
1155    $'$DEV_NAME_Field'  == "'$deviceName'" {                        \
1156      { printf $'$RW_OPT_Field' }                                   \
1157      if ( $'$MTIME_OPT_Field' != "" ) {                            \
1158        { printf ","$'$MTIME_OPT_Field' }                           \
1159      }                                                             \
1160      if ( $'$ATIME_OPT_Field' != "" ) {                            \
1161        { printf ","$'$ATIME_OPT_Field' }                           \
1162      }                                                             \
1163      if ( $'$OTHER_OPT_Field' != "" ) {                            \
1164        { printf ","$'$OTHER_OPT_Field' }                           \
1165      }                                                             \
1166      if ( $'$QUOTA_OPT_Field' != "" ) {                            \
1167        { printf ",quota="$'$QUOTA_OPT_Field' }                     \
1168      }                                                             \
1169      if ( fsType == "remotefs" ) {                                 \
1170        { printf ",dev="$'$NODESETID_Field'":"remoteDevName }       \
1171        { printf ",ldev='$deviceName'" }                            \
1172      }                                                             \
1173      { next }                                                      \
1174    }                                                               \
1175                                                                    \
1176    $'$LINE_TYPE_Field' == "'$SG_DISKS'"  &&                        \
1177    $'$DEV_NAME_Field'  == "'$deviceName'" {                        \
1178      if ( $'$EXCLUDE_Field' == "'$excludedDisk'") {                \
1179        { exclOption = ",exclDisks=yes" }                           \
1180      }                                                             \
1181      else if ( $'$DISK_STATUS_Field' == "" ||                      \
1182                $'$DISK_STATUS_Field' == "ready" ) {                \
1183        { diskType = $'$DISK_TYPE_Field' }                          \
1184        # Map certain disk types to the default GPFS driver type.   \
1185        if ( diskType == "lv" || diskType == "vsd" ) {              \
1186          { diskType = "" }                                         \
1187        }                                                           \
1188        if ( n == 0 ) {                                             \
1189          { printf ",disks="$'$DISK_NAME_Field'":"diskType }        \
1190          { n = n + 1 }                                             \
1191          { next }                                                  \
1192        }                                                           \
1193        else if ( n < 50 ) {                                        \
1194          { printf ";"$'$DISK_NAME_Field'":"diskType }              \
1195          { n = n + 1 }                                             \
1196          { next }                                                  \
1197        }                                                           \
1198        else {                                                      \
1199          { exit }                                                  \
1200        }                                                           \
1201      }                                                             \
1202    }                                                               \
1203                                                                    \
1204    END {                                                           \
1205      if ( fsType == "" ) {                                         \
1206        # Filesystem not found.  Return ENODEV.                     \
1207        { exit '$MM_FsNotFound' }                                   \
1208      }                                                             \
1209      else {                                                        \
1210        if ( exclOption != "" ) {                                   \
1211          { printf exclOption }                                     \
1212        }                                                           \
1213        # Filesystem found.  Add the mount point to the output.     \
1214        { printf " " mountPoint "\n" }                              \
1215        { exit  0 }                                                 \
1216      }                                                             \
1217    }                                                               \
1218  ' $mmsdrfsFile)
1219  rc=$?
1220  if [[ $rc -ne 0 || -z $fsLine ]]
1221  then
1222    [[ $rc -eq  0 ]] && rc=1
1223    if [[ $rc -eq $MM_FsNotFound ]]
1224    then
1225      # File system not found.
1226      printErrorMsg 288 $mmcmd "$device"
1227    else
1228      # Unexpected error.
1229      checkForErrors awk $rc
1230    fi
1231    return $rc
1232  fi
1233
1234  # Parse the result.
1235  set -f ; set -- $fsLine ; set +f
1236  fsHomeCluster=$1
1237  minorNumber=$2
1238  fsType=$3
1239  efOptions=$4
1240  mountPoint=$5
1241
1242  # Exit with a message if invoked for a remote file system.
1243  if [[ $fsType = remotefs ]]
1244  then
1245    # Command is not allowed for remote file systems.
1246    printErrorMsg 106 $mmcmd "$device" $fsHomeCluster
1247    return $MM_Remotefs
1248  fi
1249
1250  # Make sure the /dev entry looks good.  Do this only if the
1251  # checkMountPointOpt parameter is set to "doMountPointCheck".
1252  if [[ $checkMountPointOpt = "doMountPointCheck" || $checkMountPointOpt = "yes" ]]
1253  then
1254    [[ $osName = Linux ]] && checkVfsNumber
1255    confirmMajorMinor mount /dev/$deviceName $neededMajorNumber $minorNumber
1256    rc=$?
1257    if [[ $rc -ne 0 ]]
1258    then
1259      # /dev entry not created by GPFS.
1260      printErrorMsg 462 "$mmcmd" "/dev/$deviceName"
1261      # Pretend everything is OK and let the daemon
1262      # decide whether it can mount the file system.
1263      rc=0
1264    fi
1265  fi  # end of if [[ $checkMountPointOpt = "doMountPointCheck" ]]
1266
1267  # Ensure the output does not overrun the daemon input buffers.
1268  # If necessary, take out one or more disks from the efOptions string.
1269  while [[ ${#efOptions} -gt 1023 ]]
1270  do
1271    efOptions="${efOptions%;*}"
1272  done
1273
1274  # Put out the result and return.
1275  print -- "$efOptions"
1276  print -- "$mountPoint"
1277  return $rc
1278
1279}  #----- end of function getEFOptions --------------------------
1280
1281
1282#####################################################################
1283#
1284# Function:  Retrieve the mount point for a file system.
1285#
1286# Input:     $1 - file system device name
1287#
1288# Output:    The mount point for the file system.
1289#
1290# Returns:   0 - mount point generated successfully
1291#            19 (ENODEV) - file system not found
1292#            22 (EINVAL) - device name is not valid
1293#            1 - some other unexpected error
1294#
1295#####################################################################
1296function getMountPoint  # <device>
1297{
1298  typeset sourceFile="mmcommon.sh"
1299  [[ -n $DEBUG || -n $DEBUGgetMountPoint ]] && set -x
1300  $mmTRACE_ENTER "$*"
1301  typeset device=$1
1302  # typeset checkMountPointOpt=$2
1303
1304  typeset rc=0
1305  typeset mountPoint deviceName
1306
1307  [[ ! -f $mmsdrfsFile ]] &&  \
1308    checkForErrors "getMountPoint - Missing /var/mmfs/gen/mmsdrfs" 1
1309
1310  # Strip away any /dev/ prefix from the device id.
1311  deviceName=${device##+(/)dev+(/)}
1312
1313  # Verify the device name.
1314  if [[ $deviceName = /* ]]
1315  then
1316    printErrorMsg 169 $mmcmd "$device"
1317    rc=$MM_InvalidName
1318    return $rc
1319  elif [[ $deviceName = */* ]]
1320  then
1321    printErrorMsg 170 $mmcmd "$device"
1322    rc=$MM_InvalidName
1323    return $rc
1324  fi
1325
1326  # Note:  We will assume that at the point this function is invoked,
1327  #        the /etc/filesystems information in general, and the mount
1328  #        point in particular, are up-to date. Therefore, we will skip
1329  #        the call to gpfsInit.  If this assumption turns out to be
1330  #        inaccurate, the sections of code that deal with gpfsInit
1331  #        and confirmMajorMinor will have to activated.
1332
1333  # Make sure the mmsdrfs file is current.  To avoid undesired side effects,
1334  # tell gpfsInit to restrict mount point checking to only the file system
1335  # that is subject to the current getMountPoint call.  This is done only if
1336  # the checkMountPointOpt parameter is set to "doMountPointCheck" or "yes".
1337  # [[ $checkMountPointOpt = "doMountPointCheck" || $checkMountPointOpt = "yes" ]] && \
1338  #   export MOUNT_POINT_CHECK="$deviceName"
1339  # gpfsInit nolock >/dev/null
1340  # checkForErrors gpfsInit $?
1341  # unset MOUNT_POINT_CHECK
1342
1343  # The script looks for the first SG_ETCFS line for the
1344  # file system and prints the value of the mount point.
1345  # If the line was found, the script returns 0.
1346  # Otherwise, the return code is set to 19 (ENODEV).
1347  mountPoint=$($awk -F: '                             \
1348    $'$LINE_TYPE_Field'   == "'$SG_ETCFS'"        &&  \
1349    $'$DEV_NAME_Field'    == "'$deviceName'"      &&  \
1350    $'$LINE_NUMBER_Field' == "'$MOUNT_POINT_Line'" {  \
1351      { mountPoint = $'$ETCFS_TEXT_Field'":" }        \
1352      { exit }                                        \
1353    }                                                 \
1354    END {                                             \
1355      if ( mountPoint == "" ) {                       \
1356        # Filesystem not found.  Return ENODEV.       \
1357        { exit '$MM_FsNotFound' }                     \
1358      }                                               \
1359      else {                                          \
1360        # Filesystem found.  Return the mount point.  \
1361        { print mountPoint }                          \
1362        { exit  0 }                                   \
1363      }                                               \
1364    }                                                 \
1365  ' $mmsdrfsFile)
1366  rc=$?
1367  if [[ $rc -ne 0 || -z $mountPoint ]]
1368  then
1369    [[ $rc -eq  0 ]] && rc=1
1370    if [[ $rc -eq $MM_FsNotFound ]]
1371    then
1372      # File system not found.
1373      printErrorMsg 288 $mmcmd "$device"
1374    else
1375      # Unexpected error.
1376      checkForErrors awk $rc
1377    fi
1378    return $rc
1379  fi
1380
1381  # Make sure the /dev entry looks good.  Do this only if the
1382  # checkMountPointOpt parameter is set to "doMountPointCheck".
1383  # if [[ $checkMountPointOpt = "doMountPointCheck" || $checkMountPointOpt = "yes" ]]
1384  # then
1385  #   [[ $osName = Linux ]] && checkVfsNumber
1386  #   confirmMajorMinor mount /dev/$deviceName $neededMajorNumber $minorNumber
1387  #   rc=$?
1388  #   if [[ $rc -ne 0 ]]
1389  #   then
1390  #     # /dev entry not created by GPFS.
1391  #     printErrorMsg 462 "$mmcmd" "/dev/$deviceName"
1392  #     # Pretend everything is OK and let the daemon
1393  #     # decide whether it can mount the file system.
1394  #     rc=0
1395  #   fi
1396  # fi  # end of if [[ $checkMountPointOpt = "doMountPointCheck" ]]
1397
1398  # Put out the result and return.
1399  print -- "$mountPoint"
1400  return $rc
1401
1402}  #----- end of function getMountPoint -------------------------
1403
1404
1405#####################################################################
1406#
1407# Function:  This function is called by the mmfsd daemon during
1408#            initialization, before it runs recovery for any VFS
1409#            mount points that may already be mounted.  The only
1410#            thing that this function presently does is to invoke
1411#            the /var/mmfs/etc/gpfsready user exit.
1412#
1413# Note:      The daemon will wait until this script returns.
1414#            Do not invoke long running commands synchronously
1415#            from this function.  Specifically, do not start
1416#            mount commands here and do not do anything that
1417#            assumes a mounted GPFS file system.
1418#
1419# Input:     None
1420#
1421# Output:    None
1422#
1423# Returns:   0 - no errors encountered
1424#            1 - unexpected error
1425#
1426#####################################################################
1427function gpfsready   #
1428{
1429  typeset sourceFile="mmcommon.sh"
1430  [[ -n $DEBUG || -n $DEBUGgpfsready ]] && set -x
1431  $mmTRACE_ENTER "$*"
1432
1433  print "$(date): mmcommon gpfsready invoked"
1434
1435  #####################################################
1436  # Invoke the user exit, if it is properly installed.
1437  #####################################################
1438  if [[ -x ${mmfscfgDir}gpfsready ]]
1439  then
1440    print "$(date): ${mmfscfgDir}gpfsready invoked"
1441    ${mmfscfgDir}gpfsready
1442  fi
1443
1444  return 0
1445
1446}  #----- end of function gpfsready -------------------------
1447
1448
1449#####################################################################
1450#
1451# Function:  This function is called by the mmfsd daemon when it is
1452#            up and ready for sessions.  It mounts all file systems
1453#            that have to be mounted at daemon startup time and then
1454#            invokes the /var/mmfs/etc/mmfsup user exit.
1455#
1456# Input:     $1 - IP address of this node
1457#            $2 - IP address of the config manager node
1458#
1459# Output:    None
1460#
1461# Returns:   0 - no errors encountered
1462#            1 - unexpected error
1463#
1464#####################################################################
1465function mmfsup   # <localIPaddr> <ccMgrIPaddr>
1466{
1467  typeset sourceFile="mmcommon.sh"
1468  [[ -n $DEBUG || -n $DEBUGmmfsup ]] && set -x
1469  $mmTRACE_ENTER "$*"
1470  typeset localIPaddr=$1
1471  typeset ccMgrIPaddr=$2
1472
1473  typeset mountedFileSystems device mountOptions
1474
1475  print "$(date): mmcommon mmfsup invoked"
1476
1477  ##############################################################
1478  # Mount all GPFS file systems for which -A yes was specified.
1479  # If there are such file systems, their device names are put
1480  # in file /var/mmfs/gen/automount.  The device names in this
1481  # file are ordered to avoid simultaneous mounting of the same
1482  # file system from all nodes in the cluster.
1483  ##############################################################
1484  if [[ -s $startupMountFile && ! -f $ignoreStartupMount ]]
1485  then
1486    # Create a list of the currently mounted file systems on this node.
1487    if [[ $osName = AIX ]]
1488    then
1489      $mount >$tmpfile 2>/dev/null
1490      mountedFileSystems=$tmpfile
1491    elif [[ $osName = Linux ]]
1492    then
1493      mountedFileSystems=/proc/mounts
1494    else
1495      # Should never get here.
1496      printErrorMsg 171 "$mmcmd" "mmfsup: unsupported OS $osName" 1
1497      return 1
1498    fi  # end of if [[ $osName = AIX ]]
1499
1500    # Process the list of file systems.
1501    exec 3< $startupMountFile
1502    while read -u3 device
1503    do
1504      # If file ignoreStartupMount exists for this file system,
1505      # do not attempt to mount it.
1506      [[ -s ${ignoreStartupMount}.${device#/dev/} ]] &&  \
1507        continue
1508
1509      # See if there are local override mount options for this file system.
1510      if [[ -s ${localMountOptions}.${device#/dev/} ]]
1511      then
1512        mountOptions="-o $($tail -n -1 ${localMountOptions}.${device#/dev/} 2>/dev/null)"
1513      else
1514        mountOptions=""
1515      fi
1516
1517      # See if this file system is already mounted.
1518      $grep -qw $device $tmpfile > /dev/null 2>&1
1519      if [[ $? -ne 0 ]]
1520      then
1521        # The file system is not mounted.  Do it now.
1522        print -- "$(date): mounting $device"
1523        $mount $mountOptions $device 2>&1 | $grep -i -v "already mounted"
1524        print -- "$(date): finished mounting $device"
1525      fi
1526    done
1527  fi  # end of if [[ -s $startupMountFile ]]
1528
1529  #####################################################
1530  # Invoke the user exit, if it is properly installed.
1531  #####################################################
1532  if [[ -x ${mmfscfgDir}mmfsup ]]
1533  then
1534    print "$(date): ${mmfscfgDir}mmfsup invoked"
1535    ${mmfscfgDir}mmfsup $localIPaddr $ccMgrIPaddr
1536  elif [[ -x ${mmfscfgDir}mmfsup.scr ]]
1537  then
1538    print "$(date): ${mmfscfgDir}mmfsup.scr invoked"
1539    ${mmfscfgDir}mmfsup.scr $localIPaddr $ccMgrIPaddr
1540  fi
1541
1542  return 0
1543
1544}  #----- end of function mmfsup -------------------------
1545
1546
1547#####################################################################
1548#
1549# Function:  This function is called by the mmfsd daemon during
1550#            normal and abnormal sutdown processing. A number of
1551#            cleanup tasks are performed and then the function
1552#            invokes the /var/mmfs/etc/mmfsdown user exit.
1553#
1554# Input:     None
1555#
1556# Output:    None
1557#
1558# Returns:   0 - no errors encountered
1559#            1 - unexpected error
1560#
1561#####################################################################
1562function mmfsdown   #
1563{
1564  typeset sourceFile="mmcommon.sh"
1565  [[ -n $DEBUG || -n $DEBUGmmfsdown ]] && set -x
1566  $mmTRACE_ENTER "$*"
1567
1568  typeset pid status
1569
1570  ############################################
1571  # Determine whether GPFS will be restarted.
1572  ############################################
1573  pid=$($ps -eo "pid args" | $awk '/\/runmmfs/ && !/this process/ {print $1}')
1574  if [[ -n $pid && -f $rerunmmfsFile ]]
1575  then
1576    status=active
1577  else
1578    status=down
1579  fi
1580
1581  print "$(date): mmcommon mmfsdown invoked.  Subsystem: mmfs  Status: $status"
1582  ########################
1583  # Do the cleanup tasks.
1584  ########################
1585  if [[ $status = active ]]
1586  then
1587    #---------------------------------------------
1588    # The GPFS daemon died but will be restarted.
1589    #---------------------------------------------
1590    if [[ -n "$MMTRACE" ]]
1591    then
1592      # If the MMTRACE environment variable is set,
1593      # stop tracing on this node.
1594      $mmtrace stop
1595
1596      if [[ $MMTRACE = global ]]
1597      then
1598        # If tracing was started on all nodes, cut trace
1599        # records on all of the nodes in the cluster.
1600        getNodeList $REL_HOSTNAME_Field $GLOBAL_ID $mmsdrfsFile > $nodefile
1601        $mmcommon onall $nodefile $unreachedNodes adminCmd mmtrace
1602      fi
1603    fi  # end of if [[ -n "$MMTRACE" ]]
1604
1605  else
1606    #-----------------------------------
1607    # The GPFS daemon is shutting down.
1608    #-----------------------------------
1609    if [[ -n "$MMTRACE" ]]
1610    then
1611      # If the MMTRACE environment variable is set,
1612      # stop tracing on this node.
1613      $mmtrace stop
1614    fi
1615
1616    # Force unmount of all gpfs file systems.
1617    printInfoMsg 426 "$(date)" $mmcmd
1618    if [[ $osName = AIX ]]
1619    then
1620      unmountFileSystems all -f 2>/dev/null
1621    elif [[ $osName = Linux ]]
1622    then
1623      # Note: Do not redirect stderr on Linux umount.
1624      unmountFileSystems all -f
1625    else
1626      # Should never get here.
1627      printErrorMsg 171 "$mmcmd" "mmfsdown: unsupported OS $osName" 1
1628      return 1
1629    fi
1630
1631    # Remove the respawn file since the daemon will not be restarted.
1632    $rm -f $respawnlog
1633
1634  fi  # end of if [[ $status = active ]]
1635
1636  #####################################################
1637  # Invoke the user exit, if it is properly installed.
1638  #####################################################
1639  if [[ -x ${mmfscfgDir}mmfsdown ]]
1640  then
1641    print "$(date): ${mmfscfgDir}mmfsdown invoked"
1642    ${mmfscfgDir}mmfsdown $status
1643  elif [[ -x ${mmfscfgDir}mmfsdown.scr ]]
1644  then
1645    print "$(date): ${mmfscfgDir}mmfsdown.scr invoked"
1646    ${mmfscfgDir}mmfsdown.scr $status
1647  fi
1648
1649  return 0
1650
1651}  #----- end of function mmfsdown -------------------------
1652
1653
1654#####################################################################
1655#
1656# Function:  This function is called prior to unmounting a file system
1657#            in response to an explicit mmumount or mmshutdown command.
1658#            The function is also invoked by the mmfsd daemon during
1659#            normal and abnormal shutdown processing.
1660#
1661# Input:     $1 - file system device name or all
1662#            $2 - reason: umount or cleanup
1663#
1664# Output:    None
1665#
1666# Returns:   0 - no errors encountered
1667#            1 - unexpected error
1668#
1669#####################################################################
1670function preunmount   # <device> <reason>
1671{
1672  typeset sourceFile="mmcommon.sh"
1673  [[ -n $DEBUG || -n $DEBUGpreunmount ]] && set -x
1674  $mmTRACE_ENTER "$*"
1675  typeset device=$1
1676  typeset reason=$2
1677
1678  typeset timeout=5
1679  typeset waited=0
1680  typeset retrydelay=1
1681  typeset pid
1682
1683
1684  ###################################################################
1685  # If the reason for the call is daemon cleanup, determine if this
1686  # is a normal or abnormal shutdown.  If normal shutdown, the exit
1687  # must have already been invoked by mmremote shutdownDaemon.
1688  ###################################################################
1689  if [[ -x ${mmfscfgDir}preunmount ]]
1690  then
1691    print "$(date): mmcommon preunmount invoked.  File system: $device  Reason: $reason"
1692  fi
1693  if [[ $reason = cleanup ]]
1694  then
1695    # Determine whether GPFS will be restarted.
1696    pid=$($ps -eo "pid args" | $awk '/\/runmmfs/ && !/this process/ {print $1}')
1697    if [[ -n $pid && -f $rerunmmfsFile ]]
1698    then
1699      # This is abnormal shutdown; the daemon will be restarted.
1700      :  # keep going with the rest of the code.
1701    else
1702      # This is normal shutdown; the daemon will not be restarted.
1703      # This function must have already been invoked by mmremote shutdownDaemon.
1704      return 0
1705    fi
1706  fi  # end of if [[ $reason = cleanup ]]
1707
1708  #############################################################
1709  # Invoke the user exit, if it is properly installed.
1710  # Allow no more than 5 seconds for the user code to finish.
1711  # If the user process does not return within this time,
1712  # the function will return.  This is intended to prevent
1713  # GPFS recovery from hanging.
1714  #############################################################
1715  if [[ -x ${mmfscfgDir}preunmount ]]
1716  then
1717    print "$(date): ${mmfscfgDir}preunmount invoked"
1718    ${mmfscfgDir}preunmount $device $reason &
1719    pid=$!
1720
1721    # Wait until the user exit finishes or the timeout expires.
1722    while [[ $waited -lt $timeout ]]
1723    do
1724      $sleep $retrydelay
1725      (( waited = waited + retrydelay ))
1726
1727      if ! kill -0 $pid 2>/dev/null
1728      then
1729        # The user process finished.
1730        waited=-1
1731        break
1732      fi
1733    done  # while [[ $waited -lt $timeout ]]
1734
1735    # Inform the user if the exit did not finish in the alloted time.
1736    if [[ $waited -gt 0 ]]
1737    then
1738      print "$(date): ${mmfscfgDir}preunmount not finished after $waited seconds."
1739      print "    The process is left to run in the background."
1740    fi
1741  fi  # end of if [[ -x ${mmfscfgDir}preunmount ]]
1742
1743  return 0
1744
1745}  #------------ end of function preunmount -------------------------
1746
1747
1748#####################################################################
1749#
1750# Function:  This function is called by the mmfsd daemon during
1751#            node failure recovery before any distributed locks
1752#            held by failed nodes are released.  This script is
1753#            invoked once for each file system on all nodes on
1754#            which the file system is mounted or otherwise in use.
1755#            The only thing that this function presently does is
1756#            to invoke the /var/mmfs/etc/gpfsrecover user exit.
1757#
1758# Note:      The daemon will wait until this script returns.
1759#            Do not invoke long running commands synchronously
1760#            from this function.  Specifically, do not start
1761#            mount commands here and do not attempt to access
1762#            any GPFS files or directories.
1763#
1764# Input:     $1 - file system name
1765#            $2 - recovery phase (always 0)
1766#            $3, $4, ... - node numbers of the failed nodes.
1767#
1768# Output:    None
1769#
1770# Returns:   0 - no errors encountered
1771#            1 - unexpected error
1772#
1773#####################################################################
1774function gpfsrecover   #
1775{
1776  typeset sourceFile="mmcommon.sh"
1777  [[ -n $DEBUG || -n $DEBUGgpfsrecover ]] && set -x
1778  $mmTRACE_ENTER "$*"
1779  typeset fsname=$1
1780  typeset phase=$2
1781  shift 2
1782  typeset failedNodes=$*
1783
1784  print "$(date): mmcommon gpfsrecover invoked:"
1785  print "    fsname=$fsname  phase=$phase  failed nodes=\"$failedNodes\""
1786
1787  #####################################################
1788  # Invoke the user exit, if it is properly installed.
1789  #####################################################
1790  if [[ -x ${mmfscfgDir}gpfsrecover ]]
1791  then
1792    print "$(date): ${mmfscfgDir}gpfsrecover invoked"
1793    ${mmfscfgDir}gpfsrecover $fsname $phase $failedNodes
1794  elif [[ -x ${mmfscfgDir}gpfsrecover.scr ]]
1795  then
1796    print "$(date): ${mmfscfgDir}gpfsrecover.scr invoked"
1797    ${mmfscfgDir}gpfsrecover.scr $fsname $phase $failedNodes
1798  fi
1799
1800  return 0
1801
1802}  #----- end of function gpfsrecover -------------------------
1803
1804
1805#####################################################################
1806#
1807# Function:  Reconcile the mmsdrfs file with the GPFS daemon's data
1808#            for the passed filesystem.
1809#
1810# Input:     fsname
1811#
1812# Output:    The mmsdrfs file is brought into sync with the
1813#            GPFS daemon's view of the passed filesystem.
1814#
1815# Returns:   0 - no errors encountered
1816#            1 - unexpected error
1817#
1818#####################################################################
1819function recoverfs   # <fsname>
1820{
1821  typeset sourceFile="mmcommon.sh"
1822  [[ -n $DEBUG || -n $DEBUGrecoverfs ]] && set -x
1823  $mmTRACE_ENTER "$*"
1824
1825  typeset fsname=$1
1826  typeset nodeCount versionLine rc oddState
1827  typeset findFSoutput fqDeviceName deviceName fsHomeCluster
1828  integer newGenNumber
1829
1830  # Set up trap exception handling and call the gpfsInit function.
1831  # It will ensure that the local copy of the mmsdrfs and the rest of the
1832  # GPFS system files are up-to-date and it will also obtain the sdr lock.
1833  trap pretrap HUP INT QUIT KILL
1834  gpfsInitOutput=$(gpfsInit $lockId)
1835  setGlobalVar $? $gpfsInitOutput
1836
1837  findFSoutput=$(findFS "$fsname" $mmsdrfsFile)
1838  [[ -z $findFSoutput ]] && cleanupAndExit
1839
1840  # Parse the output from the findFS function.
1841  set -f ; set -- $findFSoutput ; set +f
1842  fqDeviceName=$1
1843  deviceName=$2
1844  fsHomeCluster=$3
1845
1846  # Exit with a message if the command was invoked for a remote file system.
1847  if [[ $fsHomeCluster != $HOME_CLUSTER ]]
1848  then
1849    # Command is not allowed for remote file systems.
1850    printErrorMsg 106 $mmcmd $fsname $fsHomeCluster
1851    cleanupAndExit
1852  fi
1853
1854  # Create a file with the reliable names of the nodes that belong to
1855  # the nodeset to which the specified file system belongs.
1856  $rm -f $nodefile
1857  nodeCount=$(getNodeFile $REL_HOSTNAME_Field $fsHomeCluster $mmsdrfsFile $nodefile)
1858  if [[ $nodeCount -eq 0 ]]
1859  then
1860    # The nodeset is empty; there is nobody to run the command.
1861    printErrorMsg 171 $mmcmd "getNodeFile (nodeCount=0)" 1
1862    cleanupAndExit
1863  fi
1864
1865  # Copy the sdrfs file to a temporary file.
1866  $cp $mmsdrfsFile $tmpsdrfs
1867
1868  # Reconcile the sdrfs file with the GPFS daemon's view of the filesystem.
1869  oddState=$(reconcileSdrfsWithDaemon $deviceName $tmpsdrfs)
1870  rc=$?
1871  if [[ $rc -ne 0 ]]
1872  then
1873    # reconcileSdrfsWithDaemon failed.
1874    printErrorMsg 171 $mmcmd reconcileSdrfsWithDaemon $rc
1875    cleanupAndExit
1876  fi
1877
1878  # Obtain the generation number from the version line of the new sdrfs file.
1879  versionLine=$($head -1 $tmpsdrfs)
1880  IFS=':'
1881  set -f ; set -- $versionLine ; set +f
1882  newGenNumber=$6
1883  IFS="$IFS_sv"
1884
1885  # Commit the new mmsdrfs file.
1886  trap "" HUP INT QUIT KILL    # Disable interrupts until the commit is done.
1887  gpfsObjectInfo=$(commitChanges  \
1888    $GLOBAL_ID $fsHomeCluster $gpfsObjectInfo $newGenNumber $tmpsdrfs $primaryServer)
1889  rc=$?
1890  if [[ $rc -ne 0 ]]
1891  then
1892    # The commit step failed.
1893    printErrorMsg 381 $mmcmd
1894    # Tell the user what to do.
1895    printErrorMsg 190 $mmcmd $fsname $fsname
1896    cleanupAndExit
1897  fi
1898
1899  # Unlock the sdr.
1900  [[ $sdrLocked = yes ]] &&  \
1901    freeLockOnServer $primaryServer $ourNodeNumber > /dev/null
1902  sdrLocked=no
1903  trap posttrap HUP INT QUIT KILL   # Enable interrupts again.
1904
1905  # Propagate the changes to all affected nodes.
1906  propagateSdrfsFile async $nodefile $mmsdrfsFile $newGenNumber
1907
1908  # If installed, invoke the syncfsconfig user exit.
1909  if [[ -x $syncfsconfig ]]
1910  then
1911     print -- "$mmcmd:  Starting $syncfsconfig ..."
1912     $syncfsconfig
1913     print -- "$mmcmd$syncfsconfig finished."
1914  fi
1915
1916  cleanupAndExit 0
1917
1918}  #----- end of function recoverfs ------------------------------
1919
1920
1921#####################################################################
1922#
1923# Function:  Reset the starting integer for NSD names generation.
1924#            This is a service-only command.
1925#
1926# Input:     $1 - nsdBaseNumber
1927#
1928# Output:    None
1929#
1930# Returns:   0 - no errors encountered
1931#            1 - unexpected error
1932#
1933#####################################################################
1934function resetNsdNumber    #  <nsdBaseNumber>
1935{
1936  typeset sourceFile="mmcommon.sh"
1937  [[ -n $DEBUG || -n $DEBUGresetNsdNumber ]] && set -x
1938  $mmTRACE_ENTER "$*"
1939  typeset nsdBaseNumber=$1
1940
1941  typeset gpfsInitOutput sdrfsLine newGenNumber
1942  typeset rc
1943
1944  #######################################################################
1945  # Set up trap exception handling and call the gpfsInit function.
1946  # It will ensure that the local copy of the mmsdrfs and the rest of
1947  # the GPFS system files are up-to-date and will obtain the sdr lock.
1948  #######################################################################
1949  trap pretrap HUP INT QUIT KILL
1950  gpfsInitOutput=$(gpfsInit $lockId)
1951  setGlobalVar $? $gpfsInitOutput
1952
1953  ########################################################################
1954  # Go through the current mmsdrfs file.  Increment the generation
1955  # number and build the node name lists that will be needed later.
1956  # Set HIGHEST_GPFS_DISK_NBR_Field to the specified value.
1957  ########################################################################
1958  $rm -f $newsdrfs $nodefile
1959  IFS=":"
1960  exec 3<&-
1961  exec 3< $mmsdrfsFile
1962  while read -u3 sdrfsLine
1963  do
1964    # Parse the line.
1965    set -f ; set -A v -- - $sdrfsLine ; set +f
1966    IFS="$IFS_sv"
1967
1968    case ${v[$LINE_TYPE_Field]} in
1969
1970      $VERSION_LINE )  # this is the global header line
1971        # Increment the generation number
1972        newGenNumber=${v[$SDRFS_GENNUM_Field]}+1
1973        v[$SDRFS_GENNUM_Field]=$newGenNumber
1974        v[$HIGHEST_GPFS_DISK_NBR_Field]=$nsdBaseNumber
1975        ;;
1976
1977      $MEMBER_NODE )   # this line describes a node
1978        # Collect the reliable names of all nodes in the cluster.
1979        print -- "${v[$REL_HOSTNAME_Field]}" >> $nodefile
1980        checkForErrors "writing to file $nodefile" $?
1981        ;;
1982
1983      $SG_DISKS )  # this line describes a disk
1984        print -u2 "$mmcmd: There are disks in the cluster."
1985        print -u2 "$mmcmd: The base number for naming disks cannot be changed."
1986        cleanupAndExit
1987        ;;
1988
1989      * )  # We are not interested in any other lines.
1990        ;;
1991
1992    esac  # end Change some of the fields
1993
1994    # Build and write the line to the new mmsdrfs file.
1995    print_newLine >> $newsdrfs
1996    checkForErrors "writing to file $newsdrfs" $?
1997
1998    IFS=":"  # Change the separator back to ":" for the next iteration.
1999
2000  done  # end while read -u3
2001
2002  IFS="$IFS_sv"  # Restore the default IFS settings.
2003
2004  #######################
2005  # Commit the changes.
2006  #######################
2007  trap "" HUP INT QUIT KILL
2008  gpfsObjectInfo=$(commitChanges  \
2009     $nsId $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer)
2010  rc=$?
2011  if [[ $rc -ne 0 ]]
2012  then
2013    # The commit step failed
2014    printErrorMsg 381 $mmcmd
2015    cleanupAndExit
2016  fi
2017
2018  ##################
2019  # Unlock the sdr.
2020  ##################
2021  [[ $sdrLocked = yes ]] &&  \
2022    freeLockOnServer $primaryServer $ourNodeNumber > /dev/null
2023  sdrLocked=no
2024  trap posttrap HUP INT QUIT KILL
2025
2026  ###############################################
2027  # Propagate the changes to all affected nodes.
2028  ###############################################
2029  propagateSdrfsFile async $nodefile $newsdrfs $newGenNumber
2030
2031  cleanupAndExit 0
2032
2033}  #----- end of function resetNsdNumber --------------------------
2034
2035
2036######################################################################
2037#
2038# Function:  Save the specified file on both the primary and backup
2039#            server nodes.  Used in conjunction with tspreparedisk to
2040#            create backup copy of the SG descriptor being migrated.
2041#            The information is stored in /var/mmfs/tmp/mmimportfs
2042#            The file name has the following format:
2043#            tspreparedisk.diskDesc.<diskName>.<checksum>.<timestamp>
2044#
2045# Input:     $1 - file name with the following format:
2046#                 /var/mmfs/tmp/tspreparedisk.diskDesc.<diskName>
2047#
2048# Output:    None
2049#
2050# Returns:   0 - no errors encountered
2051#            non-zero - error encounterred
2052#
2053######################################################################
2054function saveSGDescFile    #  <sgDescFile>
2055{
2056  typeset sourceFile="mmcommon.sh"
2057  [[ -n $DEBUG || -n $DEBUGsaveSGDescFile ]] && set -x
2058  $mmTRACE_ENTER "$*"
2059  typeset sgDescFile=$1
2060
2061  typeset sumOutput checksum timeStamp targetName serverNode
2062  typeset mvResult keyword status errorCode
2063
2064  if [[ $MMMODE != lc && $MMMODE != single ]]
2065  then
2066    # Command not supported.
2067    printErrorMsg 376 "$mmcmd:saveSGDescFile" $MMMODE
2068    cleanupAndExit
2069  fi
2070
2071  # Return ENOENT if file is not there or if it is empty.
2072  [[ ! -s $sgDescFile ]] &&  \
2073    return 2
2074
2075  # Calculate the checksum for the source file.
2076  sumOutput=$($sum $sgDescFile)
2077  checkForErrors "sum $sgDescFile" $?
2078  set -f ; set -- $sumOutput ; set +f
2079  checksum=$1
2080
2081  # Get a current timestamp.
2082  timeStamp=$($perl -e 'print time')
2083
2084  # Generate the name under which the file will be stored
2085  # on the primary and backup configuration servers.
2086  targetName=${tmpDir}mmimportfs/${sgDescFile##*/}.${checksum}.${timeStamp}
2087
2088  # Commit the file to the server nodes.
2089  [[ -z $primaryServer ]] && determineMode
2090  for serverNode in $(print -- "$primaryServer $backupServer")
2091  do
2092    if [[ $serverNode = $ourNodeName ]]
2093    then
2094      mvResult=$($mmremote mvSGDescFile  \
2095                   $sgDescFile $targetName $checksum $ourNodeName)
2096      rc=$?
2097    else
2098      mvResult=$(run onNode $serverNode mvSGDescFile  \
2099                   $sgDescFile $targetName $checksum $ourNodeName)
2100      rc=$?
2101    fi
2102
2103    # Parse the result.
2104    IFS=":"
2105    set -f ; set -- $mvResult ; set +f
2106    keyword=$1
2107    status=$2
2108    errorCode=$3
2109    IFS="$IFS_sv"
2110
2111    if [[ $keyword != mvSGDescFile ]]
2112    then
2113      # Unexpected error from mmremote or mmdsh.
2114      printErrorMsg 171 $mmcmd "mmremote mvSGDescFile" 1
2115      return 1
2116    fi
2117
2118    if [[ $status != success ]]
2119    then
2120      if [[ $errorCode = copyfile || $errorCode = checksum ]]
2121      then
2122        # Error retrieving data from client.
2123        printErrorMsg 379 $mmcmd $ourNodeName $serverNode
2124      else
2125        # Unexpected error from mmremote or mmdsh.
2126        printErrorMsg 171 $mmcmd "mmremote mvSGDescFile" 1
2127      fi
2128      return 1
2129    fi  # end of if [[ $status != success ]]
2130
2131  done # for serverNode in $(print -- "$primaryServer $backupServer")
2132
2133
2134  # Everything seems to have worked fine.
2135  # Remove the source file and return.
2136  $rm -f $sgDescFile
2137  return 0
2138
2139}  #----- end of function saveSGDescFile -------------------------
2140
2141
2142
2143#######################
2144# Mainline processing
2145#######################
2146
2147kword=$arg1
2148kword_lc=$arg1
2149arg3_lc=$arg3
2150
2151if [[ -z $kword ]]
2152then
2153  # Missing keyword
2154  printErrorMsg 133 mmcommon NULL
2155  cleanupAndExit
2156fi
2157
2158# Set up silent trap exception handling.
2159trap pretrap3 HUP INT QUIT KILL
2160
2161# Determine the execution environment and set needed global variables.
2162if [[ $arg3_lc  = checknewclusternode* ||
2163      $arg3_lc  = removefromclustercr  ||
2164      $kword_lc = getdiskdevices       ]]
2165then
2166  # If the node is not yet a member of the GPFS cluster,
2167  # the functions to determine the local data do not work.
2168  [[ -z $ourNodeName ]] && ourNodeName=$($hostname)
2169else
2170  # In all other cases, file mmsdrfs should already exist
2171  # and we can use it as a starting point.
2172  [[ -z $MMMODE || -z $environmentType ]] && determineMode
2173  getLocalNodeData
2174fi
2175
2176# Make sure we have the proper credentials.
2177[[ $getCredCalled = no ]] && getCred
2178
2179# Reset the remote commands if necessary.
2180[[ -n $GPFS_rshPath ]] && rsh=$GPFS_rshPath
2181[[ -n $GPFS_rcpPath ]] && rcp=$GPFS_rcpPath
2182
2183# Perform the action requested by the keyword.
2184case $kword_lc in
2185
2186                   #----------------------------------------
2187  init)            # mmcommon init <lockid | nolock>
2188                   #----------------------------------------
2189    if [[ $argc -ne 2 ]]
2190    then
2191      operands="<lockid | nolock>"
2192      printErrorMsg 260 mmcommon $kword "$operands"
2193      cleanupAndExit
2194    fi
2195
2196    # Update local system files; lock the sdr if requested.
2197    gpfsInit $arg2
2198    rc=$?
2199    ;;
2200
2201                     #----------------------------------------
2202  getlocalnodename)  # mmcommon getLocalNodeName
2203                     #----------------------------------------
2204    print -- "$ourNodeName"
2205    rc=0
2206    ;;
2207
2208                     #----------------------------------------
2209  getclusternodes)   # mmcommon getClusterNodes
2210                     #----------------------------------------
2211    # Return the reliable hostnames of all nodes in the cluster.
2212    getNodeList $REL_HOSTNAME_Field $GLOBAL_ID $mmsdrfsFile
2213    rc=$?
2214    ;;
2215
2216                         #----------------------------------------
2217  getnodedatafordaemon)  # mmcommon getNodeDataForDaemon <clType>
2218                         #----------------------------------------
2219    # Set MMMODE from the passed cluster type parameter.
2220    [[ -n $arg2 ]] && export MMMODE=$arg2
2221
2222    # Get the data from the mmsdrfs file.
2223    getNodeDataFromSdrfs $sdrNodeFile "."
2224    rc=$?
2225
2226    # Return the result to the caller via standard output.
2227    [[ $rc -eq 0 ]] && $cat $sdrNodeFile
2228    ;;
2229
2230               #----------------------------------------
2231  getnodelist) # mmcommon getNodeList [norefresh]
2232               #----------------------------------------
2233    # Get the data from the mmsdrfs file.
2234    getNodeListFromSdrfs $sdrNodeFile $arg2
2235    rc=$?
2236
2237    # Return the result to the caller via standard output.
2238    [[ $rc -eq 0 ]] && $cat $sdrNodeFile
2239    ;;
2240
2241                  #------------------------
2242  getdiskdevices) # mmcommon getDiskDevices
2243                  #------------------------
2244    # Generate a list of all disk devices known to this node.
2245    getDiskDevices
2246    rc=$?
2247    ;;
2248
2249                         #---------------------------------------
2250  getvsdrpdnodedata)     # mmcommon getVsdRpdNodeData <filename>
2251                         #---------------------------------------
2252    if [[ $argc -ne 2 ]]
2253    then
2254      operands="<filename>"
2255      printErrorMsg 260 mmcommon $kword "$operands"
2256      cleanupAndExit
2257    fi
2258
2259    # Obtain node-related data from the peer domain.
2260    getVsdRpdNodeData $arg2
2261    rc=$?
2262    ;;
2263
2264                   #----------------------------------------
2265  getvsddata)      # mmcommon getVSDdata <filename>
2266                   #----------------------------------------
2267    if [[ $argc -ne 2 ]]
2268    then
2269      operands="<filename>"
2270      printErrorMsg 260 mmcommon $kword "$operands"
2271      cleanupAndExit
2272    fi
2273
2274    # Call routine to extract vsd information based on
2275    # which type of VSD code (PSSP or RSCT) is in use.
2276    vsdPath=$(LC_ALL=C $ls -l $vsdatalst 2>/dev/null)
2277    if [[ $vsdPath = *${vsdatalstRSCT}* && -x $vsdatalstRSCT ]]
2278    then
2279      # Extract VSD-related data from the RPD.
2280      getVSDdataRPD $arg2
2281      rc=$?
2282    elif [[ $vsdPath = *${vsdatalstPSSP}* && -x $vsdatalstPSSP ]]
2283    then
2284      # Extract VSD-related data from the SDR.
2285      getVSDdataSDR $arg2
2286      rc=$?
2287    else
2288      printErrorMsg 320 "getVSDdata"
2289      cleanupAndExit
2290    fi
2291    ;;
2292
2293                          #------------------------------------
2294  getvsdnodedata)         # mmcommon getVsdNodeData <filename>
2295                          #------------------------------------
2296    if [[ $argc -ne 2 ]]
2297    then
2298      operands="<filename>"
2299      printErrorMsg 260 mmcommon $kword "$operands"
2300      cleanupAndExit
2301    fi
2302
2303    # Call routine to extract vsd information based on
2304    # which type of VSD code (PSSP or RSCT) is in use.
2305    vsdPath=$(LC_ALL=C $ls -l $vsdatalst 2>/dev/null)
2306    if [[ $vsdPath = *${vsdatalstRSCT}* && -x $vsdatalstRSCT ]]
2307    then
2308      # Extract VSD-related data from the RPD.
2309      getVsdNodeDataRPD $arg2
2310      rc=$?
2311    elif [[ $vsdPath = *${vsdatalstPSSP}* && -x $vsdatalstPSSP ]]
2312    then
2313      # Extract VSD-related data from the SDR.
2314      getVsdNodeDataSDR $arg2
2315      rc=$?
2316    else
2317      printErrorMsg 320 "getVsdNodeData"
2318      cleanupAndExit
2319    fi
2320    ;;
2321
2322                     #----------------------------------------
2323  getvsdnodenumbers) # mmcommon getVsdNodeNumbers
2324                     #----------------------------------------
2325    # Create mapping of the GPFS to VSD node numbers.
2326    getVsdNodeNumbers
2327    rc=$?
2328    ;;
2329
2330                   #---------------------------------------------------------
2331  checkauth)       # mmcommon checkAuth <clusterName> <sgDevice> [norefresh]
2332                   #---------------------------------------------------------
2333    if [[ $argc -lt 3 ]]
2334    then
2335      operands="<clusterName> <deviceName> [norefresh]"
2336      printErrorMsg 260 mmcommon $kword "$operands"
2337      cleanupAndExit
2338    fi
2339
2340    # Check the authorization.
2341    checkAuth $arg2 "$arg3" $arg4
2342    rc=$?
2343    ;;
2344
2345                   #--------------------
2346  gpfsready)       # mmcommon gpfsready
2347                   #--------------------
2348    # Invoke the gpfsready exit.
2349    gpfsready
2350    rc=$?
2351    ;;
2352
2353                   #-----------------
2354  mmfsup)          # mmcommon mmfsup
2355                   #-----------------
2356    # Invoke the mmfsup exit.
2357    mmfsup $arg2 $arg3
2358    rc=$?
2359    ;;
2360
2361                   #-------------------
2362  mmfsdown)        # mmcommon mmfsdown
2363                   #-------------------
2364    # Invoke the mmfsdown exit.
2365    mmfsdown
2366    rc=$?
2367    ;;
2368
2369                    #---------------------------------------
2370  preunmount)       # mmcommon preunmount <device> <reason>
2371                    #---------------------------------------
2372    if [[ $argc -lt 3 ]]
2373    then
2374      operands="<deviceName|all> <reason>"
2375      printErrorMsg 260 mmcommon $kword "$operands"
2376      cleanupAndExit
2377    fi
2378
2379    # Invoke the preunmount exit.
2380    preunmount $arg2 $arg3
2381    rc=$?
2382    ;;
2383
2384                   #----------------------------------------------------
2385  gpfsrecover)     # mmcommon gpfsrecover <sgDevice> <phase> <nodeList>
2386                   #----------------------------------------------------
2387    if [[ $argc -lt 4 ]]
2388    then
2389      operands="<deviceName> <pahse> <nodeNumber> [<nodeNumber> ... ]"
2390      printErrorMsg 260 mmcommon $kword "$operands"
2391      cleanupAndExit
2392    fi
2393
2394    # Shift past the positional parameters and get the node list.
2395    shift 3
2396    nodeList=$*
2397
2398    # Invoke the gpfsrecover exit.
2399    gpfsrecover $arg2 $arg3 $nodeList
2400    rc=$?
2401    ;;
2402
2403                   #-------------------------------------------------------
2404  getefoptions)    # mmcommon getEFOptions <sgDevice> <checkMountPointOpt>
2405                   #-------------------------------------------------------
2406    if [[ $argc -ne 3 ]]
2407    then
2408      operands="<deviceName> <checkMountPointOpt>"
2409      printErrorMsg 260 mmcommon $kword "$operands"
2410      cleanupAndExit
2411    fi
2412
2413    # Generate the options line.
2414    getEFOptions "$arg2" $arg3
2415    rc=$?
2416    ;;
2417
2418                   #------------------------------------
2419  getmountpoint)   # mmcommon getMountPoint <sgDevice>
2420                   #------------------------------------
2421    if [[ $argc -ne 2 ]]
2422    then
2423      operands="<deviceName>"
2424      printErrorMsg 260 mmcommon $kword "$operands"
2425      cleanupAndExit
2426    fi
2427
2428    # Generate the options line.
2429    getMountPoint "$arg2" $arg3
2430    rc=$?
2431    ;;
2432
2433                   #------------------------------------------
2434  getcontactnodes) # mmcommon getContactNodes <remoteCluster>
2435                   #------------------------------------------
2436    if [[ $argc -ne 2 ]]
2437    then
2438      operands="<remoteCluster>"
2439      printErrorMsg 260 mmcommon $kword "$operands"
2440      cleanupAndExit
2441    fi
2442
2443    # If an user exit is installed, try it first.  If we get
2444    # a result, consider this to be the definitive answer.
2445    contactList=""
2446    if [[ -x $remoteclusternodes ]]
2447    then
2448      contactList=$($remoteclusternodes $arg2)
2449      rc=$?
2450      # Tell the daemon where does the data come from.
2451      [[ -n $contactList ]] &&  \
2452        contactList="${contactList},refreshMethod=1"
2453    fi
2454
2455    # If an user exit is not activated, or if it did not return
2456    # anything, look for the contact nodes in the mmsdrfs file.
2457    if [[ -z $contactList ]]
2458    then
2459      gpfsInit nolock >/dev/null
2460      checkForErrors gpfsInit $?
2461      contactList=$($grep -e "^$arg2:$REM_CLUSTER:" $mmsdrfsFile |  \
2462                              $GETVALUE $CONTACT_NODES_Field)
2463#     # Tell the daemon where does the data come from.
2464#     [[ -n $contactList ]] &&  \
2465#       contactList="${contactList},refreshMethod=0"
2466    fi
2467
2468    # Put out the result.
2469    if [[ -n $contactList ]]
2470    then
2471      print -- "$contactList"
2472      rc=0
2473    else
2474      [[ $rc -eq 0 ]] && rc=19  # ENODEV
2475    fi
2476    ;;
2477
2478                   #----------------------------------------
2479  getfsnames)      # mmcommon getFSNames
2480                   #----------------------------------------
2481
2482    # Return the names of the file systems in the nodeset to which
2483    # this node belongs.  The environment is assumed to be up to date.
2484    # All errors are ignored.
2485    #
2486    # Because this function is used by the daemon and can be invoked
2487    # during recovery, there should be no locking and/or initializing
2488    # of the GPFS environment.  Otherwise, there can be a deadlock.
2489    #
2490    $awk -F: '                                         \
2491      BEGIN { nodesetId = "" }                         \
2492      $'$LINE_TYPE_Field'   == "'$MEMBER_NODE'"   &&   \
2493      $'$NODE_NUMBER_Field' == "'$ourNodeNumber'"  {   \
2494        { nodesetId = $'$NODESETID_Field' }            \
2495        { next }                                       \
2496      }                                                \
2497      $'$LINE_TYPE_Field' == "'$SG_HEADR'" &&          \
2498      $'$NODESETID_Field' == nodesetId {               \
2499        { print "/dev/"$'$DEV_NAME_Field' }            \
2500      }                                                \
2501    ' $mmsdrfsFile  2>/dev/null
2502    rc=0
2503    ;;
2504
2505                     #------------------------------------------
2506  getquotaenabledfs) # mmcommon getQuotaEnabledFS [<nodesetId>]
2507                     #------------------------------------------
2508
2509    # Make sure the mmsdrfs file is current.
2510    gpfsInitOutput=$(gpfsInit nolock)
2511    setGlobalVar $? $gpfsInitOutput
2512
2513    # If the nodeset is set to the global id, clear the variable
2514    # so that we can look at all SG_MOUNT records in the sdrfs.
2515    # Otherwise, prepend the '^' char to ensure correct match.
2516    [[ -n $arg2 ]] && nsId="$arg2"
2517    [[ $arg2 = $GLOBAL_ID ]] && nsId=""
2518    [[ -n $nsId ]] && nsId="^$nsId"
2519
2520    # Put out the names of all file systems that have non-null quota options.
2521    $awk -F: '                                \
2522      /'$nsId:$SG_MOUNT:'/ {                  \
2523        if ( $'$QUOTA_OPT_Field' != "" ) {    \
2524          { print $'$DEV_NAME_Field' }        \
2525        }                                     \
2526      }                                       \
2527    ' $mmsdrfsFile
2528    checkForErrors awk $?
2529    rc=0
2530    ;;
2531
2532                     #----------------------------------------
2533  getdisknames)      # mmcommon getDiskNames [<SGname>] [<nodesetId>]
2534                     #----------------------------------------
2535
2536    # Make sure the mmsdrfs file is current.
2537    gpfsInitOutput=$(gpfsInit nolock)
2538    setGlobalVar $? $gpfsInitOutput
2539
2540    # Make sure that the file system name, if specified,
2541    # is stripped from any /dev/ prefix.
2542    deviceName=""
2543    [[ -n $arg2 ]] && deviceName="${arg2##+(/)dev+(/)}:"
2544
2545    # If the nodeset is set to the global id, clear the variable
2546    # so that we can look at all SG_DISKS records in the sdrfs.
2547    # Otherwise, prepend the '^' char to ensure correct match.
2548    [[ -n $arg3 ]] && nsId="$arg3"
2549    [[ $arg3 = $GLOBAL_ID ]] && nsId=""
2550    [[ -n $nsId ]] && nsId="^$nsId"
2551
2552    # Put out the names of all file system disks.
2553    $awk -F: '                                                      \
2554      /'$nsId:$SG_DISKS:$deviceName'/ { print $'$DISK_NAME_Field' } \
2555    ' $mmsdrfsFile
2556    checkForErrors awk $?
2557    rc=0
2558    ;;
2559
2560                     #----------------------------------------
2561  getsgdevice)       # mmcommon getSGDevice <diskname>
2562                     #----------------------------------------
2563    # Make sure the mmsdrfs file is current.
2564    gpfsInitOutput=$(gpfsInit nolock)
2565    setGlobalVar $? $gpfsInitOutput
2566
2567    # Find the file system to which the disk belongs.
2568    findFSforDisk "$arg2" $mmsdrfsFile
2569    rc=0
2570    ;;
2571
2572                     #----------------------------------------
2573  recoverfs)         # mmcommon recoverfs <fsname>
2574                     #----------------------------------------
2575    if [[ $argc -lt 2 ]]
2576    then
2577      operands="<fsname>"
2578      printErrorMsg 260 mmcommon $kword "$operands"
2579      cleanupAndExit
2580    fi
2581
2582    # Make sure the mmsdrfs file matches the GPFS daemon's data
2583    # for the specified filesystem.
2584    recoverfs "$arg2"
2585    rc=$?
2586    ;;
2587
2588                     #----------------------------------------
2589  getnsddata)        # mmcommon getNsdData [<fsname>]
2590                     #----------------------------------------
2591    # Make sure the mmsdrfs file is current.
2592    gpfsInitOutput=$(gpfsInit nolock)
2593    setGlobalVar $? $gpfsInitOutput
2594
2595    # Retrieve the NSD data.
2596    getNsdData $arg2
2597    rc=0
2598    ;;
2599
2600                     #---------------------------------------------------
2601  restoremmfscfg )   # mmcommon restoreMmfscfg <nodesetId>
2602                     #---------------------------------------------------
2603    if [[ $argc -lt 2 ]]
2604    then
2605      operands=" <nodesetId> "
2606      printErrorMsg 260 mmcommon $kword "$operands"
2607      cleanupAndExit
2608    fi
2609
2610    # Retrieve the mmfs.cfg data.
2611    restoreMmfscfg $arg2
2612    rc=$?
2613    ;;
2614
2615                     #---------------------------------------------------
2616  resetnsdnumber )   # mmcommon resetNsdNumber <nn>
2617                     #---------------------------------------------------
2618    if [[ $argc -lt 2 ]]
2619    then
2620      operands=" <nodesetId> "
2621      printErrorMsg 260 mmcommon $kword "$operands"
2622      cleanupAndExit
2623    fi
2624
2625    # Change the starting number for NSD names.
2626    resetNsdNumber $arg2
2627    rc=$?
2628    ;;
2629
2630                   #-------------------------------------------------------
2631  on1 | on1long )  # mmcommon on1 <hostname> <remoteCommand> [<arg ... >]
2632                   #-------------------------------------------------------
2633    if [[ $argc -lt 3 ]]
2634    then
2635      operands="<hostname> <remoteCommand> [<arg ... >] "
2636      printErrorMsg 260 mmcommon $kword "$operands"
2637      cleanupAndExit
2638    fi
2639
2640    target=$arg2
2641
2642    # Shift past the hostname and get the command to execute and its args.
2643    shift 2
2644    remoteCommand=$*
2645    remoteVerb=$1
2646
2647    if [[ $target = $ourNodeName || $MMMODE = single ]]
2648    then
2649      # If we happen to be the target node, run the command locally.
2650      $mmremote $remoteCommand
2651      rc=$?
2652
2653    else
2654      # Invoke mmdsh to execute command on remote system,
2655      # suppressing prepending of the hostname to the output lines.
2656      $rm -f $tmpDir$remoteVerb$$.*
2657      $mmdsh -svL $target $mmremote onbehalf2 $ourNodeName $remoteVerb$$  \
2658                  $MMMODE $NO_LINK mmremote $remoteCommand
2659      rc=$?
2660
2661      # Determine the return code.  The goal is to pass back the return code
2662      # from the mmremote command.  Because rsh and different versions of ssh
2663      # handle the return code differently (e.g., rsh does not propagate
2664      # it back), mmremote onbehalf creates a special file that has the
2665      # return code appended at the end of its name.  If we do not see this
2666      # file on our side, we assume that mmdsh returned the return code from
2667      # the remote command.  Although this is not necessarily always the case
2668      # (there could have been a problem with the touch command that creates
2669      # the special file) it is the best we can do under the circumstances.
2670      rcInfo=$($ls $tmpDir$remoteVerb$$.* 2> /dev/null)
2671      $rm -f $tmpDir$remoteVerb$$.*
2672      if [[ -n $rcInfo ]]
2673      then
2674        # The return code was passed back via the empty file mechanism.
2675        # Extract the return code from the file name.
2676        rc=${rcInfo#$tmpDir$remoteVerb$$\.}
2677#esjx      else
2678#esjx        # The special file was not found.
2679#esjx        # Override the rc from mmdsh if necessary.
2680#esjx        [[ $rc -eq 0 ]] && rc=1
2681      fi
2682    fi
2683    ;;
2684
2685              #---------------------------------------------------
2686  onall)      # mmcommon onall <relNameFile> <unreachedNodesFile>
2687              #                   <remoteCommand> [<arg ... >]
2688              #---------------------------------------------------
2689    if [[ $argc -lt 4 ]]
2690    then
2691      operands="<relNameFile> <unreachedNodesFile> <remoteCommand> [<arg ... >]"
2692      printErrorMsg 260 mmcommon $kword "$operands"
2693      cleanupAndExit
2694    fi
2695
2696    # Shift past the reliable names file and the report file
2697    # and get the command to execute and its args.
2698    shift 3
2699    remoteCommand=$*
2700
2701    if [[ $MMMODE = single ]]
2702    then
2703      # Execute the command locally.
2704      $mmremote $remoteCommand
2705      rc=$?
2706    else
2707      # Invoke mmdsh to execute command on remote systems.
2708      $mmdsh -vF $arg2 -R $arg3 $mmremote $remoteCommand
2709      rc=$?
2710    fi
2711    ;;
2712
2713               #----------------------------------------------------------------
2714  onall_async) # mmcommon onall_async <relNameFile> <remoteCommand> [<arg ... >]
2715               #----------------------------------------------------------------
2716    if [[ $argc -lt 3 ]]
2717    then
2718      operands="<relNameFile> <remoteCommand> [<arg ... >] "
2719      printErrorMsg 260 mmcommon $kword "$operands"
2720      cleanupAndExit
2721    fi
2722
2723    # Shift past the file name and get the command to execute and its args.
2724    shift 2
2725    remoteCommand=$*
2726
2727    if [[ $MMMODE = single ]]
2728    then
2729      # Execute the command locally.
2730      $mmremote $remoteCommand
2731      rc=$?
2732    else
2733      # Invoke mmdsh to execute command on remote systems.
2734#esjdbg  # Show msgs during development and testing only.
2735#esjdbg  $mmdsh -vF $arg2 $mmremote $remoteCommand
2736      $mmdsh -vF $arg2 $mmremote $remoteCommand >/dev/null 2>&1
2737      rc=$?
2738    fi
2739
2740    # Remove the node names file.  The caller is gone by now.
2741    $rm -f $arg2
2742    ;;
2743
2744                              #----------------------------------------------
2745  pushsdr | pushsdr_async )   # mmcommon pushSdr <relNameFile> <fileToCopy>
2746                              #                  <checksum> [<options>]
2747                              #----------------------------------------------
2748    if [[ $argc -lt 4 ]]
2749    then
2750      operands="<relNameFile> <fileToCopy> <checksum> [<options>]"
2751      printErrorMsg 260 mmcommon $kword "$operands"
2752      cleanupAndExit
2753    fi
2754
2755    if [[ $kword_lc = pushsdr_async ]]
2756    then
2757      async_call=yes
2758#esjdbg  # Show msgs during development and testing only.
2759#esjdbg  print -u2 "$(date): mmcommon $kword: mmsdrfs propagation started"
2760    fi
2761
2762    # Shift past all positional parameters and collect the command arguments.
2763    shift 4
2764    opt="$@"
2765
2766    if [[ $MMMODE = single ]]
2767    then
2768      # This function is a no-op for single clusters.
2769      rc=0
2770    else
2771#esjdbg  # Show msgs during development and testing only.
2772#esjdbg  $mmdsh -vF $arg2 -I $arg3 $mmremote upgradeSystemFiles $arg3 $arg4 "$opt"
2773      $mmdsh -vF $arg2 -I $arg3  \
2774        $mmremote upgradeSystemFiles $arg3 $arg4 "$opt" >/dev/null 2>&1
2775      rc=$?
2776    fi
2777
2778    if [[ $async_call = yes ]]
2779    then
2780      # Cleanup files that were left behind by the main process.
2781      $rm -f $arg2 $arg3
2782#esjdbg  # Show msgs during development and testing only.
2783#esjdbg  print -u2 "$(date): mmcommon $kword: mmsdrfs propagation completed; mmdsh rc=$rc"
2784    fi
2785    ;;
2786
2787                              #------------------------------------------------
2788  pushkey | pushkey_async )   # mmcommon pushKey <nodeFile> <sdrfsFile>
2789                              #                  <sdrfsChecksum>
2790                              #                  <keyFile> <keyChecksum>
2791                              #                  [<options>]
2792                              #------------------------------------------------
2793    if [[ $argc -lt 6 ]]
2794    then
2795      operands="<nodeFile> <sdrfsFile> <sdrfsChecksum> <keyFile> <keyChecksum> [<options>]"
2796      printErrorMsg 260 mmcommon $kword "$operands"
2797      cleanupAndExit
2798    fi
2799
2800    if [[ $kword_lc = pushkey_async ]]
2801    then
2802      async_call=yes
2803#esjdbg  # Show msgs during development and testing only.
2804#esjdbg  print -u2 "$(date): mmcommon $kword: mmsdrfs propagation started"
2805    fi
2806
2807    # Shift past all positional parameters and collect the command arguments.
2808    shift 6
2809    opt="$@"
2810
2811    if [[ $MMMODE = single ]]
2812    then
2813      # This function is a no-op for single clusters.
2814      rc=0
2815    else
2816#esjdbg  # Show msgs during development and testing only.
2817#esjdbg  $mmdsh -vF $arg2 -I $arg3 -I $arg5  \
2818#esjdbg    $mmremote upgradeSystemFiles2 $arg3 $arg4 $arg5 $arg6 "$opt"
2819      $mmdsh -vF $arg2 -I $arg3 -I $arg5  \
2820        $mmremote upgradeSystemFiles2 $arg3 $arg4 $arg5 $arg6 "$opt" >/dev/null 2>&1
2821      rc=$?
2822    fi
2823
2824    if [[ $async_call = yes ]]
2825    then
2826      # Cleanup files that were left behind by the main process.
2827      $rm -f $arg2 $arg3
2828      [[ $arg5 != ${genkeyData}* ]] && $rm -f $arg5
2829#esjdbg  # Show msgs during development and testing only.
2830#esjdbg  print -u2 "$(date): mmcommon $kword: mmsdrfs propagation completed; mmdsh rc=$rc"
2831    fi
2832    ;;
2833
2834  onactive | onactive_async )
2835             #------------------------------------------------------------------
2836             # mmcommon onactive <preferredNode> <relNameFile> <fileToCopy>
2837             #           <fsToCheck> <scope> <link> <remoteCommand> [<arg ... >]
2838             #------------------------------------------------------------------
2839    if [[ $argc -lt 8 ]]
2840    then
2841      operands="<preferredNode> <relNameFile> <fileToCopy>"
2842      operands="$operands <fsToCheck> <scope> <link> <remoteCommand> [<arg ... >] "
2843      printErrorMsg 260 mmcommon $kword "$operands"
2844      cleanupAndExit
2845    fi
2846
2847    # If async call, mark the relNameFile for deletion.
2848    [[ $kword_lc = onactive_async ]] && async_call=yes
2849
2850    # Shift past all positional parameters and collect the command arguments.
2851    shift 8
2852    arguments="$@"
2853
2854    # Find an active node and execute the command.
2855    runRemoteCommand $arg2 $arg3 $arg4 $arg5 $arg6 $arg7 $arg8 "$arguments"
2856    rc=$?
2857
2858    # Remove the file with node names.
2859    [[ $async_call = yes ]] && $rm -f $arg3
2860    ;;
2861
2862                #-------------------------------------------------------
2863  linkcommand)  # mmcommon linkCommand <preferredNode> <relNameFile>
2864                #                      <remoteCommand> [<arg ... >]
2865                #-------------------------------------------------------
2866    if [[ $argc -lt 4 ]]
2867    then
2868      operands="<preferredNode> <relNameFile> <remoteCommand> [<arg ... >] "
2869      printErrorMsg 260 mmcommon $kword "$operands"
2870      cleanupAndExit
2871    fi
2872
2873    # Shift past all positional parameters and collect the command arguments.
2874    shift 4
2875    arguments="$@"
2876
2877    # Find an active node and execute the command.
2878    runRemoteCommand $arg2 $arg3  \
2879      $NO_FILE_COPY $NO_MOUNT_CHECK NULL $LINK $arg4 "$arguments"
2880    rc=$?
2881    ;;
2882
2883        #-------------------------------------------
2884  run)  # mmcommon run <function> [arg ... ]
2885        # Note:  Intended for use by SMIT mostly
2886        #-------------------------------------------
2887    if [[ $argc -lt 2 ]]
2888    then
2889      operands="<function> [arg ... ]"
2890      printErrorMsg 260 mmcommon $kword "$operands"
2891      cleanupAndExit
2892    fi
2893
2894    shift 1  # Skip past the keyword "run".
2895    $@       # Execute the requested function.
2896    rc=$?
2897    ;;
2898
2899              #-------------------------------------------
2900  freelocks)  # mmcommon freeLocks
2901              #-------------------------------------------
2902    primaryServer=$($head -1 $mmsdrfsFile | $GETVALUE $PRIMARY_SERVER_Field)
2903    setRunningCommand null $primaryServer > /dev/null 2>&1
2904    freeLockOnServer $primaryServer > /dev/null 2>&1
2905    freeEnvLock > /dev/null 2>&1
2906    ;;
2907
2908                      #---------------------------
2909  startautomounter )  # mmcommon startAutomounter
2910                      #---------------------------
2911    # Make sure that the local mmfs.cfg file is up-to-date.
2912    gpfsInitOutput=$(gpfsInit nolock)
2913    checkForErrors gpfsInit $?
2914
2915    # Find out the value of the automountDir config parameter.
2916    automountDir=$(showCfgValue automountDir)
2917    [[ -z $automountDir ]] && automountDir=$defaultAutomountDir
2918
2919    # Run the OS automount command.
2920    startAutomounter $automountDir
2921    rc=$?
2922    ;;
2923
2924                    #--------------------------------------
2925  savesgdescfile )  # mmcommon saveSGDescFile <sgDescFile>
2926                    #--------------------------------------
2927    if [[ $argc -lt 2 ]]
2928    then
2929      operands="<sgDescFile>"
2930      printErrorMsg 260 mmcommon $kword "$operands"
2931      cleanupAndExit
2932    fi
2933
2934    # Store the file on the config server nodes.
2935    saveSGDescFile $arg2
2936    rc=$?
2937    ;;
2938
2939                         #------------------------------------------------------
2940  expirationdatacleanup) # mmcommon expirationDataCleanup <expData> <lockAction>
2941                         #------------------------------------------------------
2942    expirationDataCleanup $arg2 $arg3
2943    rc=0
2944    ;;
2945
2946                   #-----------------------
2947  killsdrserv)     # mmcommon killSdrServ
2948                   #-----------------------
2949    killSdrServ
2950    rc=$?
2951    ;;
2952
2953        #----------------------------------------
2954  * )   # Unknown action requested
2955        #----------------------------------------
2956    # Invalid keyword
2957    printErrorMsg 133 mmcommon $kword
2958    cleanupAndExit
2959    ;;
2960
2961esac  # end case $kword_lc in
2962
2963cleanupAndExit $rc doNotUnlock
2964
Note: See TracBrowser for help on using the repository browser.