source: gpfs_3.1_ker2.6.20/lpp/mmfs/bin/mmfsfuncs @ 250

Last change on this file since 250 was 16, checked in by rock, 17 years ago
  • Property svn:executable set to *
File size: 59.0 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. 1999,2007
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# @(#)83 1.109.1.2 src/avs/fs/mmfs/ts/admin/mmfsfuncs.sh, mmfs, avs_rgpfs24, rgpfs24s012a 3/29/07 13:07:03
17######################################################################
18
19
20######################################################################
21#  Pull in operating system dependent functions and declarations.
22######################################################################
23[[ -e ${mmcmdDir}/mmfsfuncs.$osName ]] &&  \
24  . ${mmcmdDir}/mmfsfuncs.$osName
25
26
27##################################################################
28#
29# Function:  Given a disk name, find the file system to which
30#            the disk belongs.
31#
32# Input:     $1 - Name of disk
33#            $2 - Name of mmsdrfs file
34#
35# Output:    $1 - File system name
36#
37# Returns:   0 - file system found
38#            1 - file system not found
39#
40##################################################################
41function findFSforDisk  #  <diskName>  <sdrfs>
42{
43  typeset sourceFile="mmfsfuncs.sh"
44  [[ -n $DEBUG || -n $DEBUGfindFSforDisk ]] && set -x
45  $mmTRACE_ENTER "$*"
46  typeset diskName=$1
47  typeset sdrfs=$2
48  typeset rc fsName
49
50  # The awk script looks at all SG_DISKS lines.
51  # If the disk name field matches the value in $diskName,
52  # we have located the line that we are looking for.
53  # Print the file system device name and stop.
54  fsName=$($awk -F: '                              \
55    /':$SG_DISKS:'/ {                              \
56      if ($'$DISK_NAME_Field' == "'$diskName'" &&  \
57          $'$DEV_NAME_Field' != "'$NO_DEVICE'") {  \
58        { print $'$DEV_NAME_Field' }               \
59        { exit 0 }                                 \
60      }                                            \
61    }                                              \
62  ' $sdrfs)
63  checkForErrors awk $?
64
65  if [[ -n $fsName ]]
66  then
67    print -- $fsName
68    return 0
69  else
70    return 1
71  fi
72
73}  #----- end of function findFSforDisk ------------------
74
75
76##################################################################
77#
78# Function:  Given a disk name, find the corresponding SG_DISKS
79#            line and return the value of the specified field.
80#
81# Input:     $1 - field whose value should be returned
82#            $2 - name of disk for which info is sought
83#            $3 - name of mmsdrfs file to search
84#
85# Output:    $1 - value of the requested field
86#
87# Returns:   0 - disk found and requested value returned
88#            1 - disk not found
89#
90##################################################################
91function getDiskInfo  #  <returnField> <diskName> <sdrfs>
92{
93  typeset sourceFile="mmfsfuncs.sh"
94  [[ -n $DEBUG || -n $DEBUGgetDiskInfo ]] && set -x
95  $mmTRACE_ENTER "$*"
96  typeset returnField=$1
97  typeset diskName=$2
98  typeset sdrfs=$3
99  typeset rc result
100
101  # The awk script looks at SG_DISKS lines.
102  # If the diskname field matches the value in $diskName,
103  # we have located the line that we are looking for.
104  # Print the value of the requested field and stop.
105  result=$($awk -F: '                              \
106    /':$SG_DISKS:'/ {                              \
107      if ($'$DISK_NAME_Field' == "'$diskName'") {  \
108        { print $'$returnField' }                  \
109        { exit 0 }                                 \
110      }                                            \
111    }                                              \
112  ' $sdrfs)
113  checkForErrors awk $?
114
115  if [[ -n $result ]]
116  then
117    print -- $result
118    return 0
119  else
120    return 1
121  fi
122
123}  #----- end of function getDiskInfo --------------------
124
125
126############################################################################
127#
128# Function:  Given an mm disk descriptor and its corresponding free
129#            SG_DISKS line, this routine validates the parameters,
130#            converts the descriptor to ts format, and generates
131#            an updated SG_DISKS line.
132#
133# Input:     $1 - disk descriptor in mm format
134#            $2 - the current (free) SG_DISKS line for the disk
135#            $3 - file system to which the disk will be assigned
136#                   or $NO_DEVICE if invoked from mmcrnsd
137#                   or $CHANGE_NSD if invoked from mmchnsd
138#            $4 - nodeset to which the file system belongs
139#                   or $FREE_DISK if invoked from mmcrnsd
140#            $5 - status string with which to update DISK_STATUS_Field
141#                   when a match is found; NULL if no value
142#            $6 - (optional) Default disk usage if usage is not
143#                   specified in the mm disk descriptor.
144#                   "oldDiskUsage" is used when replacing a disk.
145#
146# Output:    $1 - updated SG_DISKS line for the disk
147#            $2 - Disk descriptor in TS format
148#            $3 - Disk usage
149#
150# Returns:   0 - valid descriptor
151#            1 - invalid descriptor
152#
153############################################################################
154function validateAndConvertNsdDescriptor  # <mmDiskDesc> <freeDiskLine>
155                                          # <fs> <nodesetId> <statusString>
156                                          # [<defaultUsage>]
157{
158  typeset sourceFile="mmfsfuncs.sh"
159  [[ -n $DEBUG || -n $DEBUGvalidateAndConvertNsdDescriptor ]] && set -x
160  $mmTRACE_ENTER "$*"
161  typeset mmDiskDesc=$1
162  typeset freeDiskLine=$2
163  typeset deviceName=$3
164  typeset nodesetId=$4
165  typeset statusString=$5
166  typeset defaultUsage=$6
167
168  typeset updatedDiskLine diskName diskUsage failureGroup ipa storagePool
169  typeset primaryNsdAdminNode newPrimaryNsdAdminNode
170  typeset primaryNsdDaemonNode newPrimaryNsdDaemonNode
171  typeset backupNsdAdminNode newBackupNsdAdminNode
172  typeset backupNsdDaemonNode newBackupNsdDaemonNode
173  typeset -i primaryNodeNumber defaultFailureGroup
174
175  typeset driverType="nsd"
176  typeset sectorSize=""
177  typeset hasMetaData=1
178  typeset hasData=1
179  typeset addingDiskToFS=""
180  typeset replacingDisk=""
181
182  [[ $statusString = NULL ]] && statusString=""
183  [[ $defaultUsage = oldDiskUsage ]] && replacingDisk=yes
184
185  ######################################################################
186  # Parse the mm descriptor and the current SG_DISKS line for the disk.
187  ######################################################################
188  IFS=":"
189  set -f ; set -- $mmDiskDesc ; set +f
190  diskName=${1#+(/)dev+(/)}       # name stripped of /dev/ prefix
191  newPrimaryNsdAdminNode=$2
192  newBackupNsdAdminNode=$3
193  diskUsage=$4
194  failureGroup=$5
195  storagePool=$7
196
197  set -f ; set -A v -- - $freeDiskLine ; set +f
198  IFS="$IFS_sv"
199
200  #################################################################
201  # Determine who the caller is.  The logic depends on whether
202  # we are creating a new disk (mmcrnsd), adding an already
203  # existing disk to a file system (mmcrfs, mmadddisk, mmrpldisk)
204  # or changing some of the disk attributes (mmchnsd).
205  #################################################################
206  if [[ $deviceName = $NO_DEVICE ]]
207  then
208    # Creating a new disk.  Verify that the disk name is specified.
209    deviceName=""
210    if [[ -z $diskName ]]
211    then
212      # The disk name must be specified in the disk descriptor.
213      printErrorMsg 23 $mmcmd
214      return 1
215    fi
216  elif [[ $deviceName = $CHANGE_NSD ]]
217  then
218    # The caller is mmchnsd or mmimportfs.
219    # The disk may or may not belong to a file system.
220    deviceName=${v[$DEV_NAME_Field]}
221    [[ $deviceName = $NO_DEVICE ]] && deviceName=""
222  else
223    # The caller is mmcrfs, mmadddisk, or mmrpldisk.
224    # The file system is known.
225    addingDiskToFS=yes
226  fi
227
228  #######################################################
229  # Verify the diskUsage parameter and set the ts flags.
230  #######################################################
231  [[ -z $defaultUsage ]] && defaultUsage=dataAndMetadata
232
233  [[ -z $diskUsage ]] && diskUsage=$defaultUsage
234
235  if [[ $diskUsage = dataAndMetadata ]]
236  then
237    :  # There is nothing to do; use default values.
238  elif [[ $diskUsage = metadataOnly ]]
239  then
240    hasData=0
241  elif [[ $diskUsage = dataOnly ]]
242  then
243    hasMetaData=0
244  elif [[ $diskUsage = descOnly ]]
245  then
246    hasData=0
247    hasMetaData=0
248  elif [[ $diskUsage = oldDiskUsage ]]
249  then
250    hasData=""
251    hasMetaData=""
252    diskUsage=${v[$DISK_USAGE_Field]}
253  else
254    # The disk usage parameter is invalid.
255    printErrorMsg 24 $mmcmd
256    return 1
257  fi
258
259  #######################################################
260  # Verify the NSD server node values.
261  #######################################################
262
263  # If a server node was specified, make sure that it is valid
264  # and convert it if necessary to an admin node adapter name.
265  if [[ -n $newPrimaryNsdAdminNode ]]
266  then
267    newPrimaryNsdAdminNode=$(checkAndConvertNodeValue  \
268      $newPrimaryNsdAdminNode $REL_HOSTNAME_Field)
269    [[ $? -ne 0 ]] && return 1
270    newPrimaryNsdDaemonNode=$(checkAndConvertNodeValue  \
271      $newPrimaryNsdAdminNode $DAEMON_NODENAME_Field)
272    [[ $? -ne 0 ]] && return 1
273  fi
274  if [[ -n $newBackupNsdAdminNode ]]
275  then
276    newBackupNsdAdminNode=$(checkAndConvertNodeValue  \
277      $newBackupNsdAdminNode $REL_HOSTNAME_Field)
278    [[ $? -ne 0 ]] && return 1
279    newBackupNsdDaemonNode=$(checkAndConvertNodeValue  \
280      $newBackupNsdAdminNode $DAEMON_NODENAME_Field)
281    [[ $? -ne 0 ]] && return 1
282  fi
283
284  # Are we adding disks to a file system?
285  if [[ -n $addingDiskToFS ]]
286  then
287    # If adding an existing disk to some file system,
288    # the descriptor cannot have NSD server nodes that
289    # are different than the ones already defined.
290    # Note:  Under normal circumstances, the server fields
291    #        in the disk descriptor should be null.
292    primaryNsdAdminNode=${v[$NSD_PRIMARY_NODE_Field]}
293    primaryNsdDaemonNode=${v[$DAEMON_NSD_PRIMARY_Field]}
294    backupNsdAdminNode=${v[$NSD_BACKUP_NODE_Field]}
295    backupNsdDaemonNode=${v[$DAEMON_NSD_BACKUP_Field]}
296
297    if [[ -n $newPrimaryNsdAdminNode &&  \
298          $newPrimaryNsdAdminNode != $primaryNsdAdminNode ]]
299    then
300      # The server node in the disk descriptor is not valid.
301      printErrorMsg 201 $mmcmd $newPrimaryNsdAdminNode
302      return 1
303    fi
304    if [[ -n $newBackupNsdAdminNode &&  \
305          $newBackupNsdAdminNode != $backupNsdAdminNode ]]
306    then
307      # The server node in the disk descriptor is not valid.
308      printErrorMsg 201 $mmcmd $newBackupNsdAdminNode
309      return 1
310    fi
311  else
312    # If creating a new disk or changing an existing one,
313    # accept the server node values from the descriptor.
314    primaryNsdAdminNode=$newPrimaryNsdAdminNode
315    primaryNsdDaemonNode=$newPrimaryNsdDaemonNode
316    backupNsdAdminNode=$newBackupNsdAdminNode
317    backupNsdDaemonNode=$newBackupNsdDaemonNode
318
319    if [[ -n $backupNsdAdminNode && -z $primaryNsdAdminNode ]]
320    then
321      # The primary NSD node is not specified.
322      printErrorMsg 491 $mmcmd $diskName
323      return 1
324    fi
325  fi  # end of if [[ -n $addingDiskToFS ]]
326
327  # If a primary NSD node was specified, find its node number
328  # in order to compute the default failure group value.
329  if [[ -n $primaryNsdAdminNode ]]
330  then
331    if [[ $backupNsdAdminNode = $primaryNsdAdminNode ]]
332    then
333      # The primary and backup NSD servers must be different nodes.
334      printErrorMsg 492 $mmcmd
335      return 1
336    fi
337
338    primaryNodeNumber=$(checkAndConvertNodeValue $primaryNsdAdminNode $NODE_NUMBER_Field)
339    [[ $? -ne 0 ]] && return 1
340
341    # The default failure group is the primary server number + 4000.
342    defaultFailureGroup=$primaryNodeNumber+4000
343  fi  # end of if [[ -n $primaryNsdAdminNode ]]
344
345  ##############################
346  # Failure group verification
347  ##############################
348  if [[ -n $replacingDisk ]]
349  then
350    : # Let tsrpldisk handle the failure group.
351
352  elif [[ -n $failureGroup ]]
353  then
354    # Validate the user-supplied value.
355    if [[ $failureGroup != ?(-)+([0-9]) ]]
356    then
357      # Invalid integer
358      printErrorMsg 199 $mmcmd $failureGroup
359      return 1
360    fi
361
362    if [[ $failureGroup -ge -1 && $failureGroup -le 4000 ||
363          -n $primaryNsdAdminNode && $failureGroup -eq $defaultFailureGroup ]]
364    then
365      : # The user-specified failure group looks reasonable.
366    else
367      # Invalid failure group range.
368      printErrorMsg 30 $mmcmd
369      return 1
370    fi
371
372  elif [[ -n $primaryNsdAdminNode ]]
373  then
374    # Set the failure group to the server node number + 4000.
375    failureGroup=$defaultFailureGroup
376
377  else
378    # If all else fails, go with negative one.
379    failureGroup="-1"
380  fi  # end of if [[ -n $replacingDisk ]]
381
382  #############################
383  # Storage pool verification
384  #############################
385  # Check the storage pool name if one was specified.
386  if [[ -n $storagePool && $storagePool != "system" ]]
387  then
388    # Check whether the disk is to be used for metadata.
389    if [[ $hasMetaData = 1 || $diskUsage = descOnly ]]
390    then
391      # The disk usage is not compatible with the storage pool.
392      printErrorMsg 239 $mmcmd $diskUsage $storagePool
393      return 1
394    fi
395
396    # Check whether the storage pool name conforms to naming rules.
397    # If it does not, issue an error message and exit with a non-zero rc.
398    checkName poolName 255 "$storagePool"
399    [[ $? -ne 0 ]] && return 1
400  fi
401
402  ##############################################################
403  # Everything seems to be OK.  Generate the output and return.
404  ##############################################################
405  # Build the ts version of the descriptor.
406  tsDiskDesc="$diskName:$driverType:$sectorSize:$failureGroup:"
407  tsDiskDesc="${tsDiskDesc}$hasMetaData:$hasData:$storagePool"
408
409  # Update fields in the SG_DISKS line as necessary.
410  [[ -z $deviceName ]] && deviceName=$NO_DEVICE
411  v[$NODESETID_Field]=$nodesetId
412  v[$DEV_NAME_Field]=$deviceName
413  v[$FAILURE_GROUP_Field]=$failureGroup
414  v[$DISK_USAGE_Field]=$diskUsage
415  v[$DISK_TYPE_Field]=$driverType
416  v[$DISK_STATUS_Field]=$statusString
417  v[$NSD_PRIMARY_NODE_Field]=$primaryNsdAdminNode
418  v[$NSD_BACKUP_NODE_Field]=$backupNsdAdminNode
419  v[$DAEMON_NSD_PRIMARY_Field]=$primaryNsdDaemonNode
420  v[$DAEMON_NSD_BACKUP_Field]=$backupNsdDaemonNode
421  v[$STORAGE_POOL_Field]=$storagePool
422  updatedDiskLine=$(print_newLine)
423
424  # Print the results.
425  print -- "$updatedDiskLine $tsDiskDesc $diskUsage"
426
427  return 0
428
429}  #----- end of function validateAndConvertNsdDescriptor ---------
430
431
432########################################################################
433#
434# Function:  Invoke tspreparedisk to generate an unique identifier
435#            and record it on the disk.  If invoked by mmimportfs,
436#            move the sg descriptor to sector 8 if necessary.
437#
438# Input:     $1 - name of the underlying disk to use
439#            $2 - value of verification flag (-v option of mmcrnsd)
440#            $3 - invoking command
441#            $4 - nsd subtype
442#                   (if "NULL" is passed, createNsd will determine it)
443#
444# Output:    NSD disk type followed by the output from tspreparedisk
445#
446# Returns:   0 - success
447#            non-zero - unexpected error
448#
449########################################################################
450function createNsd  # <diskName> <vflag> <invokingCommand> <nsdSubtype>
451{
452  typeset sourceFile="mmfsfuncs.sh"
453  [[ -n $DEBUG || -n $DEBUGcreateNsd ]] && set -x
454  $mmTRACE_ENTER "$*"
455  typeset diskName=$1
456  typeset vflag=$2
457  typeset invokingCommand=$3
458  typeset nsdSubtype=$4
459
460  typeset device tscmdParms tspreparediskOutput
461  typeset unfenceAttempted=""
462  typeset rc=0
463  typeset ec=0
464
465  if [[ $nsdSubtype = NULL ]]
466  then
467    # Determine the type of the underlying disk.
468    nsdSubtype=$(determineNsdSubtype $diskName)
469    rc=$?
470    if [[ $rc -ne 0 || -z $nsdSubtype ]]
471    then
472      # Print result and return.
473      print error tspreparedisk:0:0:0:0:3901:0:0
474      [[ $rc -eq 0 ]] && rc=1
475      return $rc
476    fi
477  fi  # end of if [[ $nsdSubtype = NULL ]]
478
479  # Ensure the sg descriptor starts in sector 8.
480  if [[ $invokingCommand = mmimportfs ]]
481  then
482    tspreparediskOutput=$($tspreparedisk -m $diskName 2>$errMsg)
483    rc=$?
484
485    # If we fail because this is a fenced-out VSD,
486    # unfence the disk and retry the tspreparedisk.
487    if [[ $rc -eq 50 && $nsdSubtype = vsd ]]
488    then
489      $rm -f $errMsg
490      unfenceVSDdisk $diskName
491      ec=$?
492      unfenceAttempted=yes
493      if [[ $ec -eq 0 ]]
494      then
495        tspreparediskOutput=$($tspreparedisk -m $diskName 2>$errMsg)
496        rc=$?
497      fi
498    fi  # end of if [[ $rc -eq 50 && $nsdSubtype = vsd ]]
499
500    # Check the result from the tspreparedisk command.
501    if [[ $rc -ne 0 || -z $tspreparediskOutput ]]
502    then
503      # Print result and return.
504      [[ -s $errMsg ]] && $cat $errMsg 1>&2
505      $rm -f $errMsg
506      print error tspreparedisk:$rc:0:0:0:3902:0:0
507      [[ $rc -eq 0 ]] && rc=1
508      return $rc
509    fi
510    $rm -f $errMsg
511  fi  # end of if [[ $invokingCommand = mmimportfs ]]
512
513  # Construct the fully-qualified device name.
514  # Note that this is required for the -n and -N options
515  # of tspreparedisk, but not for the -m option.
516  if [[ $diskName = /* ]]
517  then
518    device=$diskName
519  elif [[ $osName = AIX ]]
520  then
521    device=/dev/r$diskName
522  else
523    device=/dev/$diskName
524  fi
525
526  # Determine the parameters to specify on the tspreparedisk command.
527  # If the -v flag on the mmcrnsd command was set to yes, do not
528  # overwrite an existing pvid.  Otherwise, unconditionally generate
529  # a new pvid.
530  if [[ $vflag = yes ]]
531  then
532    tscmdParms="-n $device -t $nsdSubtype"
533  else
534    tscmdParms="-N $device -t $nsdSubtype"
535  fi
536
537  # Invoke tspreparedisk to generate and write a unique pvid on the disk.
538  tspreparediskOutput=$($tspreparedisk $tscmdParms)
539  rc=$?
540
541  # If there is failure because this is a fenced-out VSD,
542  # unfence the disk and retry the tspreparedisk.
543  if [[ $rc -eq 50 && $nsdSubtype = vsd && -z $unfenceAttempted ]]
544  then
545    unfenceVSDdisk $diskName
546    ec=$?
547    if [[ $ec -eq 0 ]]
548    then
549      tspreparediskOutput=$($tspreparedisk $tscmdParms)
550      rc=$?
551    fi
552  fi  # end of if [[ $rc -eq 50 && $nsdSubtype = vsd && -z $unfenceAttempted ]]
553
554  # Output the NSD subtype and the result from tspreparedisk.
555  print $nsdSubtype $tspreparediskOutput
556  return $rc
557
558}  #----- end of function createNsd ----------------------
559
560
561##############################################################################
562#
563# Function:  Invoke tspreparedisk to configure disks for use as quorum disks.
564#
565# Input:     $1 - file with the SG_DISK lines for the disks
566#            $2 - comma-separated list of quorum node numbers
567#            $3 - comma-separated list of quorum node names
568#            $4 - invoking command
569#
570# Output:    None
571#
572# Returns:   0 - success
573#            non-zero - unexpected error
574#
575##############################################################################
576function formatPaxosDisks  # <diskLines> <quorumNodeNumbers>
577                           # <quorumNodeNames> <invokingCommand>
578{
579  typeset sourceFile="mmfsfuncs.sh"
580  [[ -n $DEBUG || -n $DEBUGformatPaxosDisks ]] && set -x
581  $mmTRACE_ENTER "$*"
582  typeset diskLines=$1
583  typeset quorumNodeNumbers=$2
584  typeset quorumNodeNames=$3
585  typeset invokingCommand=$4
586
587  typeset rc=0
588  typeset formatPaxosDisks_rc=0
589  typeset wOpt=""
590  typeset sdrfsLine diskName pvid nsdSubtype fOpt rc2
591  typeset magicWord fsName nodeName invokedNode result
592
593  [[ $invokingCommand = mmaddnode ]] && wOpt="-w"
594
595  # Read the SG_DISK lines and process the disks one by one.
596  $rm -f $errMsg
597  IFS=":"
598  exec 3<&-
599  exec 3< $diskLines
600  while read -u3 sdrfsLine
601  do
602    # Parse the line.
603    set -f ; set -A v -- - $sdrfsLine ; set +f
604    IFS="$IFS_sv"
605    diskName=${v[$DISK_NAME_Field]}
606    pvid=${v[$PVID_Field]}
607    nsdSubtype=${v[$NSD_SUBTYPE_Field]}
608
609    if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]]
610    then
611      fOpt=""
612    else
613      fOpt="-f"
614    fi
615
616    # Loop through the list of nodes, invoking the tspreparedisk command
617    # to format the disk.  We continue looping until we succeed on some node.
618    IFS=","
619    for nodeName in $quorumNodeNames
620    do
621      IFS="$IFS_sv"
622      if [[ $nodeName = $ourNodeName ]]
623      then
624        # Execute the command locally.
625        result=$($mmremote adminCmd tspreparedisk  \
626                    -p $pvid -t $nsdSubtype -q $quorumNodeNumbers $fOpt $wOpt)
627        rc=$?
628        invokedNode=$ourNodeName
629        tspreparediskOutput="$result"
630      else
631        # Check whether the node can be reached.
632        isNodeReachable $nodeName
633        if [[ $? -eq 0 ]]
634        then
635          # Invoke mmdsh to execute the command on the node.
636          result=$($mmdsh -vL $nodeName $mmremote adminCmd tspreparedisk  \
637                      -p $pvid -t $nsdSubtype -q $quorumNodeNumbers $fOpt $wOpt)
638          rc=$?
639          invokedNode=${result%%: *}
640          tspreparediskOutput=${result#* }
641          tspreparediskOutput=${tspreparediskOutput## }
642        else
643          rc=$MM_HostDown
644        fi  # end of if [[ $? -eq 0 ]]
645      fi  # end of if [[ $nodeName = $ourNodeName ]]
646
647      # Parse the result from tspreparedisk.
648      IFS=":"
649      set -f ; set -- $tspreparediskOutput ; set +f
650      magicWord=$1
651      rc2=$2
652      IFS="$IFS_sv"
653
654      # Issue an appropriate message if the node was unable
655      # to execute tspreparedisk successfully.
656      if [[ $rc -ne 0 || $magicWord != tspreparedisk || $rc2 -ne 0 ]]
657      then
658        # Something went wrong with this disk.
659        # Try to make sense of the error.
660        if [[ $rc -eq $MM_HostDown ]]
661        then
662          # The node is not reachable.
663          printErrorMsg 340 $mmcmd $nodeName 2>> $errMsg
664        elif [[ $magicWord = tspreparedisk ]]
665        then
666          # tspreparedisk executed but it was not happy about something.
667          if [[ $rc2 = 1 ]]       # E_PERM
668          then
669            # Permission was denied for disk.
670            printErrorMsg 523 "$invokedNode: $mmcmd" "$diskName" 2>> $errMsg
671          elif [[ $rc2 = 2 ]]     # E_NOENT
672          then
673            # The disk was not found.
674            printErrorMsg 524 "$invokedNode: $mmcmd" "$diskName" 2>> $errMsg
675          elif [[ $rc2 = 5 ]]     # E_IO
676          then
677            # I/O error
678            printErrorMsg 525 "$invokedNode: $mmcmd" "$diskName" 2>> $errMsg
679          elif [[ $rc2 = 19 ]]    # E_NODEV
680          then
681            # A return code of ENODEV was returned for the disk.
682            printErrorMsg 187 $mmcmd $invokedNode "$diskName" 2>> $errMsg
683          elif [[ $rc2 = 50 ]]    # E_NOCONNECT
684          then
685            # The disk is fenced out.
686            printErrorMsg 395 $mmcmd $invokedNode "$diskName" 2>> $errMsg
687          elif [[ $rc2 = 214 ]]   # E_VALIDATE
688          then
689            # Disk validation error.
690            printErrorMsg 539 "$invokedNode: $mmcmd" "$diskName" $rc2 2>>$errMsg
691          elif [[ $rc2 = 221 ]]   # E_BALSPACE
692          then
693            # There is no space in the descriptor for the paxos sectors.
694            printErrorMsg 531 "$invokedNode: $mmcmd" "$diskName" 2>> $errMsg
695          elif [[ $rc2 = 236 ]]   # E_FORMAT_INCOMPAT
696          then
697            # The disk belongs to a back level file system or
698            # it is not in ready state.
699            fsName=$(findFSforDisk "$diskName" $mmsdrfsFile)
700            printErrorMsg 528 "$invokedNode: $mmcmd" "$diskName" $fsName 2>> $errMsg
701          else
702            # Show the result from tspreparedisk.
703            print -u2 "$tspreparediskOutput" 2>> $errMsg
704            # There was an unexpected error from tspreparedisk.
705            printErrorMsg 171 "$invokedNode: $mmcmd"  \
706              "tspreparedisk -p $pvid -t $nsdSubtype -q $quorumNodeNumbers $fOpt $wOpt" $rc2 2>> $errMsg
707          fi  # end of if [[ $rc2 = 1 ]]
708        else
709          # Something is really wrong.  Output error information if any.
710          [[ -n $result ]] && print -u2 "$nodeName: $result" 2>> $errMsg
711        fi  # end of if [[ $magicWord = tspreparedisk ]]
712      fi  # end of if [[ $rc -ne 0 || $magicWord != tspreparedisk || $rc2 -ne 0 ]]
713
714      # Exit the loop if tspreparedisk succeeded.
715      [[ $rc -eq 0 && $magicWord = tspreparedisk && $rc2 -eq 0 ]] && break
716
717      IFS=","  # Change the field separator back to "," for the next iteration.
718    done  # end of for nodeName in $quorumNodeNames
719    IFS="$IFS_sv"
720
721    # If no node was able to run tspreparedisk successfully,
722    # show all of the error messages and set a failure return code.
723    if [[ $rc -ne 0 || $magicWord != tspreparedisk || $rc2 -ne 0 ]]
724    then
725      $cat $errMsg 1>&2
726      # Failed while processing the disk.
727      printErrorMsg 529 $mmcmd "$diskName"
728      formatPaxosDisks_rc=1
729    fi  # end of if [[ $rc -ne 0 || $magicWord != tspreparedisk || $rc2 -ne 0 ]]
730
731    # Reset things needed for the next iteration.
732    $rm -f $errMsg
733    IFS=":"
734
735  done  # end of while read -u3 sdrfsLine
736  IFS="$IFS_sv"
737
738  return $formatPaxosDisks_rc
739
740}  #----- end of function formatPaxosDisks --------------------
741
742
743############################################################################
744#
745# Function:  Send nsd data obtained from the tspreparedisk -s command
746#            (and other sources) for all nsds on this node to stdout.
747#
748# Input:     X flag (optional; if set, it specifies that eXtra information
749#              should be returned in the remarks field)
750#
751# Output:    colon-separated nsd information from the "tspreparedisk -s"
752#              command (and other sources if the X flag was specified)
753#
754# Returns:   0 - success
755#
756############################################################################
757function getLocalNsdData   # [<Xflag>]
758{
759  typeset sourceFile="mmfsfuncs.sh"
760  [[ -n $DEBUG || -n $DEBUGgetLocalNsdData ]] && set -x
761  $mmTRACE_ENTER "$*"
762  typeset Xflag=$1
763  typeset tspreparediskLine nsid deviceName localDevice deviceType vgname
764  typeset vsdDataNeeded=yes
765
766  # Obtain the output of the tspreparedisk -s command.
767  $tspreparedisk -s > $tsOutputFile 2> $errMsg
768
769  # Read and process the output.
770  exec 4<&-
771  exec 4< $tsOutputFile
772  while read -u4 tspreparediskLine
773  do
774    # Parse the tspreparedisk output line.
775    set -f ; set -- $tspreparediskLine ; set +f
776    nsid=$1
777    localDevice=$2
778    deviceType=$3
779
780    # If this is an AIX environment, replace the /dev/r prefix with /dev/.
781    if [[ $osName = AIX && $localDevice = +(/)dev+(/)r* ]]
782    then
783      deviceName=${localDevice##+(/)dev+(/)r}
784      localDevice=/dev/$deviceName
785    fi
786
787    if [[ -z $Xflag ]]
788    then
789      # Here if -m or -M was specified.
790      # If this is not an error line, print the data.
791      [[ $nsid != tspreparedisk* ]] &&  \
792        print "getLocalNsdData:$nsid:$localDevice:$deviceType::" >> $nsdDataFile
793    else
794      # Here if -X was specified.
795      # Obtain information for the remarks field for certain types of disks.
796      remarks=""
797      if [[ $osName = AIX ]]
798      then
799        if [[ $deviceType = vsd ]]
800        then
801          # Obtain VSD information for the remarks field.
802          if [[ $vsdDataNeeded = yes ]]
803          then
804            getVsdRpdNodeData $tmpNodes
805            LC_ALL=C $lsvsd -l > $vsdNamesFile 2>/dev/null
806            LC_ALL=C $vsdatalst -v > $diskfile  2>/dev/null
807            LC_ALL=C $vsdatalst -g > $volGroupFile 2>/dev/null
808            $touch $tmpNodes $vsdNamesFile $diskfile $volGroupFile
809            vsdDataNeeded=no
810          fi
811          remarks=$(obtainVsdInfo $deviceName $tmpNodes $vsdNamesFile $diskfile $volGroupFile)
812        elif [[ $deviceType = lv ]]
813        then
814          # Obtain logical volume information for the remarks field.
815          vgname=$(LC_ALL=C $lslv -L $deviceName 2>/dev/null | $awk '/VOLUME GROUP:/ {print $6}')
816          [[ -z vgname ]] && vgname=unknown
817          remarks="lv=$deviceName,vg=$vgname"
818        fi  # end of if [[ $deviceType = vsd ]]
819      fi  # end of if [[ $osName = AIX ]]
820
821      # If this is not an error line, print the data.
822      [[ $nsid != tspreparedisk* ]] &&  \
823        print "getLocalNsdData:$nsid:$localDevice:$deviceType:$remarks:" >> $nsdDataFile
824    fi    # end of if [[ -z $Xflag ]]
825  done  # end of while read -u4 tspreparediskLine
826
827  # Send the colon-separated output and any error messages to stdout.
828  $touch $nsdDataFile    # Make sure the file exists even if empty.
829  cat $nsdDataFile $errMsg
830  return 0
831
832}  #----- end of function getLocalNsdData ---------------------
833
834
835####################################################################
836#
837# Function:  Find out the local device name for the disk with
838#            the specified pvid.
839#
840# Input:     $1 - pvid of the disk being looked up
841#            $2 - nsd subtype of the disk being looked up
842#
843# Output:    A line with the following ':' separated fields:
844#            - magic word 'getLocalDiskName'
845#            - local disk name
846#            - return code from tspreparedisk -p
847#            - always 0 (used to be return code from tsnsdreset -q)
848#
849# Returns:   0 - success
850#            1 - unexpected error
851#
852####################################################################
853function getLocalDiskName  # <pvid> <nsdSubtype>
854{
855  typeset sourceFile="mmfsfuncs.sh"
856  [[ -n $DEBUG || -n $DEBUGgetLocalDiskName ]] && set -x
857  $mmTRACE_ENTER "$*"
858  typeset pvid=$1
859  typeset nsdSubtype=$2
860
861  typeset tspreparediskOutput magicWord pvid
862  typeset localDiskName=""
863  typeset rc=0
864  typeset rc1=0
865  typeset rc2=0
866
867  # Use the nsd commands to determine the local device name.
868
869  # Find out the local device name.
870  tspreparediskOutput=$($tspreparedisk -p $pvid -t $nsdSubtype 2>$errMsg2)
871  rc=$?
872
873  # Parse the output from the tspreparedisk command.
874  IFS=":"
875  set -f ; set -- $tspreparediskOutput ; set +f
876  magicWord=$1
877  rc1=$2
878  pvid=$3
879  localDiskName=$4
880  IFS="$IFS_sv"
881
882  if [[ $magicWord != tspreparedisk ]]
883  then
884    # Unexpected error.  Print error messages and give up.
885    [[ -s $errMsg2 ]] && $cat $errMsg2 1>&2
886    $rm -f $errMsg2
887    [[ $rc -eq 0 ]] && rc=1
888    printErrorMsg 171  \
889      "getLocalDiskName" "tspreparedisk -p $pvid -t $nsdSubtype" $rc
890    return 1
891  fi
892  $rm -f $errMsg2
893
894  # If this is an AIX environment, replace the /dev/r prefix with /dev/.
895  if [[ $osName = AIX && $localDiskName = +(/)dev+(/)r* ]]
896  then
897    localDiskName=${localDiskName##+(/)dev+(/)r}
898    localDiskName=/dev/$localDiskName
899  fi
900
901  if [[ $rc -eq 0 && -n $localDiskName ]]
902  then
903    # tspreparedisk worked and we have a good answer.
904    print -- "getLocalDiskName:$localDiskName:$rc1:$rc2"
905    return 0
906  fi
907
908  if [[ $MMMODE = single ]]
909  then
910    # If in single mode, there is nothing more to try; give up.
911    print -- "getLocalDiskName:$UNRESOLVED:$rc1:$rc2"
912    return 0
913  fi
914
915  # If we are here, tspreparedisk failed to find out the local disk name.
916  # There may be many reasons for this, one of which is that the disk is
917  # being reserved by some other node and we cannot verify the pvid.
918  # Assuming this is the case, we will look at the nsd map file and will
919  # attempt to determine the mapping from there keeping in mind that the
920  # answer is not 100% guaranteed to be correct anymore.
921
922  # Search the nsd map file for an entry with our pvid.
923  if [[ -s $nsdmap ]]
924  then
925    localDiskName=$($awk ' {   \
926      if ($1 == "'$pvid'") {   \
927        { print $2 }           \
928        { exit 0 }             \
929      }                        \
930    } ' $nsdmap)
931    checkForErrors "awk $nsdmap" $?
932  fi  # end of if [[ -s $nsdmap ]]
933
934  # If no matching pvid found in the hints file, give up.
935  if [[ -z $localDiskName ]]
936  then
937    print -- "getLocalDiskName:$UNRESOLVED:$rc1:$rc2"
938    return 0
939  fi
940
941  # tspreparedisk should have been able to verify the pvid;
942  # most likely this is a different disk.
943  print -- "getLocalDiskName:$UNRESOLVED:$rc1:$rc2"
944
945  return 0
946
947}  #----- end of function getLocalDiskName ---------------
948
949
950#############################################################
951#
952# Function:  Select an unused device minor number.
953#
954# Input:     $1 - list of currently-assigned minor numbers.
955#
956# Output:    A minor number for the /dev entry.
957#
958# Returns:   Zero if successful, non-zero otherwise.
959#
960#############################################################
961function assignDevMinor  # <existingMinorNumbers>
962{
963  typeset sourceFile="mmfsfuncs.sh"
964  [[ -n $DEBUG || -n $DEBUGassignDevMinor ]] && set -x
965  $mmTRACE_ENTER "$*"
966  typeset existingMinorNumbers="$1"
967
968  typeset x devMinor
969  typeset rc=0
970
971  # Set the initial devMinor number.  The first 50 numbers
972  # are reserved for existing file systems that do not play
973  # by the new rules yet.
974  devMinor=$((minMinorNumber + 50))
975
976  # Keep looping until we either find an unused minor number,
977  # or we run out of numbers.
978  while ((devMinor <= maxMinorNumber))
979  do
980    # Scan the currently-assigned minor numbers.
981    for x in $existingMinorNumbers
982    do
983      # If the number that we want is already in use,
984      # get out of the for loop.
985      [[ $x = $devMinor ]] && break
986    done
987
988    # If the number that we want is free, we are done.
989    [[ $x != $devMinor ]] && break
990
991    # No luck so far, try the next number.
992    devMinor=$((devMinor + 1))
993
994  done # end of while ((devMinor <= maxMinorNumber))
995
996  # If the number is out of range, return null and let
997  # mmfsmknod worry about it.  This should never happen
998  # since we do not support more than 32 file systems.
999  if [[ $devMinor -gt $maxMinorNumber ]]
1000  then
1001    rc=1
1002    devMinor=""
1003  fi
1004
1005  # Return the result.
1006  print -- $devMinor
1007  return $rc
1008
1009}  #----- end of function assignDevMinor -----------------
1010
1011
1012#############################################################
1013#
1014# Function:  Find the disk info (pvid, vgname, lvname) that
1015#            corresponds to the raw disk name.
1016#
1017# Input:     $1 - raw disk name (eg: hdisk7, sda2).
1018#
1019# Output:    The disk information:  pvid, vgname, lvname.
1020#
1021# Returns:   Zero if successful, non-zero otherwise.
1022#
1023#############################################################
1024function getRawDiskInfo  # <rawDiskName>
1025{
1026  typeset sourceFile="mmfsfuncs.sh"
1027  [[ -n $DEBUG || -n $DEBUGgetRawDiskInfo ]] && set -x
1028  $mmTRACE_ENTER "$*"
1029  typeset rawDiskName=$1
1030
1031  typeset pvid vgname lvname lspvOutput
1032  integer rc=0
1033
1034  # Find out the disks pvid and local volume group.
1035  lspvOutput=$($lspv | $grep -w $rawDiskName)
1036  rc=$?
1037  set -f ; set -- $lspvOutput ; set +f
1038  pvid=$2
1039  vgname=$3
1040  if [[ $rc -ne 0 || -z $pvid || -z $vgname ]]
1041  then
1042    printErrorMsg 232 $mmcmd $rawDiskName lspv
1043    return $rc
1044  fi
1045
1046  if [[ $vgname != None && $vgname != gpfs ]]
1047  then
1048    # Determine the name of the logical volume that corresponds to this
1049    # volume group.  If there is more than one lv ...?
1050    lvname=$(LC_ALL=C $lsvg -l $vgname 2>/dev/null | $grep mmfs | $awk '{ print $1 }')
1051    rc=$?
1052    if [[ $rc -ne 0 || -z $lvname ]]
1053    then
1054      printErrorMsg 104 "$mmcmd" "lsvg -l $vgname"
1055      return 1
1056    fi
1057  else
1058    # We come here if vgname = None or vgname = gpfs (the latter being
1059    # indicative of an old, no-longer-used nsd for which mmdelnsd was not run).
1060    # Tell the user no disks were found.
1061    printErrorMsg 418 $mmcmd
1062    return 1
1063  fi
1064
1065  print -- $pvid $vgname $lvname
1066  return 0
1067
1068}  #----- end of function getRawDiskInfo -----------------
1069
1070
1071#############################################################
1072#
1073# Function:  Find the VSD name corresponding to the vgname.
1074#
1075# Input:     $1 - vg name
1076#
1077# Output:    The VSD name.
1078#
1079# Returns:   Zero if successful, non-zero otherwise.
1080#
1081#############################################################
1082function getVSDName  # <vgname>
1083{
1084  typeset sourceFile="mmfsfuncs.sh"
1085  [[ -n $DEBUG || -n $DEBUGgetVSDName ]] && set -x
1086  $mmTRACE_ENTER "$*"
1087  typeset vgname=$1
1088
1089  typeset vsdname gvg
1090  integer rc=0
1091
1092  gvg=$($vsdatalst -g | $awk '{ if ($2 == "'"$vgname"'") print $1 }')
1093  if [[ -z $gvg ]]
1094  then
1095    printErrorMsg 232 $mmcmd $vgname "vsdatalst -g"
1096    print -- ""
1097    return 1
1098  else
1099    vsdname=$($vsdatalst -v |  \
1100                $awk '{if ($3 == "'"$gvg"'") print $1}')
1101    rc=$?
1102    if [[ $rc -ne 0 || -z $vsdname ]]
1103    then
1104      printErrorMsg 232 $mmcmd $vgname "vsdatalst -v"
1105      print -- ""
1106      return 1
1107    fi
1108  fi
1109
1110 print -- $vsdname
1111 return 0
1112
1113}  #----- end of function getVSDName ---------------------
1114
1115
1116#############################################################
1117#
1118# Function:  Find the NSD disk name.
1119#
1120# Input:     $1 - rawdisk, lv, or vsdname
1121#
1122# Output:    the NSD disk name
1123#
1124# Returns:   zero if successful, non-zero otherwise
1125#
1126#############################################################
1127function getNSDName  # <rawName>
1128{
1129  typeset sourceFile="mmfsfuncs.sh"
1130  [[ -n $DEBUG || -n $DEBUGgetNSDName ]] && set -x
1131  $mmTRACE_ENTER "$*"
1132  rawName=$1
1133  typeset rc=0
1134
1135  typeset gpfsDiskName tspreparediskOutput pvid
1136
1137  if [[ $osName = AIX ]]
1138  then
1139    rawName="r$rawName"
1140  fi
1141
1142  tspreparediskOutput=$($tspreparedisk -s | $grep -w "/dev/$rawName")
1143  rc=$?
1144
1145  # Parse the output from the tspreparedisk command.
1146  IF=":"
1147  set -f ; set -- $tspreparediskOutput ; set +f
1148  pvid=$1
1149  [[ $rc -ne 0 || -z $pvid ]] && return 1
1150
1151  # Search for the nsd disk name in the mmsdrfs file.
1152  gpfsDiskName=$($awk -F: '                \
1153    /':$SG_DISKS:'/ {                      \
1154      if ($'$PVID_Field' == "'$pvid'") {   \
1155        { print $'$DISK_NAME_Field' }      \
1156        { exit 0 }                         \
1157      }                                    \
1158    }
1159  ' $mmsdrfsFile)
1160
1161  checkForErrors awk $?
1162  if [[ -n $gpfsDiskName ]]
1163  then
1164    print -- $gpfsDiskName
1165    return 0
1166  else
1167    return 1
1168  fi
1169
1170}  #----- end of function getNSDName ---------------------
1171
1172
1173###############################################################
1174#
1175# Function:  Find the GPFS disk name given the raw disk name.
1176#
1177# Input:     $1 - raw disk name (eg: hdisk, sda)
1178#
1179# Output:    the GPFS disk name
1180#
1181# Returns:   zero if successful, non-zero otherwise
1182#
1183###############################################################
1184function getGpfsDiskName   #  <rawDiskName>
1185{
1186  typeset sourceFile="mmfsfuncs.sh"
1187  [[ -n $DEBUG || -n $DEBUGgetGpfsDiskName ]] && set -x
1188  $mmTRACE_ENTER "$*"
1189  typeset rawDiskName=$1
1190
1191  typeset rawDiskInfo pvid vgname lvname vsdname gpfsDiskName
1192
1193  # Check the GPFS cluster type.
1194  [[ -z $MMMODE ]] && determineMode
1195
1196  # Call routine to obtain the name of the NSD.
1197  gpfsDiskName=$(getNSDName $rawDiskName)
1198
1199  # If the NSD was not found and this is a Linux node,
1200  # return with a failure rc; there is nothing more we can do.
1201  [[ -z $gpfsDiskName && $osName = Linux ]] && return 1
1202
1203  # Did we get the name of the NSD?
1204  if [[ -z $gpfsDiskName ]]
1205  then
1206    # We did not get the name of the NSD.
1207    # Check whether this is an AIX logical volume.
1208    rawDiskInfo=$(getRawDiskInfo $rawDiskName)
1209    set -f ; set -- $rawDiskInfo ; set +f
1210    pvid=$1
1211    vgname=$2
1212    lvname=$3
1213
1214    # If we did not find an lv, return with a failing rc;
1215    # the disk is not known.
1216    [[ -z $lvname ]] && return 1
1217
1218    # Check for an NSD name corresponding to the lv.
1219    gpfsDiskName=$(getNSDName $lvname)
1220    if [[ -z $gpfsDiskName ]]
1221    then
1222      # If still no NSD was found, check whether this is a VSD.
1223      vsdname=$(getVSDName $vgname)
1224      if [[ -n $vsdname ]]
1225      then
1226        # Check for an NSD name corresponding to the vsd.
1227        gpfsDiskName=$(getNSDName $vsdname)
1228        [[ -z $gpfsDiskName ]] && return 1
1229      else
1230        # We did not find the NSD.  Return with a failing rc.
1231        return 1
1232      fi
1233    fi
1234  fi  # end of if [[ -z $gpfsDiskName ]]
1235
1236  # Output the GPFS disk name and return.
1237  print -- $gpfsDiskName
1238  return 0
1239
1240}  #----- end of function getGpfsDiskName -----------------------
1241
1242
1243###########################################################################
1244#
1245# Function:  Reset (i.e., set to the null string) the status field
1246#            of SG_DISKS lines for the specified filesystem if their
1247#            disk status value matches the passed status string,
1248#            thus causing the disk to be reported to the GPFS daemon
1249#            by future invocations of the getEFOptions routine.
1250#
1251#            This routine is called after a ts disk command has completed
1252#            successfully.
1253#
1254# Input:     $1 - file system name
1255#            $2 - passed sdrfs file
1256#            $3 - 1st status string used to identify SG_DISK lines
1257#                   whose disk status fields need to be reset;
1258#                   the only acceptable values are "mmadd" and "mmdel"
1259#            $4 - optional 2nd status string used to identify SG_DISK
1260#                   lines whose disk status fields need to be reset;
1261#                   if specified, the only acceptable value is "mmdel";
1262#                   this option is used by mmrpldisk which does both
1263#                   an add and a delete
1264#
1265# Output:    The sdrfs file has been updated (the DISK_STATUS field
1266#              of any SG_DISKS line for the specified filesystem is
1267#              reset if the disk status matches the passed values)
1268#
1269# Returns:   0 - the passed sdrfs file was successfully updated
1270#
1271###########################################################################
1272function resetDiskStatus  # <fsname> <sdrfsFile> <status1> [<status2>]
1273{
1274  typeset sourceFile="mmfsfuncs.sh"
1275  [[ -n $DEBUG || -n $DEBUGresetDiskStatus ]] && set -x
1276  $mmTRACE_ENTER "$*"
1277
1278  typeset fsname=$1
1279  typeset sdrfsFile=$2
1280  typeset status1=$3
1281  typeset status2=$4
1282
1283  typeset oddState
1284  typeset outfile=${sdrfs}tmp
1285
1286  $rm -f $outfile
1287
1288  oddState=$($awk -F:  '                                                          \
1289    BEGIN {                                                                       \
1290      { oddstate = "no" }                                                         \
1291      { c = ":" }                                                                 \
1292    }                                                                             \
1293    # If this is the global header line, increment the gen number.                \
1294    /^'$GLOBAL_ID:$VERSION_LINE:'/ {                                              \
1295      { $'$SDRFS_GENNUM_Field' = $'$SDRFS_GENNUM_Field' + 1 }                     \
1296      { print  $1":" $2":" $3":" $4":" $5":" $6":" $7":" $8":" $9":"$10":"        \
1297              $11":"$12":"$13":"$14":"$15":"$16":"$17":"$18":"$19":"$20":"        \
1298              $21":"$22":"$23":"$24":"$25":"$26":"$27":" >> "'$outfile'" }        \
1299      { next }                                                                    \
1300    }                                                                             \
1301    # Save the SG_HEADR line for the specified filesystem as two                  \
1302    # strings - the parts before and after ODD_STATE_Field ($6).                  \
1303    /':$SG_HEADR:$fsname:'/ {                                                     \
1304      { sgh1 =  $1 c $2 c  $3 c  $4 c  $5 }                                       \
1305      { sgh2 =  $7 c $8 c  $9 c $10 c $11 c $12 c $13 c $14 c $15 c $16 c $17 c } \
1306      { sgh2 = sgh2 $18 c $19 c $20 c $21 c $22 c $23 c $24 c $25 c $26 c $27 c } \
1307      { next }                                                                    \
1308    }                                                                             \
1309    # Check for SG_DISKS lines for the specified filesystem.                      \
1310    /':$SG_DISKS:$fsname:'/ {                                                     \
1311      # Does the disk status value match the first passed value?                  \
1312      if ( $'$DISK_STATUS_Field' == "'$status1'" ) {                              \
1313        # The disk status value matches.  Process the line.                       \
1314        if ( "'$status1'" == "mmadd" ) {                                          \
1315          # For mmadd, we simply reset the disk status field.                     \
1316          { $'$DISK_STATUS_Field' = "" }                                          \
1317          { print  $1":" $2":" $3":" $4":" $5":" $6":" $7":" $8":" $9":"$10":"    \
1318                  $11":"$12":"$13":"$14":"$15":"$16":"$17":"$18":"$19":"$20":"    \
1319                  $21":"$22":"$23":"$24":"$25":"$26":"$27":" >> "'$outfile'" }    \
1320        } else {                                                                  \
1321          if ( "'$status1'" == "mmdel" ) {                                        \
1322            # For mmdel, we change the disk into a free disk                      \
1323            # and reset the disk status field.                                    \
1324            { $'$NODESETID_Field' = "'$FREE_DISK'" }                              \
1325            { $'$DEV_NAME_Field' = "'$NO_DEVICE'" }                               \
1326            { $'$LINE_NUMBER_Field' = "0" }                                       \
1327            { $'$DISK_STATUS_Field' = "" }                                        \
1328            { print  $1":" $2":" $3":" $4":" $5":" $6":" $7":" $8":" $9":"$10":"  \
1329                    $11":"$12":"$13":"$14":"$15":"$16":"$17":"$18":"$19":"$20":"  \
1330                    $21":"$22":"$23":"$24":"$25":"$26":"$27":" >> "'$outfile'" }  \
1331          }                                                                       \
1332        }                                                                         \
1333        { next }                                                                  \
1334      } else {                                                                    \
1335        # Does the disk status value match a second passed value of mmdel?        \
1336        if ( "'$status2'" == "mmdel" && $'$DISK_STATUS_Field' == "'$status2'" ) { \
1337          # The disk status value matches and is mmdel.                           \
1338          # We change the disk into a free disk and reset the status field.       \
1339          { $'$NODESETID_Field' = "'$FREE_DISK'" }                                \
1340          { $'$DEV_NAME_Field' = "'$NO_DEVICE'" }                                 \
1341          { $'$LINE_NUMBER_Field' = "0" }                                         \
1342          { $'$DISK_STATUS_Field' = "" }                                          \
1343          { print  $1":" $2":" $3":" $4":" $5":" $6":" $7":" $8":" $9":"$10":"    \
1344                  $11":"$12":"$13":"$14":"$15":"$16":"$17":"$18":"$19":"$20":"    \
1345                  $21":"$22":"$23":"$24":"$25":"$26":"$27":" >> "'$outfile'" }    \
1346          { next }                                                                \
1347        } else {                                                                  \
1348          # The disk status value does not match anything.                        \
1349          # Echo the line as is and check whether the disk is in an odd state.    \
1350          { print $0 >> "'$outfile'" }                                            \
1351          if ( $'$DISK_STATUS_Field' != "" &&                                     \
1352               $'$DISK_STATUS_Field' != "ready" ) {                               \
1353            { oddstate = "yes" }                                                  \
1354          }                                                                       \
1355          { next }                                                                \
1356        }                                                                         \
1357      }                                                                           \
1358    }                                                                             \
1359    # All other lines are echoed without change.                                  \
1360    { print $0 >> "'$outfile'" }                                                  \
1361    END {                                                                         \
1362      { print sgh1 ":" oddstate ":" sgh2 >> "'$outfile'" }                        \
1363    }                                                                             \
1364  ' $sdrfsFile)
1365  checkForErrors awk $?
1366
1367  # Print a message for the user if any disks are in an odd state.
1368  [[ $oddState = yes ]] && printErrorMsg 103 $mmcmd $fsname $fsname
1369
1370  # Sort the updated version of the sdrfs file.
1371  LC_ALL=C $SORT_MMSDRFS $outfile -o $outfile
1372  checkForErrors "sorting $outfile" $?
1373
1374  # The file was updated successfully.  Copy it to the input file.
1375  $mv $outfile $sdrfsFile
1376  checkForErrors "resetDiskStatus:  mv $outfile $sdrfsFile " $?
1377
1378  return 0
1379
1380}  #----- end of function resetDiskStatus -----------------------
1381
1382
1383##########################################################################
1384#
1385# Function:  Compare the daemon's list of disks for the file system
1386#            with that contained in the passed sdrfs file.
1387#            If they disagree, change the sdrfs file to agree
1388#            with the information returned by the daemon.
1389#            If any of the disks of the file system are in an
1390#            "odd state", the "odd state" flag is set to "yes"
1391#            in the SG_HEADR line for the file system (otherwise
1392#            it is set to "no").
1393#
1394# Input:     $1 - file system name
1395#            $2 - passed sdrfs file
1396#
1397# Output:    The SG_DISKS lines in the sdrfs file for the specified
1398#              file system now agree with the daemon's view of the disks.
1399#
1400# Returns:   0 - the passed sdrfs file now agrees with the daemon
1401#                  for the disks in the specified file system
1402#            Any other return code indicates an unexpected error.
1403#
1404##########################################################################
1405function reconcileSdrfsWithDaemon  # <fsname> <sdrfsFile>
1406{
1407  typeset sourceFile="mmfsfuncs.sh"
1408  [[ -n $DEBUG || -n $DEBUGreconcileSdrfsWithDaemon ]] && set -x
1409  $mmTRACE_ENTER "$*"
1410
1411  typeset fsname=$1
1412  typeset sdrfsFile=$2
1413
1414  typeset mmlsdiskLine sdrfsLine nodesetId diskName sgh1 sgh2
1415  typeset failureGroup holdsMetadata holdsData diskStatus
1416  typeset oddState="no"
1417  typeset rc=0
1418  integer nodeCount=0
1419  integer seqNo=0
1420
1421  # Print message:  "Verifying file system configuration information ..."
1422  printInfoMsg 473
1423
1424  # Determine the nodeset to which this filesystem belongs.
1425  nodesetId=$($awk -F: '                           \
1426    /':$SG_HEADR:'/ {                              \
1427      if ( $'$DEV_NAME_Field' == "'$fsname'" ) {   \
1428        {print $'$NODESETID_Field'}                \
1429        { exit 0 }                                 \
1430      }                                            \
1431    }                                              \
1432  ' $sdrfsFile)
1433  checkForErrors awk $?
1434
1435  # Obtain the daemon's list of disks for the filesystem.
1436  # If the nodeset to which this node belongs is the same as the nodeset
1437  # in which the file system resides, invoke the command directly.
1438  if [[ $nsId = $nodesetId ]]
1439  then
1440    ${mmcmdDir}/${links}/mmlsdisk $fsname >$tmpfile2 2>$errMsg
1441    rc=$(remapRC $?)
1442
1443    # If the command failed in a way that a remote invocation will not
1444    # make a difference, display any error messages and get out.
1445    if [[ $rc -ne $MM_DaemonDown &&
1446          $rc -ne $MM_QuorumWait &&
1447          $rc -ne 0              ]]
1448    then
1449      [[ -s $errMsg ]] && $cat $errMsg 1>&2
1450      $rm -f $errMsg
1451      if [[ $rc -eq $MM_ConnectionReset ]]
1452      then
1453        # An internode connection was reset.
1454        printErrorMsg 257 $mmcmd
1455      fi
1456      return $rc
1457    fi
1458  else
1459    # Set rc to a non-zero value so we will try the mmlsdisk cmd remotely.
1460    rc=$MM_DaemonDown
1461  fi
1462  $rm -f $errMsg
1463
1464  # If the mmlsdisk call has not succeeded yet,
1465  # issue the mmlsdisk command on a remote node.
1466  if [[ $rc -ne 0 ]]
1467  then
1468    # Create a file with the reliable names that form
1469    # the nodeset to which the file system belongs.
1470    nodeCount=$(getNodeFile $REL_HOSTNAME_Field $nodesetId $sdrfsFile $nodefile)
1471    if [[ $nodeCount -eq 0 ]]
1472    then
1473      # The nodeset is empty; there is nobody to run the command.
1474      printErrorMsg 171 $mmcmd "getNodeFile (nodeCount=0)" 1
1475      return 1
1476    fi
1477
1478    # Try the nodes one by one until a node is able to execute the command.
1479    preferredNode=0   # We have no idea where to go first; let mmcommon decide.
1480    $mmcommon linkCommand $preferredNode $nodefile  \
1481                                mmlsdisk $fsname >$tmpfile2 2>$errMsg
1482    rc=$?
1483    if [[ $rc -ne 0 ]]
1484    then
1485      [[ -s $errMsg ]] && $cat $errMsg 1>&2
1486      $rm -f $errMsg
1487      if [[ $rc -eq $MM_ConnectionReset ]]
1488      then
1489        # An internode connection was reset.
1490        printErrorMsg 257 $mmcmd
1491      fi
1492      return $rc
1493    fi
1494  fi
1495  $rm -f $errMsg
1496
1497  # Remove the header lines from the mmlsdisk output.
1498  $tail -n +4 $tmpfile2 > $tmpfile
1499  checkForErrors "tail -n +4 $tmpfile2 $tmpfile" $?
1500
1501  # One more sanity check before we proceed.
1502  if [[ ! -s $tmpfile ]]
1503  then
1504    printErrorMsg 171 reconcileSdrfsWithDaemon "tslsdisk - missing disk information" 1
1505    return 1
1506  fi
1507
1508
1509  ##########################################################################
1510  # Go through the passed sdrfs file.  Increment the generation number.
1511  # Make any needed changes to SG_DISKS lines for the specified filesystem.
1512  ##########################################################################
1513  # Delete the temporary file that will be created.
1514  $rm -f $sdrfs
1515
1516  IFS=":"           # Change the field separator to ':'.
1517  exec 3<&-
1518  exec 3< $sdrfsFile
1519  while read -u3 sdrfsLine
1520  do
1521    # Parse the line.
1522    set -f ; set -A v -- - $sdrfsLine ; set +f
1523
1524    IFS="$IFS_sv"
1525    printLine=true
1526
1527    # Selectively alter some of the fields in the line.
1528    case ${v[$LINE_TYPE_Field]} in
1529
1530      $VERSION_LINE )  # This is the global header line.
1531        # Increment the generation number
1532        newGenNumber=${v[$SDRFS_GENNUM_Field]}+1
1533        v[$SDRFS_GENNUM_Field]=$newGenNumber
1534        ;;
1535
1536      $SG_HEADR )  # This is the header line for some file system.
1537        # If this is the header for the specified file system,
1538        # save the line's contents into two strings that will be used
1539        # later in creating the SG_HEADR line.  We can't create the
1540        # line now because we don't know how to set the "odd state"
1541        # field for the file system yet.
1542        if [[ ${v[$DEV_NAME_Field]} = $fsname ]]
1543        then
1544          printLine=false
1545          sgh1=${v[1]}:${v[2]}:${v[3]}:${v[4]}:${v[5]}
1546          sgh2=${v[7]}:${v[8]}:${v[9]}:${v[10]}:${v[11]}:${v[12]}:${v[13]}
1547          sgh2=$sgh2:${v[14]}:${v[15]}:${v[16]}:${v[17]}:${v[18]}:${v[19]}
1548          sgh2=$sgh2:${v[20]}:${v[21]}:${v[22]}:${v[23]}:${v[24]}
1549        fi
1550        ;;
1551
1552      $SG_DISKS )  # This line describes a disk.
1553        # If this disk belongs to the file system or is a free disk,
1554        # make the SG_DISKS line agree with the daemon's data about the disk.
1555        if [[ ${v[$DEV_NAME_Field]} = $fsname  ||
1556              ${v[$NODESETID_Field]} = $FREE_DISK ]]
1557        then
1558          # Locate the line for this disk in the mmlsdisk output file.
1559          $rm -f $tmpfile2
1560          mmlsdiskLine=$($awk '                                           \
1561            # If the line is for our disk, output it to $mmlsdiskLine     \
1562            # but do not append it to tmpfile2.                           \
1563            $1 == "'${v[$DISK_NAME_Field]}'" {                            \
1564              { print $0 }                                                \
1565              { next }                                                    \
1566            }                                                             \
1567            # If the line is for some other disk, append it to tmpfile2.  \
1568            { print $0 >> "'$tmpfile2'" }                                 \
1569          ' $tmpfile)
1570          checkForErrors awk $?
1571
1572          # Prepare the mmlsdisk output file for the next iteration.
1573          # It will contain all of its prior lines except the line
1574          # for the disk that is currently being processed.
1575          $touch $tmpfile2   # Make sure the file exists even if empty.
1576          $mv $tmpfile2 $tmpfile
1577          checkForErrors "mv $tmpfile2 $tmpfile" $?
1578
1579          if [[ -z $mmlsdiskLine ]]
1580          then
1581            # The daemon doesn't know about this disk.
1582            # If the SG_DISKS line indicates the disk belongs to the
1583            # filesystem, change the SG_DISKS line into a free disk line.
1584            if [[ ${v[$DEV_NAME_Field]} = $fsname ]]
1585            then
1586              v[$NODESETID_Field]=$FREE_DISK
1587              v[$DEV_NAME_Field]=$NO_DEVICE
1588              v[$LINE_NUMBER_Field]=0
1589              v[$EXCLUDE_Field]=$includedDisk
1590              v[$DISK_STATUS_Field]=""
1591            fi
1592          else
1593            # The daemon says this disk is part of the filesystem.
1594            # Update the SG_DISKS line fields with the data from
1595            # mmlsdisk so that it is current.
1596            set -f ; set -- $mmlsdiskLine ; set +f
1597            failureGroup=$4
1598            holdsMetadata=$5
1599            holdsData=$6
1600            diskStatus=$7
1601            v[$FAILURE_GROUP_Field]=$failureGroup
1602            if [[ $holdsData = yes ]]
1603            then
1604              if [[ $holdsMetadata = yes ]]
1605              then
1606                v[$DISK_USAGE_Field]=dataAndMetadata
1607              else
1608                v[$DISK_USAGE_Field]=dataOnly
1609              fi
1610            else
1611              if [[ $holdsMetadata = yes ]]
1612              then
1613                v[$DISK_USAGE_Field]=metadataOnly
1614              else
1615                v[$DISK_USAGE_Field]=descOnly
1616              fi
1617            fi
1618            [[ $diskStatus = allocmap* ||
1619               $diskStatus = being*    ||
1620               $diskStatus = removing* ]] && diskStatus=$diskStatus$8
1621            v[$DISK_STATUS_Field]=$diskStatus
1622            [[ $diskStatus != ready && $diskStatus != "" ]] && oddState="yes"
1623
1624            # If the disk is listed as a free disk, change the SG_DISKS
1625            # line to indicate that the disk is part of the filesystem.
1626            if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]]
1627            then
1628              v[$NODESETID_Field]=$nodesetId
1629              v[$DEV_NAME_Field]=$fsname
1630            fi
1631
1632            # Update the sequence number.
1633            seqNo=seqNo+1
1634            v[$LINE_NUMBER_Field]=$seqNo
1635          fi  # end of if [[ -z $mmlsdiskLine ]]
1636        fi  # end of if [[ disk belongs to filesystem or disk is a free disk ]]
1637        ;;
1638
1639      * )  # Pass all lines for other nodesets without a change.
1640        ;;
1641
1642    esac  # end Change some of the fields
1643
1644    # Build and write the line to the new sdrfs file.
1645    if [[ $printLine = true ]]
1646    then
1647      print_newLine >> $sdrfs
1648      checkForErrors "writing to file $sdrfs" $?
1649    fi
1650
1651    IFS=":"  # Change the separator back to ":" for the next iteration.
1652
1653  done  # end while read -u3 sdrfsLine
1654
1655  IFS="$IFS_sv"  # Restore the default IFS settings.
1656
1657  # Issue informational error messages for any active disks
1658  # reported by the daemon but not found in the sdrfs file.
1659  if [[ -s $tmpfile ]]
1660  then
1661    $rm -f $tmpfile2
1662    exec 3<&-
1663    exec 3< $tmpfile
1664    while read -u3 mmlsdiskLine
1665    do
1666      # Parse the line.
1667      set -f ; set -- $mmlsdiskLine ; set +f
1668      diskStatus=$7
1669      if [[ $diskStatus = "ready" ]]
1670      then
1671        print -- $mmlsdiskLine >> $tmpfile2
1672      else
1673        oddState=yes  # Set flag to let caller know he has odd-state disks.
1674      fi
1675    done  # end of while read -u3 mmlsdiskLine
1676    if [[ -s $tmpfile2 ]]
1677    then
1678      # Active disks are missing from the GPFS configuration data.
1679      printErrorMsg 102 $mmcmd
1680      $cat $tmpfile2 1>&2
1681      return 1
1682    fi
1683  fi  # end of if [[ -s $tmpfile ]]
1684
1685  # Create/store the SG_HEADER line for the file system in the sdrfs file,
1686  # using the odd state flag that was set if any of the disks in the
1687  # file system were in an odd state.
1688  print -- "$sgh1:$oddState:$sgh2" >> $sdrfs
1689  checkForErrors "writing to file $sdrfs" $?
1690
1691  # Print a message for the user if any disks are in an odd state.
1692  [[ $oddState = yes ]] && printErrorMsg 266 $mmcmd $fsname
1693
1694  # Sort the reconciled version of the mmsdrfs file.
1695  LC_ALL=C $SORT_MMSDRFS $sdrfs -o $sdrfs
1696  checkForErrors "sorting $sdrfs" $?
1697
1698  # Everything seems to have gone ok so far.
1699  # Rename the file so that the caller can find it.
1700  $mv $sdrfs $sdrfsFile
1701  checkForErrors "mv $sdrfs $sdrfsFile" $?
1702
1703  # Return to the caller.
1704  return 0
1705
1706}  #----- end of function reconcileSdrfsWithDaemon --------------
1707
Note: See TracBrowser for help on using the repository browser.