#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # bos72V src/bos/usr/bin/mkszfile/mkszfile.sh 1.42.17.24 # # Licensed Materials - Property of IBM # # COPYRIGHT International Business Machines Corp. 1989,2020 # All Rights Reserved # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # IBM_PROLOG_END_TAG # @(#)801.42.17.24 src/bos/usr/bin/mkszfile/mkszfile.sh, cmdbsys, bos72V, v2020_34A8 8/17/20 09:07:00 # # COMPONENT_NAME: (CMDBSYS) # # FUNCTIONS: mkszfile.sh # # ORIGINS: 27 # # (C) COPYRIGHT International Business Machines Corp. 1989, 1997 # All Rights Reserved # Licensed Materials - Property of IBM # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # ## [End of PROLOG] # FILE NAME: mkszfile # NOTE: mkvgdata and mkwpardata are "symbolic" links to mkszfile command. # # FILE DESCRIPTION: High-level shell command for creating the Volume # Group(VG) or Workload Partition (WPAR) Data file. # This file captures the Volume Group characteristics; the Physical # Volumes (and sizes) in the VG, # all the characteristics of the non-jfs Logical Volumes and MOUNTED # Filesystems (jfs Logical Volumes) associate with the VG or WPAR. # This will exclude NFS, CD-ROM, and other "special" file systems. # If the Volume Group is the rootvg, then the System LANG environment # variable is also captured. # Specifying the "-X" flag, will cause mkszfile to expand the /tmp # file system if needed for work space. # Specifying the "-m" flag, will cause mkszfile to generate "maps" of # the physical layout of the physical partitions used by each Logical # Volume. # Mkszfile will determine if there is sufficient work space available # in the file systems for the image data file and logical volume map # file(s) and also (for rootvg) will determine if enough work space is # available in /tmp to generate a Boot image. # For user Volume Groups, the image data file and map file(s) are all # created in the /tmp filesystem, in Directory /tmp/vgdata// # For the rootvg Volume Group, the image data file is placed in the # / filesystem and map file(s) are created in the /tmp/vgdata/rootvg/ # directory. # For workload partitions, the image data file and map file(s) are # all created in the /tmp filesystem, in directory /tmp/wpardata/. # # INPUT FLAGS: # -X Expand /tmp if needed. # -m Generate Physical Partition Location Data # -G Global only. Excludes WPAR file systems (mkszfile only) # -N Mounts filesystems in WPARS in the Defined state # VGname Name of VG to generate data on (mkvgdata only) # WPARName Name of WPAR to generate data on (mkwpardata only) # NOTE: the -f flag for the mkszfile command is no longer used, for # compatibility to existing scripts, the -f flag will be # excepted from the commandline but no action will be taken # and no error will be returned. # # OUTPUT: # Error messages (Standard Error) # Image Data file (/image.data for rootvg or # /tmp/vgdata//.data for user VGs or # /tmp/wpardata//image.data for WPARs) # Map Files in /tmp/vgdata//.map or # /tmp/wpardata//.map for WPARs # # RETURN VALUE DESCRIPTION: # 0 Successful # non-zero Unsuccessful # # EXTERNAL PROCEDURES CALLED: lsvg, lslv, lsjfs, lsjfs2, df, bootinfo # bosboot # # GLOBAL VARIABLES: none # ########################## Function Declarations ######################### ############################## canonical ##################################### # # NAME: canonical() # # # DESCRIPTION: output the pathname in canonical form - rebased to the # root directory for the entity being backed up. This is # only of interest for mkwpardata # # INPUT: # $1 = pathname # # OUTPUT: # Rebased pathname # ########## canonical () { fn=$1 if [ "$NAME" != "mkwpardata" ] then echo $fn else if [ "$fn" = "$WPAR_BASE" ] then echo / else echo $fn | ${sed} "s:$WPAR_BASE::" fi fi } ############################## cleanup_m ##################################### # # NAME: cleanup_m() # # # DESCRIPTION: unset traps, issue error message and exit w/ an error code # # INPUT: # $1 = exit code # $2 = error message if not null # # OUTPUT: # Error messages (Standard Error) # # RETURN VALUE DESCRIPTION: exits with a return code of $1 # NOTE: This function will not return (i.e., it will exit the entire # script with exit value of $1) ########## cleanup_m () { ec=$1 error=$2 [ -n "$PID" ] && kill $PID >/dev/null 2>&1 [[ "$ec" != "0" ]] && echo case "$ec" in "$USAGE_SZ") # mkszfile usage error error="`${dspmsg} -s $MSGSET $MSGCAT 37 ' Usage: %s [-X] [-d directory] [-m] [-G | -N] [-x filename]\n\n\ -X\tExpand /tmp if needed.\n\ -d directory\tDirectory to contain image.data file.\n\ -m\tGenerate Physical Partition maps.\n\ -G\tExcludes file systems for WPARS in the image.data file.\n\ -N\tIncludes file systems for WPARS in the Defined state in the image.data file.\n\ -x filename\tExcludes file systems listed in file.\n\n ' $NAME`" 1>&2 ;; "$USAGE_VG" | "$INVALID_VG") # mkvgdata usage error if [ "$ec" = "$INVALID_VG" ] then ${dspmsg} -s 1 $MSGCAT 6 \ "0512-009 %s: Invalid or missing Volume Group Name.\n\n" $NAME 1>&2 fi error="`${dspmsg} -s $MSGSET $MSGCAT 40 ' Usage: %s [-X] [-m] [-x filename] vgname\n -X\tExpand /tmp if needed.\n\ -m\tGenerate Physical Partition maps.\n\ -x filename\tExcludes file systems listed in file.\n\ vgname\tName of volume group to backup.\n\n' $NAME`" 1>&2 ;; "$FILE_EC") # Error creating a file or directory error="`${dspmsg} -s $MSGSET $MSGCAT 22 \ '0512-022 %s: An Error occurred creating the Image Data File or the Physical Partition Map Files. Make sure you have write permission to the /tmp and / directories.\n\n' $NAME`" ;; "$USAGE_WP" | "$INVALID_WPAR") # mkvgdata usage error if [ "$ec" = "$INVALID_WPAR" ] then ${dspmsg} -s 1 $MSGCAT 72 \ "0512-065 %s: Invalid or missing Workload Partition Name.\n\n" $NAME 1>&2 fi error="`${dspmsg} -s $MSGSET $MSGCAT 32 ' Usage: %s [-X] [-m] wparName\n\n\ -X\t\tExpand /tmp if needed.\n\ -m\t\tGenerate Physical Partition maps\n\ wparName\tName of workload partition to backup.\n\n' $NAME`" 1>&2 ;; *) ;; # Error Message Passed in, in $2 esac # Cleanup locks and unmount file systems mounted by mkwpardata if [ $NAME = "mkwpardata" ] && [ "$ec" != "$USAGE_WP" ] && \ [ "$ec" != "$INVALID_WPAR" ] && [ "$ec" != "$LOCK_EC" ] && \ [ "$ec" != "$INSIDE_WPAR" ] then cd / # If any filesystems were mounted by this process, unmount them in # reverse order. typeset i=${#DEVS_MOUNTED[*]} while [[ $i -gt 0 ]]; do i=$((i-1)) unmount_dev ${DEVS_MOUNTED[$i]} done fi # Remove $WORKDIR, if any, created by init_baselib while using mkwpardata if [ $NAME = "mkwpardata" ] && [ -n "$WORKDIR" ] then rm -rf "$WORKDIR" > /dev/null 2>&1 fi ### Unmount filesysms of WPARS in the Defined State ###### if [ $NNFLAG = "yes" ] then unmount_wpar_fs fi [[ "$ec" != "0" ]] && echo "\n${error}\n" trap '' 1 2 15 exit "$ec" } ########################################################## fail_if_wpar () { # Check to make sure that this is running in the # global environment or in the rootvg wpar. if [[ "$WPARID" != "0" ]]; then if [[ "$NAME" = "mkwpardata" ]]; then cleanup_m "$INSIDE_WPAR" \ "`${dspmsg} -s 1 wpars.cat 484 \ '%s: 0960-540 Operation is not permitted in a workload partition.' $NAME`" fi ${lsvg} rootvg >/dev/null 2>&1 if [[ $? -ne 0 ]] && [[ "$NAME" = "mkszfile" ]]; then cleanup_m "$INSIDE_WPAR" \ "`${dspmsg} -s 1 wpars.cat 550 \ '%s: 0960-612 Operation is not permitted in a workload partition with no rootvg.' $NAME`" fi TMP_OUT=$(${lsvg} 2>/dev/null) if [[ -z $TMP_OUT ]]; then cleanup_m "$INSIDE_WPAR" \ "`${dspmsg} -s 1 wpars.cat 551 \ '%s: 0960-613 Operation is not permitted in a workload partition with no volume group.' $NAME`" fi fi } ########################### getoptions ################################## # # NAME: getoptions() # # DESCRIPTION: parse the commandline arguements, check prerequsites: usage # # INPUT: # $* = the commandline arguements # # OUTPUT: # sets variables FORCE and MAPS # # RETURN VALUE DESCRIPTION: # exits on error or # returns successful to program ########## getoptions() { if [ $NAME = "mkszfile" ] then set -- `${getopt} Xd:fmGNx: $*` # mkszfile options elif [ $NAME = "mkvgdata" ] then set -- `${getopt} Xmx: $*` # mkvgdata options else set -- `${getopt} Xm $*` # mkwpardata options fi if [ "$1" == "" ] then cleanup_m "$USAGE_EC" "" fi while [ $1 != -- ] ## Parse flag arguements do case $1 in "-X") XXFLAG="-X" ;; #Expand /tmp if needed "-d") IMG_DIR=$2 # Alternate output directory shift;; "-f") ;; ## No-op, no error - continue "-m") MAPS="yes" ;; "-N") NNFLAG="yes" ;; "-G") XWPARFLAG="yes" ;; "-x") XFSLIST=$2 # File system exclusion list shift;; *) cleanup_m "$USAGE_EC" "";; esac shift done if [[ $NNFLAG = "yes" && "$XWPARFLAG" = "yes" ]] then cleanup_m "$USAGE_EC" fi if [[ -n "$IMG_DIR" ]] && ( [[ ! -d "$IMG_DIR" ]] || [[ ! -w "$IMG_DIR" ]] ) then cleanup_m "$INVALID_DIR" "`${dspmsg} -s $MSGSET $MSGCAT 38 '0512-071 %s: Cannot create %s.\n' $NAME ${IMG_DIR}/image.data`" fi if [[ -n "$XFSLIST" ]] && [[ ! -f "$XFSLIST" ]] then cleanup_m "$INVALID_FILE" "`${dspmsg} -s $MSGSET $MSGCAT 39 '0512-072 %s: Cannot access %s.\n' $NAME ${XFSLIST}`" fi if [ $NAME = "mkszfile" ] then VG="rootvg" elif [ $NAME = "mkwpardata" ] then set `${getopt} $*` #Get Name of WPAR to Backup. WPAR=$1 [ "$WPAR" = "" ] && cleanup_m "$INVALID_WPAR" "" # valid WPAR name? [[ `${lswpar} -qca type $WPAR 2>/dev/null` != 'S' ]] && \ cleanup_m "$INVALID_WPAR" "" WPAR_BASE=`${lswpar} -qca directory $WPAR` # Load WPAR and install shell utilities . /usr/lib/wpars/libcor_sh || return 1 init_baselib `basename $0` || return 1 cor_init_vars export GLOBALCMD="mkwpardata" # GLOBALCMD is used by wpar lock facility mount_wpar_fs else set `${getopt} $*` #Get VG Name of VG to Backup. VG=$1 [ "$VG" = "" ] && cleanup_m "$INVALID_VG" "" # valid VG name? ${lsvg} $VG >/dev/null 2>&1 [ $? -ne 0 ] && cleanup_m "$INVALID_VG" "" fi } ########################### mk_mapfile ################################## # # NAME: mk_mapfile() # # DESCRIPTION: Creates the map files # # INPUT: # $1 = lv_name (i.e. hd1) # # OUTPUT: # map files created for the lv in the $DATA_DIR directory # map file name is $LV_NAME.map # # RETURN VALUE DESCRIPTION: # returns sucessful mk_mapfile() { LV_NAME=$1 ${rm} -f $DATA_DIR/$LV_NAME.map # remove any old map data set -- `LC_ALL=C ${lslv} -m $LV_NAME | ${grep} "^0001"` CP1=$2 # 1st copy of LV CP2=$4 # 2nd copy of LV (mirror) CP3=$6 # 3rd copy of LV (2nd mirror) [ -n "$CP1" ] && LC_ALL=C ${lslv} -m $LV_NAME | ${tail} +3l | ${awk} '{print $3 ":" $2}' > $DATA_DIR/$LV_NAME.map [ -n "$CP2" ] && LC_ALL=C ${lslv} -m $LV_NAME | ${tail} +3l | ${awk} '{print $5 ":" $4}' >> $DATA_DIR/$LV_NAME.map [ -n "$CP3" ] && LC_ALL=C ${lslv} -m $LV_NAME | ${tail} +3l | ${awk} '{print $7 ":" $6}' >> $DATA_DIR/$LV_NAME.map } ########################### mount_wpar_fs ################################ # # NAME: mount_wpar_fs() # # DESCRIPTION: Mounts unmounted wpar file systems if necessary. Uses # libcor_sh functions # # INPUT: # none - $WPAR must be set # # OUTPUT: # DEVS_MOUNTED array is set if any file systems had to be mounted # # RETURN VALUE DESCRIPTION: # not set mount_wpar_fs() { # If WPAR is not active, need to mount the file systems WPARSTATE=`${lswpar} -qca state $WPAR` case "$WPARSTATE" in 'A') ;; 'D') # Mount file systems. If any are mounted as a result # then FS_MOUNTED will be set to 1, and DEVS_MOUNTED # will be set to the list of mounts which were # performed. If it fails, it will error off cor_mount_fs $WPAR >/dev/null ;; esac } ################################### # # input: logical volume 's name (like /dev/abc) # # ouput: type of fs created on lv # ################################### function get_fs_type { typeset lv=$1 typeset fs_type="" typeset str="" typeset field="" typeset -i i=0 str=$(LC_ALL=C lsfs -c $lv | grep $lv) OLD_IFS=$IFS IFS=":" for field in $str do (( i = i + 1 )) if [[ $i -eq 3 ]] ; then fs_type=$field break fi done IFS=$OLD_IFS echo $fs_type } ########################## Function Declarations ######################### ################################# main ######################################## # # set up environment # if [ "$MKSZDEBUG" ]; then set -x for i in $(typeset +f); do typeset -ft $i done fi export PATH="/usr/bin:/usr/sbin:/etc:$PATH" NAME=`/usr/bin/basename $0` # Command invoked mkszfile, mkvgdata, or mkwpardata MSGCAT=mksysb.cat # message catalog name MSGSET=2 USAGE_SZ=1 # mkszfile usage err exit code USAGE_VG=2 # mkvgdata usage err exit code USAGE_WP=9 # mkwpardata usage err exit code USAGE_EC=$USAGE_SZ # set mkszfile usage error [ $NAME = "mkvgdata" ] && USAGE_EC=$USAGE_VG # set mkvgdata usage error [ $NAME = "mkwpardata" ] && USAGE_EC=$USAGE_WP # set mkwpardata usage error NO_SPACE_EC=3 # No Space err exit code TRAP_EC=4 # Trap/Interrupt Encountered err exit code INVALID_VG=5 # invalid VG specified for mkvgdata FILE_EC=6 # Error creating a file or dir OTHER_VGS=7 # Error saving other VG data INVALID_WPAR=10 # invalid WPAR specified for mkwpardata INSIDE_WPAR=11 # command running inside a WPAR LV_FS_TYPE_ERR=12 # mismatched type between fs and lv BOSBOOT_EC=13 # bosboot returns error INVALID_DIR=14 # invalid directory specified for image.data ONEMEG=1048576 # One Meg to use for calculations SIXTEEN_MB=32768 # Minimum jfs2 size ONE_K=1024 # 1 Kbytes FOUR_K=4096 # 4 Kbytes - Min size of file BLK_SZ=512 # Block Size used for calculations MIN_FILE_BLKS=8 # Minimum Num. of blks allocated per file MAPS="no" # Do not generate Maps (Default) NNFLAG="no" # Do not mount filesystem for WPARS in the Defined State XWPARFLAG="no" # Exclude WPAR filesystems (Default is no) stripewarn= # Set to yes, if maps in use and striped lv's VG="_" WPAR_LV_SIZE=0 IMG_DIR= # Directory to hold image.data file XFSLIST= # File containing list of file systems to exclude PID= # Initializing PID variable ## Full-Path to commands used awk=/usr/bin/awk cp=/usr/bin/cp cut=/usr/bin/cut date=/usr/bin/date df=/usr/bin/df dspmsg=/usr/bin/dspmsg expr=/usr/bin/expr fsdb=/usr/sbin/fsdb getlvcb=/usr/sbin/getlvcb getlvodm=/usr/sbin/getlvodm getopt=/usr/bin/getopt grep=/usr/bin/grep mkdir=/usr/bin/mkdir rm=/usr/bin/rm tail=/usr/bin/tail wc=/usr/bin/wc uname=/usr/bin/uname bootinfo=/usr/sbin/bootinfo bosboot=/usr/sbin/bosboot lqueryvg=/usr/sbin/lqueryvg lquerylv=/usr/sbin/lquerylv lsattr=/usr/sbin/lsattr lsdev=/usr/sbin/lsdev lsjfs=/usr/sbin/lsjfs lsjfs2=/usr/sbin/lsjfs2 lslv=/usr/sbin/lslv lsfs=/usr/sbin/lsfs lsvg=/usr/sbin/lsvg lswpar=/usr/sbin/lswpar mkwpar=/usr/sbin/mkwpar mount=/usr/sbin/mount lslpp=/usr/bin/lslpp egrep=/usr/bin/egrep oslevel=/usr/bin/oslevel sed=/usr/bin/sed sort=/usr/bin/sort WPARID=`/usr/bin/uname -W` # Disallow in a workload partition fail_if_wpar BLK_SZ2=`${expr} $ONEMEG \/ $BLK_SZ` if [[ $SAVEWPAR -ne 1 ]]; then PLATFORM=`${bootinfo} -p` fi # # Trap on exit/interrupt/break to clean up # trap "cleanup_m $TRAP_EC \"`${dspmsg} -s 1 $MSGCAT 4 '0512-007 %s: Abnormal program termination.' $NAME`"\" 1 2 15 getoptions $* # parse commandline arguements ################################################################### ## Load cmdbsys_lib functions (just if we -N flag is selected). ################################################################### if [ "$NNFLAG"="yes" ] then . /usr/lpp/bosinst/cmdbsys_lib fi # Establish data repository variables if [ $NAME != mkwpardata ] then DATA_BASEDIR=/tmp/vgdata # base data Directory DATA_DIR=$DATA_BASEDIR/$VG # vg data Directory if [[ "$WPARID" != "0" ]] && [[ "$NAME" = "mkszfile" ]] then MAP_DIR=./.savewpar_dir # lv map files Directory - relative to rootvg wpar restore directory else MAP_DIR=$DATA_DIR # lv map files Directory fi if [ $VG = "rootvg" ] then VG_DATA=${IMG_DIR}/image.data # Rootvg image data file else VG_DATA=$DATA_DIR/$VG.data # User vg image data file fi ################################################################### ## Generate logical volume list, (LVs potentially excluded later) ################################################################### VGLIST=$VG LVLIST=`LC_ALL=C ${lsvg} -l $VG | ${tail} +3l |${awk} '{ if ( -n $3 ) {print $1} }'` else DATA_BASEDIR=/tmp/wpardata # base data Directory DATA_DIR=$DATA_BASEDIR/$WPAR # image.data Directory MAP_DIR=./.savewpar_dir # lv map files Directory - relative to # wpar restore directory FSLIST=`${lswpar} -qcM -a vfs,mountpoint $WPAR | ${grep} ^jfs | ${cut} -d: -f2` LVLIST=`${lswpar} -qcM -a vfs,device $WPAR | ${grep} ^jfs | ${cut} -d: -f2 | sed 's:/dev/::'` VGLIST=`for lv in $LVLIST do ${lslv} $lv | head -1 | ${awk} '{print $NF}' done | ${sort} -u` VG_DATA=$DATA_DIR/image.data # image.data output file # If there are no LVs (remote file systems only), disable maps [ -n "$LVLIST" ] || MAPS="no" fi FS_TMP=$DATA_DIR/fs_data_tmp # temp fs_data FS_MOUNT=$DATA_DIR/mount_tmp # temp mount list # ROOT_LV=`LC_ALL=C ${df} / | ${tail} +2l | ${awk} '{ if ( (length($7) == 1) && ($1 ~ /dev/) ) { gsub ("/dev/", "", $1); print $1 } }' ` TMP_LV=`LC_ALL=C ${df} /tmp | ${tail} +2l | grep /dev | ${awk} '{gsub ("/dev/", "", $1); print $1}' ` FREETMPBLKS=`LC_ALL=C ${df} /dev/$TMP_LV | ${tail} +2l | ${awk} '{print $3}'` # about 735 bytes for "Single Entry" stanzas IMAGE_DATA_SZ=735 for VG in $VGLIST do VGID=`${getlvodm} -v $VG` ################################################################### # # ESTIMATE size of the VG.DATA file (in num of Partitions) # ### Estimate of bytes needed for "source_disk_data" stanzas SP_HDISK=`${lqueryvg} -g $VGID -c 2>/dev/null| ${awk} '{print $1 * 160}'` # about 160 bytes ## per hdisk SP_LV=`${lqueryvg} -g $VGID -n 2>/dev/null| ${awk} '{print $1 * 606}'` # about 606 bytes ## per Logical Volume ### Estimate of bytes needed for "fs_data:" stanzas SP_FS=`LC_ALL=C ${lsvg} -l $VG | ${awk} '$2 ~/jfs/ { print $1 } ' | # about 1200 bytes ${wc} -l | ${awk} '{print $1 * 1200}'` ## per filesystem ### Add up all stanza values for estimate of # bytes for the image.data (( IMAGE_DATA_SZ = IMAGE_DATA_SZ + SP_HDISK + SP_LV + SP_FS )) done #### Convert IMAGE_DATA_SZ to 512 byte blks (rounded up) ADD_ONE=0 REM=`${expr} $IMAGE_DATA_SZ % $BLK_SZ` && ADD_ONE=1 IMAGE_DATA_SZ=`${expr} $IMAGE_DATA_SZ \/ $BLK_SZ` IMAGE_DATA_SZ=`${expr} $IMAGE_DATA_SZ \+ $ADD_ONE` REM=`${expr} $IMAGE_DATA_SZ % $MIN_FILE_BLKS` && \ REM=`${expr} $MIN_FILE_BLKS \- $REM` IMAGE_DATA_SZ=`${expr} $IMAGE_DATA_SZ \+ $REM` #### Add in the size of the WPAR specification file for mkwpardata if [ $NAME = mkwpardata ] then WPAR_SPEC_SZ=`${mkwpar} -e $WPAR -W -w -o - | ${wc} -c` if [[ $WPAR_SPEC_SZ -eq 0 ]] then cleanup_m "$NO_SPACE_EC" #MJS fi #### Convert WPAR_SPEC_SZ to 512 byte blks (rounded up) REM=`${expr} $WPAR_SPEC_SZ % $BLK_SZ` && ADD_ONE=1 WPAR_SPEC_SZ=`${expr} $WPAR_SPEC_SZ \/ $BLK_SZ` WPAR_SPEC_SZ=`${expr} $WPAR_SPEC_SZ \+ $ADD_ONE` REM=`${expr} $WPAR_SPEC_SZ % $MIN_FILE_BLKS` && \ REM=`${expr} $MIN_FILE_BLKS \- $REM` WPAR_SPEC_SZ=`${expr} $WPAR_SPEC_SZ \+ $REM` IMAGE_DATA_SZ=`${expr} $IMAGE_DATA_SZ \+ $WPAR_SPEC_SZ` fi ### If excluding WPAR file systems, add in more space for the WPAR LV ### list. if [[ "$XWPARFLAG" = yes ]] then WPAR_LV_SIZE="`${lswpar} -M -qca vfs,device 2>/dev/null | ${grep} "^jfs" | ${awk} -F: '{print $2}' | ${wc} -c`" #### Convert WPAR_LV_SIZE to 512 byte blks (rounded up) REM=`${expr} $WPAR_LV_SIZE % $BLK_SZ` && ADD_ONE=1 WPAR_LV_SIZE=`${expr} $WPAR_LV_SIZE \/ $BLK_SZ` WPAR_LV_SIZE=`${expr} $WPAR_LV_SIZE \+ $ADD_ONE` REM=`${expr} $WPAR_LV_SIZE % $MIN_FILE_BLKS` && \ REM=`${expr} $MIN_FILE_BLKS \- $REM` WPAR_LV_SIZE=`${expr} $WPAR_LV_SIZE \+ $REM` fi ################################################################### MUSTHAVE_TMP_BLKS=$IMAGE_DATA_SZ if [ $VG = "rootvg" ] && [ $NAME != mkwpardata ] && [ "$WPARID" = "0" ] # Check for space for /image.data file then FREEROOTBLKS=`LC_ALL=C ${df} / | ${tail} +2l | ${awk} '{ if ( length($7) == 1 ) {print $3} }'` if [ "$FREEROOTBLKS" -lt "$IMAGE_DATA_SZ" ] then KBYTES=`${expr} $IMAGE_DATA_SZ \/ 2 ` #Convert to KBytes REM=`${expr} $IMAGE_DATA_SZ \% 2` [ "$REM" -ne 0 ] && KBYTES=`${expr} $KBYTES \+ 1` cleanup_m "$NO_SPACE_EC" \ "`${dspmsg} -s $MSGSET $MSGCAT 18 \ '0512-018 %s: The backup could not continue because the %s Kbytes of free work space on the / filesystem that are necessary were not found. Before you reissue this command, you should extend the / filesystem (chfs) or free up space to provide a total of %s Kbytes of free work space in the / filesystem.\n\n' $NAME $KBYTES $KBYTES`" fi # Get space needed for bosboot, required at mksysb and bosinstall time if [ -c /dev/ipldevice ]; then B_OPTS=" -qvd /dev/ipldevice " else B_OPTS=" -qv " fi BOOT_BLKS=`LC_MESSAGES=C ${bosboot} $B_OPTS | ${tail} -1l | ${awk} '{print $2 * 2}'` if [ "$BOOT_BLKS" = "" ]; then cleanup_m $BOSBOOT_EC "" fi # Worst case scenario is a tape device # Note: if no tape device in PdDv then bosboot error msg goes to null and # return value is less then above bosboot call. TAPE_BLKS=`LC_MESSAGES=C ${bosboot} -qvd /dev/rmt 2>/dev/null | ${tail} -1l | ${awk} '{print $2 * 2}'` [ "$TAPE_BLKS" -gt "$BOOT_BLKS" ] && BOOT_BLKS=$TAPE_BLKS MUSTHAVE_TMP_BLKS=`${expr} $MUSTHAVE_TMP_BLKS + $BOOT_BLKS` else ### For non-rootvg, need space in /tmp for /etc/filesystems filesystem_size=`${wc} -c /etc/filesystems | ${awk} '{print $1}'` #### Convert IMAGE_DATA_SZ to 512 byte blks (rounded up) ADD_ONE=0 (( REM=$filesystem_size % $BLK_SZ )) && ADD_ONE=1 (( filesystem_size = $filesystem_size / $BLK_SZ )) (( filesystem_size = $filesystem_size + $ADD_ONE )) (( REM=$filesystem_size % $MIN_FILE_BLKS )) && \ (( REM=$MIN_FILE_BLKS - $REM )) (( filesystem_size = $filesystem_size + $REM )) #### Convert IMAGE_DATA_SZ to 512 byte blks (rounded up) ADD_ONE=0 (( REM=$filesystem_size % $BLK_SZ )) && ADD_ONE=1 (( filesystem_size = $filesystem_size / $BLK_SZ )) (( filesystem_size = $filesystem_size + $ADD_ONE )) (( REM=$filesystem_size % $MIN_FILE_BLKS )) && \ (( REM=$MIN_FILE_BLKS - $REM )) ################################################################### ### Sum of image_data and filesystem space needs (( MUSTHAVE_TMP_BLKS = $MUSTHAVE_TMP_BLKS + $filesystem_size )) fi ################################################################ # ESTIMATE size needed for the MAP files # if [ "$MAPS" = "yes" ] # calculate space needed for the maps then MAP_BLKS=`LC_ALL=C ${lsvg} -l $VG | ${tail} +3l | \ ${grep} -v "pmhibernation" | ${awk} 'BEGIN{x=0} { y = $4 * 12 if ( y <= '$FOUR_K' ) x++ else { x += (y % '$FOUR_K') ? \ (int(y / '$FOUR_K') + 1) : \ int(y / '$FOUR_K') } } END{ print (x * '$MIN_FILE_BLKS')}'` MUSTHAVE_TMP_BLKS=`${expr} $MUSTHAVE_TMP_BLKS \+ $MAP_BLKS ` fi ############################################## # # ### CHECK IF ENOUGH FREE SPACE EXISTS IN /tmp ###### # if [ $FREETMPBLKS -lt $MUSTHAVE_TMP_BLKS ] then KBYTES=`${expr} $MUSTHAVE_TMP_BLKS \/ 2 ` #Convert to KBytes REM=`${expr} $MUSTHAVE_TMP_BLKS \% 2` [ "$REM" -ne 0 ] && KBYTES=`${expr} $KBYTES \+ 1` if [ -n "$XXFLAG" ] then ((EXPAND_BLKS = MUSTHAVE_TMP_BLKS - FREETMPBLKS)) dspmsg -s 1 $MSGCAT 29 'Expanding /tmp.\n' chfs -a size=+$EXPAND_BLKS /tmp if [[ $? != 0 ]] then cleanup_m "$NO_SPACE_EC" \ "`dspmsg -s $MSGSET $MSGCAT 26 \ '0512-041 %s: The /tmp file system could not be expanded.\n' $NAME`" fi else cleanup_m "$NO_SPACE_EC" \ "`${dspmsg} -s $MSGSET $MSGCAT 23 \ '0512-023 %s: The backup could not continue because the %s KBytes of free work space in the /tmp filesystem that are necessary were not found. To make backup, do one of the following: \t (1) Specify that the /tmp filesystem can be expanded. \t (From the commandline, specify the -X option.) \t (2) Use the chfs command to extend the /tmp filesystem. \t (3) Free up space to provide a total of %s Kbytes of free work space \t in the /tmp filesystem.\n\n' $NAME $KBYTES $KBYTES`" fi fi ### End of TMP space check ########## We GOT enough space to continue ${mkdir} -p $DATA_DIR [ "$?" != 0 ] && cleanup_m "$FILE_EC" "" ${rm} -fr $DATA_DIR/* ## Clean any old data files if [ $VG != "rootvg" ] || [ "$NAME" = "mkwpardata" ] then ${cp} /etc/filesystems $DATA_DIR fi if [[ "$WPARID" != "0" ]] && [[ "$NAME" = "mkszfile" ]] then typeset WPAR=`uname -n` echo wpar $WPAR > $DATA_DIR/image.info else # Write image type information file case "$NAME" in "mkszfile") echo rvg rootvg > $DATA_DIR/image.info;; "mkvgdata") echo uvg $VG > $DATA_DIR/image.info;; "mkwpardata") echo wpar $WPAR > $DATA_DIR/image.info;; *) echo unknown $VG > $DATA_DIR/image.info;; esac fi ########### Save Estimated Minimum /tmp sizes TMP_MIN_FS_SZ=`LC_ALL=C ${df} -IM /dev/$TMP_LV | ${tail} +2l | ${awk} '{print $4 + '$MUSTHAVE_TMP_BLKS'}'` ROOT_MIN_FS_SZ=`LC_ALL=C ${df} -IM /dev/$ROOT_LV | ${tail} +2l | ${awk} '{print $4 + '$IMAGE_DATA_SZ'}'` # Start progress message if [ -n "$MKSYSB_CALL" ] then if [ $NAME = "mkwpardata" ] then echo ${dspmsg} -s $MSGSET $MSGCAT 33 'Creating information file (/image.data) for %s.' $WPAR elif [ $VG = "rootvg" ] then echo ${dspmsg} -s $MSGSET $MSGCAT 24 'Creating information file (/image.data) for rootvg.' else echo ${dspmsg} -s $MSGSET $MSGCAT 25 'Creating information file for volume group %s.' $VG fi # As a progress indicator print dots every 15 seconds while # creating the image.data or vg.data file while :; do sleep 15 echo ".\c" done & PID=$! fi ################### Mounting unmounted filesystems for WPARS ############ if [ "$NAME" = "mkszfile" ] && [ "$NNFLAG" = "yes" ] then mount_fs_wpar fi ################### Start Processing image.data file ################# #For each line, print command output in file image.data { ##### SYSTEM INFO print "image_data:" print "\tIMAGE_TYPE= bff" print "\tDATE_TIME= "`${date}` print "\tUNAME_INFO= "`${uname} -a` [ $NAME = mkwpardata ] && print "\tWPAR_NAME= ${WPAR}" if [[ "$WPARID" != "0" ]] && [[ "$NAME" = "mkszfile" ]] then print "\tWPAR_NAME= "`uname -n` fi if [ $VG = "rootvg" ] then print "\tPRODUCT_TAPE= no" ## generate list of vgs for vg in `${lsvg} -o | ${grep} -v "$VG"` #For all active VGs do USERVGS="$USERVGS$vg " # Concatenate vg to list done print "\tUSERVG_LIST= $USERVGS" mkdir -p /tmp/bos/oldvgs [[ "$?" != 0 ]] && cleanup_m "$OTHER_VGS" "" > /tmp/bos/oldvgs/.oldvgs [[ "$?" != 0 ]] && cleanup_m "$OTHER_VGS" "" for vg in `${lsvg} | ${grep} -v "$VG"` #For all defined VGs do if [ "`${getlvodm} -u $vg`" = "y" ] then vgid=`${getlvodm} -v $vg` [[ -z "$vgid" ]] && continue auto_on=`odmget -q"name=$vg AND attribute=auto_on" CuAt \ 2>/dev/null | grep "value =" | head -n 1 | cut -d'"' -f2` auto_on=${auto_on:-y} quorum_required=`odmget -q"name=$vg AND attribute=quorum" CuAt \ 2>/dev/null | grep "value =" | head -n 1 | cut -d'"' -f2` [[ "$quorum_required" != n ]] && quorum_required=y pvname=`${getlvodm} -P | grep $vg | head -n 1 | cut -d' ' -f1` [[ -z "$pvname" ]] && continue conc_capable=n conc_auto_on=n [[ `${lqueryvg} -p $pvname -X 2>/dev/null` = 0 ]] && \ echo "$vg $vgid $auto_on $quorum_required $conc_capable $conc_auto_on" \ >> /tmp/bos/oldvgs/.oldvgs fi done print "\tPLATFORM= $PLATFORM" fi print "\tOSLEVEL= "`LANG=C ${lslpp} -Lcq bos.rte 2> /dev/null | cut -d":" -f3` OSLEVEL_R=`LANG=C ${oslevel} -r 2> /dev/null | ${awk} '{print $1}'` OSLEVEL_S=`LANG=C ${oslevel} -s 2> /dev/null | ${awk} '{print $1}'` [ "$OSLEVEL_R" = "" ] && OSLEVEL_R=`LANG=C ${lslpp} -Lcq bos.rte 2> /dev/null | cut -d":" -f3 | sed -e "s/\.//g"` [ "$OSLEVEL_S" = "" ] && OSLEVEL_S=`LANG=C ${lslpp} -Lcq bos.rte 2> /dev/null | cut -d":" -f3 | sed -e "s/\.//g"` print "\tOSLEVEL_R= "$OSLEVEL_R print "\tOSLEVEL_S= "$OSLEVEL_S print "\tCPU_ID= "`${uname} -m` # Get LPAR_ID LANG=C ${uname} -Ls | while read junk nodeid nodename do if [[ $nodeid = "1" ]] && [[ $nodename = NULL ]] || [[ $nodeid = "-1" ]] then LPAR_ID= else LPAR_ID=$nodeid fi done print "\tLPAR_ID= "$LPAR_ID print "" print "logical_volume_policy:" print "\tSHRINK= no" print "\tEXACT_FIT= "$MAPS print "" if [ $VG = "rootvg" ] then print "ils_data:" print "\tLANG= "`echo` $LANG print "" fi ##### BEGIN VG DATA ############## # generate list of hdisks for VG in $VGLIST do VGID=`${getlvodm} -v $VG` VGHDISKLIST= for hd in `LC_ALL=C ${lsvg} -p $VG | ${tail} +3l | ${awk} '{print $1}'` do pvid="`${getlvodm} -p $hd`" if [ "`lquerypv -p $pvid -N $hd -S`" = "0" ] then HDISKLIST="$HDISKLIST$hd " VGHDISKLIST="$VGHDISKLIST$hd " fi done print "##Command used for vg_data; ${lsvg}\n" # list command used # Get lsvg output in a "language independent" format COL1=`LC_ALL=C ${lsvg} $VG | \ ${awk} 'BEGIN{FS=":"} {print $2}' | ${awk} 'BEGIN{ORS=":"}{print $1}'` COL2=`LC_ALL=C ${lsvg} $VG | \ ${awk} 'BEGIN{FS=":"} {print $3}' | ${awk} 'BEGIN{ORS=":"}{print $1}'` print "vg_data:" #Cut & Paste follows for data fields. print "\tVGNAME= "$VG print "\tPPSIZE= "`echo $COL2 |${awk} 'BEGIN{FS=":"} {print $2}'` print "\tVARYON= "`echo $COL2 |${awk} 'BEGIN{FS=":"} {print $9}'` print "\tVG_SOURCE_DISK_LIST= $VGHDISKLIST" print "\tQUORUM= "`echo $COL2 |${awk} 'BEGIN{FS=":"} {print $6}'` [[ `${lqueryvg} -g $VGID -X 2>/dev/null` = 32 ]] && print "\tENH_CONC_CAPABLE= yes" \ || print "\tENH_CONC_CAPABLE= no" [[ `${lqueryvg} -g $VGID -x 2>/dev/null` = 1 ]] && print "\tCONC_AUTO= yes" \ || print "\tCONC_AUTO= no" ## Determine if BIG vg, SVG vg, or old style vg, based on ## vgtype: 2 = SVG, 1 = BIG, and 0 = old style maxlvs=$(${lqueryvg} -g $VGID -N) vgtype=$(${lqueryvg} -g $VGID -j) if [ $vgtype -eq 2 ] then print "\tBIGVG= svg" bigvg=svg elif [ $vgtype -eq 1 ] then print "\tBIGVG= yes" bigvg=yes else print "\tBIGVG= no" bigvg=no fi ## Get MAX PVs and MAX PPs per PV to determine tfactor maxpvs=$(${lqueryvg} -g $VGID -m) maxppspvs=$(${lqueryvg} -g $VGID -f) ## Calculate tfactor if [ $vgtype -ne 2 ] then (( tfact = maxppspvs/1016 )) print "\tTFACTOR= $tfact" else print "\tTFACTOR= 1" print "\tMAXLVS= $maxlvs" (( maxppspervg = maxppspvs/1024 )) print "\tMAXPPSPERVG= $maxppspervg" fi print "\tCRITVG= "`echo $COL2 |${awk} 'BEGIN{FS=":"} {print $15}'` print "\tCRITPVS= "`echo $COL2 |${awk} 'BEGIN{FS=":"} {print $16}'` print "\tENCRYPTVG= "`echo $COL1 |${awk} 'BEGIN{FS=":"} {print $17}'` # Mirror pools are only supported on scalable VGs (rootvg isn't) if [[ $VG != "rootvg" && $bigvg == "svg" ]] then # Mirror Pool Support print "\tMIRROR_POOL_STRICT= "`echo $COL1 | ${awk} 'BEGIN{FS=":"} {print $13}'` # Save lsvg -P $VG output. Also keep a counter of the number of hdisks. hdisk_with_mirror_pool_count=`LC_ALL=C ${lsvg} -P $VG | ${awk} '{if(NR > 1)print}' | ${wc} -l | ${awk} '{print $1}'` print "\tHDISK_WITH_MIRROR_POOL_COUNT= $hdisk_with_mirror_pool_count" i=0 LC_ALL=C ${lsvg} -P $VG | ${awk} '{if(NR > 1)print}' | while read line do # Note HDISK_${i} does not correlate with the actual hdisk number. hdisk=`echo $line | ${awk} '{print $1}'` mirror_pool=`echo $line | ${awk} '{print $2}'` print "\tHDISK_${i}_AND_MIRROR_POOL= $hdisk $mirror_pool" ((i+=1)) done fi print "" done ###### END VG DATA ################# ##### START HARD DISK DATA. print "##Command used for source_disk_data; ${bootinfo}\n" # list command used for h in $HDISKLIST #hard disk data. do print "source_disk_data:" # Cut & Paste follows for fields. print "\tPVID= "`${getlvodm} -p $h` print "\tPHYSICAL_LOCATION= "`LC_ALL=C ${lsdev} -C -F 'physloc' -l $h` print "\tCONNECTION= "`${lsdev} -Cc disk \ -F 'parent//connwhere' -l $h` print "\tLOCATION= "`LC_ALL=C ${bootinfo} -o $h` print "\tSIZE_MB= "`LC_ALL=C ${bootinfo} -s $h` print "\tHDISKNAME= $h" print "" done # with hard disk data. ##### END HARD DISK DATA. # NFS-based WPARs will have no volume groups to process, so check if [[ -n "$VGID" ]] then ###### BEGIN LV_DATA and FS_DATA ############### # only non-jfs LVs and mounted jfs or jfs2 LVs (filesystems) PPBYTES=`${lqueryvg} -g $VGID -s 2>/dev/null| ${awk} '{printf "%d",2 ^ $1}'` # Get Partition Size PPSIZE=`${expr} $PPBYTES \/ $ONEMEG` # Get Partition Size in MBytes VGTYPE=`${lqueryvg} -g $VGID -j 2>/dev/null` # Get Volume Group Type FSLIST= # See if Hardware Dump exists and if so get lv and fs name hdexist=$(ODMDIR=/etc/objrepos odmget -q attribute=fwdump_dev SWservAt | grep value) if [[ -n $hdexist && $FORCE_ALT -ne 1 ]] then # get lvname and fs name hdlvname=`echo $hdexist | grep value | cut -d"\"" -f2 | sed -e "s/\/dev\///"` # Remove LV name from LVlist LVLIST=`echo $LVLIST | sed -e "s/ $hdlvname$//" | sed -e "s/^$hdlvname //" | sed -e "s/ $hdlvname / /"` # Note - we don't need the fs name, since we build the fs list based on # the LV processing, and we won't be processing the Hardware Dump LV fi # Exclude WPAR LVs if applicable if [[ $WPAR_LV_SIZE -ne 0 ]] then ${lswpar} -M -qca vfs,device 2>/dev/null | ${grep} "^jfs" | ${awk} -F/ '{print $NF}' > $DATA_DIR/wparlvs LVLIST=`for lv in $LVLIST do ${grep} -q "^$lv$" $DATA_DIR/wparlvs && continue echo $lv done` ${rm} -f $DATA_DIR/wparlvs fi # Exclude user-specified file systems if -x specified if [[ -n $XFSLIST ]] then ### remove tabs, blanks, and especially blank lines /usr/bin/cat $XFSLIST | sed 's/ //g;s/^ *//g;s/ *$//g;/^$/d' | while read xfs do ${lsfs} -c $xfs | ${awk} -F: '($3 ~ "jfs") {print $2}' | ${sed} 's:/dev/::' done > $DATA_DIR/xlvs LVLIST=`for lv in $LVLIST do ${grep} -q "^$lv$" $DATA_DIR/xlvs && continue echo $lv done` ${rm} -f $DATA_DIR/xlvs fi print "##Command used for lv_data; ${lslv}\n" # list command used LC_ALL=C ${lsfs} -c -a | ${awk} 'BEGIN{FS=":"} $2 ~ /^\/dev\// {gsub ("/dev/", "", $2); print $2}' > $FS_MOUNT for LV in $LVLIST do VG=`${lslv} $LV | head -1 | ${awk} '{print $NF}'` # Get lslv output in a "language independent" format LV_DATA=`LC_ALL=C ${lslv} $LV` COL1=`echo "$LV_DATA" | cut -c-82 | \ ${awk} 'BEGIN{FS=":"} {print $2}' | \ ${awk} 'BEGIN{ORS=":"} { if ( $1 == "inner" ) { print $1 $2} else {print $1}}'` COL2=`echo "$LV_DATA" | ${awk} 'BEGIN{FS=":"} {print $3}' | \ ${awk} 'BEGIN{ORS=":"}{print $1}'` echo $COL1 | awk 'BEGIN{FS=":"} {print $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7 " " $8 " " $9 " " $10 " " $11 " " $12 " " $13 " " $14 " " $15 " " $16 " " $17}' | read la1 la2 la3 la4 la5 la6 la7 la8 la9 la10 la11 la12 la13 la14 la15 la16 la17 echo $COL2 | awk 'BEGIN{FS=":"} {print $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7 " " $8 " " $9 " " $10 " " $11}' | read lb1 lb2 lb3 lb4 lb5 lb6 lb7 lb8 lb9 lb10 lb11 LV_TYP=$la4 LV_label=$lb11 if [ "$LV_TYP" = "pmhibernation" ] # If LV for Power Mgmt, skip. then continue fi # If we have an unmounted multibos instance on the system, don't backup the standby_bootlv # because it will be empty and will not be bootable. if [ "$LV_label" = "standby_bootlv" ] then # if we are on a system with an unmounted multibos instance skip backing up the standby_lv MB_lv=`grep hd4 /etc/multibos/data/sbylvlist` ${mount} | ${egrep} -q /dev/$MB_lv [ $? -ne 0 ] && continue fi MNT_PT=$la11 NOFS=0 ## reset NO FileSystem in LV flag. # Is LV a jfs or jfs2 Filesystem? if [[ "$LV_TYP" = "jfs" || "$LV_TYP" = "jfs2" ]] then LC_ALL=C ${mount} | ${awk} '$1 ~ /^\/dev\// {gsub ("/dev/", "", $1); print $1} ' | ${egrep} -q "^$LV$" if [ $? -ne 0 ] ## Is the filesystem mounted? then # LV Not mounted OR has no Filesystem # If LV has a Filesystem then skip it # otherwise save the LV attributes. ${egrep} -q "^$LV$" $FS_MOUNT [ "$?" -eq 0 ] && continue else if [ "$MNT_PT" = "N/A" ] #Yes, is Fs defined in /etc/filesystems then ### No, print warning msg echo $LV | \ ${awk} '{system ( "'${dspmsg}' -s '$MSGSET' '$MSGCAT' 20 \"0512-020 %s: The logical volume %s does not have an entry in\n/etc/filesystems which is needed to accurately define the mount point.\nAs a result, it will not be backed up. If you want it to be included\nin the backup, add a stanza for it in the /etc/filesystems file and\nreissue this command before running mksysb.\n\n\" '$NAME' " $1 " 1>&2" )}' continue else ### yes, it is mounted FSLIST="$FSLIST $LV" ## add to FS list NOFS=1 ## set NO FileSystem in LV flag. fi fi fi print "lv_data:" print "\tVOLUME_GROUP= $VG" L_S_DISK="" for S_DISK in `LC_ALL=C ${lslv} -l $LV | ${tail} +3l | ${awk} '{print $1}'` do L_S_DISK="$L_S_DISK$S_DISK " done print "\tLV_SOURCE_DISK_LIST= $L_S_DISK" LVID=$la2 print "\tLV_IDENTIFIER= $LVID" print "\tLOGICAL_VOLUME= $la1" print "\tVG_STAT= $la3" print "\tTYPE= $la4" (( MAX_MAX_LPS = $maxpvs * $maxppspvs )) MAX_LPS=$la5 [ "$MAX_LPS" -gt "$MAX_MAX_LPS" ] && MAX_LPS=$MAX_MAX_LPS print "\tMAX_LPS= $MAX_LPS" print "\tCOPIES= $la6" NUM_LPs=$la7 print "\tLPs= $NUM_LPs" print "\tSTALE_PPs= $la8" print "\tINTER_POLICY= $la9" [ "$la10" = "innermiddle" ] && la10="inner middle" [ "$la10" = "inneredge" ] && la10="inner edge" print "\tINTRA_POLICY= $la10" [ "$MNT_PT" = "N/A" ] && MNT_PT="" print "\tMOUNT_POINT= `canonical $MNT_PT`" if [ "$VGTYPE" -gt 0 ]; then # Big or Scalable VG print "\tMIRROR_WRITE_CONSISTENCY= $la14" else print "\tMIRROR_WRITE_CONSISTENCY= $la12" fi SUPER_STRICT=`echo "$LV_DATA" | ${grep} superstrict | \ ${grep} yes` if [ -n "$SUPER_STRICT" ]; then print "\tLV_SEPARATE_PV= ss" else if [ "$VGTYPE" -gt 0 ]; then # Big or Scalable VG print "\tLV_SEPARATE_PV= $la15" else print "\tLV_SEPARATE_PV= $la13" fi fi print "\tPERMISSION= $lb2" print "\tLV_STATE= $lb3" print "\tWRITE_VERIFY= $lb4" print "\tPP_SIZE= $lb5" print "\tSCHED_POLICY= $lb6" print "\tPP= $lb7" print "\tBB_POLICY= $lb8" print "\tRELOCATABLE= $lb9" print "\tUPPER_BOUND= $lb10" LBL=`${getlvodm} -B $LV` [ "$LBL" = "None" ] && LBL="" print "\tLABEL= `canonical $LBL`" if [ "$MAPS" = "yes" ] then mk_mapfile $LV print "\tMAPFILE= $MAP_DIR/$LV.map" else print "\tMAPFILE=" fi if [ "$NOFS" -eq 1 ] ## Does LV have a filesystem defined. then fs=$LV print "fs_data:" >> $FS_TMP set -- `LC_ALL=C ${df} -IM /dev/$fs | ${tail} +2l` # Convert all the links in the FS_NAME to their true path FS_NAME="$2" LINKCHECK=yes # Loop to resolve all links in FS_NAME (links to links) while [[ "$LINKCHECK" = yes ]] do OLDIFS=$IFS;IFS="/";TEMPDIR="" LINKFLAG= # Loop to resolve first level of links in FS_NAME for j in `dirname "$FS_NAME"` do TEMPDIR="$TEMPDIR/$j"; if [ -L "$TEMPDIR" ] then # Do not put dollar_sign curly braces around the commands if [ "`ls -l "$TEMPDIR"|awk '{print $NF}'|cut -c1`" = "/" ] then TEMPDIR=`ls -l "$TEMPDIR"|awk '{print $NF}'` else TEMPDIR=${TEMPDIR%/*}/`ls -l "$TEMPDIR"|awk '{print $NF}'` TEMPDIR=`echo "$TEMPDIR" |awk '{ gsub ("//","/",$1); print $1 }'` fi LINKFLAG=yes LINKCHECK=yes else [ -z "$LINKFLAG" ] && LINKCHECK= fi done if [[ -n "$OLDIFS" ]] then IFS=$OLDIFS else unset IFS fi # Verify that file system name is valid ${lsfs} "$TEMPDIR/`basename $FS_NAME`" >/dev/null 2>&1 if [ "$?" -eq 0 ] then [ "$LINKFLAG" = yes ] && FS_NAME="$TEMPDIR/`basename $FS_NAME`" else LINKCHECK= fi done # Final check to resolve link at basename of mount point if [ -L "$FS_NAME" ] then TEMPDIR="$FS_NAME" # Do not put dollar_sign curly braces around the commands if [ "`ls -l "$TEMPDIR"|awk '{print $NF}'|cut -c1`" = "/" ] then TEMPDIR=`ls -l "$TEMPDIR"|awk '{print $NF}'` else TEMPDIR=${TEMPDIR%/*}/`ls -l "$TEMPDIR"|awk '{print $NF}'` TEMPDIR=`echo "$TEMPDIR" |awk '{ gsub ("//","/",$1); print $1 }'` fi FS_NAME="$TEMPDIR" fi # Set fields in fs_data stanzas. print "\tFS_NAME= `canonical $FS_NAME`" >> $FS_TMP FS_LV=$1 FS_SIZE=$3 FS_MIN_SIZE=$4 # Make sure the type of this lv matches with # the type of fs which is created on this lv # if [[ "$LV_TYP" = "jfs" || "$LV_TYP" = "jfs2" ]]; then fs_type=$(get_fs_type $FS_LV) if [[ "$fs_type" != "$LV_TYP" ]] ; then # display error message and terminate ${dspmsg} -s $MSGSET $MSGCAT 35 \ "\n%s ATTENTION: The type of the logical volume %s does not match \n\ with filesystem's type.\n" $NAME $FS_LV 1>&2 cleanup_m $LV_FS_TYPE_ERR "" fi fi # jfs2 filesystem minimum size 16 MB and inline # log cannot be greater than 10% of filesystem if [[ "$LV_TYP" = "jfs2" ]]; then (( FS_MIN_SIZE = $FS_MIN_SIZE + 500 )) if [[ $FS_MIN_SIZE -gt $FS_SIZE ]]; then # If there is not 500 blocks free in filesystem, # then print mesg and set FS_MIN_SIZE=FS_SIZE. echo $FS_NAME | \ ${awk} '{system ( "'${dspmsg}' -s '$MSGSET' '$MSGCAT' 30 \"\n0512-064 %s: ATTENTION: The %s filesystem does not have %s Kbytes\nof free work space, a restore of a backup including %s may fail.\nTo avoid this possibility, do one of the following:\n\" '$NAME' " $1 " 250 " $1 " 1>&2" )}' echo $FS_NAME | \ ${awk} '{system ( "'${dspmsg}' -s '$MSGSET' '$MSGCAT' 36 \"\t (1) Use the chfs command to extend the %s filesystem.\n\t (2) Free up space to provide a total of %s Kbytes of\n\t free work space in the %s filesystem.\n\n\" " $1 " 250 " $1 " 1>&2" )}' FS_MIN_SIZE=$FS_SIZE ${rm} $VG_DATA cleanup_m "$NO_SPACE_EC" "" fi [ $FS_MIN_SIZE -lt $SIXTEEN_MB ] && FS_MIN_SIZE=$SIXTEEN_MB FS_MIN_LOG=`LC_ALL=C ${lsjfs2} $FS_LV |${tail} +2l | \ ${awk} 'BEGIN{FS=":"} {print $16}'` (( FS_MIN_LOG = FS_MIN_LOG * 20480 )) [ $FS_MIN_SIZE -lt $FS_MIN_LOG ] && FS_MIN_SIZE=$FS_MIN_LOG fi if [ $fs = $TMP_LV -o $fs = $ROOT_LV ] then if [ $fs = $TMP_LV ] then [ $FS_MIN_SIZE -lt $TMP_MIN_FS_SZ ] && FS_MIN_SIZE=$TMP_MIN_FS_SZ else [ $FS_MIN_SIZE -lt $ROOT_MIN_FS_SZ ] && FS_MIN_SIZE=$ROOT_MIN_FS_SZ fi fi print "\tFS_SIZE= $FS_SIZE" >> $FS_TMP print "\tFS_MIN_SIZE= $FS_MIN_SIZE" >> $FS_TMP print "\tFS_LV= $FS_LV" >> $FS_TMP if [[ "$LV_TYP" = "jfs" ]]; then FSEXT=`LC_ALL=C ${lsjfs} /dev/$fs |${tail} +2l` echo $FSEXT | awk 'BEGIN{FS=":"} {print $13 " " $14 " " $15 " " $16 " " $17}' | read f1 f2 f3 f4 f5 print "\tFS_FS= $f1" >> $FS_TMP print "\tFS_NBPI= $f2" >> $FS_TMP print "\tFS_COMPRESS= $f3" >> $FS_TMP print "\tFS_BF= $f4" >> $FS_TMP FS_AGSIZE=$f5 if [ "$FS_AGSIZE" -eq 8 -o "$FS_AGSIZE" -eq 16 -o "$FS_AGSIZE" -eq 32 -o "$FS_AGSIZE" -eq 64 ] then print "\tFS_AGSIZE= "`echo $FS_AGSIZE` >> $FS_TMP else print "\tFS_AGSIZE= " >> $FS_TMP fi print "" >> $FS_TMP elif [[ "$LV_TYP" = "jfs2" ]]; then FSEXT=`LC_ALL=C ${lsjfs2} /dev/$fs |${tail} +2l` echo $FSEXT | awk 'BEGIN{FS=":"} {print $13 " " $14 " " $15 " " $16 " " $17 " " $18 " " $19 " " $20 " " $21}' | read f13 f14 f15 f16 f17 f18 f19 f20 f21 print "\tFS_JFS2_BS= $f13" >> $FS_TMP print "\tFS_JFS2_SPARSE= $f14" >> $FS_TMP print "\tFS_JFS2_INLINELOG= $f15" >> $FS_TMP print "\tFS_JFS2_SIZEINLINELOG= $f16" >> $FS_TMP print "\tFS_JFS2_EAFORMAT= $f17" >> $FS_TMP print "\tFS_JFS2_QUOTA= $f18" >> $FS_TMP print "\tFS_JFS2_DMAPI= $f19" >> $FS_TMP print "\tFS_JFS2_VIX= $f20" >> $FS_TMP print "\tFS_JFS2_EFS= $f21" >> $FS_TMP print "" >> $FS_TMP fi NUMLP=$FS_MIN_SIZE # LV size in MB REM=`${expr} $NUMLP \% $BLK_SZ2` NUMLP=`${expr} $NUMLP \/ $BLK_SZ2` [ $REM -ne 0 ] && NUMLP=`${expr} $NUMLP \+ 1` # LV size in partitions LV_MIN_LPS=`${expr} $NUMLP \/ $PPSIZE` REM=`${expr} $NUMLP \% $PPSIZE` && \ LV_MIN_LPS=`${expr} $LV_MIN_LPS \+ 1` print "\tLV_MIN_LPS= $LV_MIN_LPS" else print "\tLV_MIN_LPS= $NUM_LPs" fi STRIPE_WIDTH=`echo "$LV_DATA" | ${grep} "STRIPE WIDTH" | ${awk} 'BEGIN{FS=":"} {print $2}' | ${awk} '{print $1}'` STRIPE_SIZE=`echo "$LV_DATA" | ${grep} "STRIPE SIZE" | ${awk} 'BEGIN{FS=":"} {print $2}' | ${awk} '{print $1}'` DEV_SUBTYPE=`echo "$LV_DATA" | ${grep} "DEVICESUBTYPE" | ${awk} 'BEGIN{FS=":"} {print $2}' | ${awk} '{print $1}'` print "\tSTRIPE_WIDTH= $STRIPE_WIDTH" print "\tSTRIPE_SIZE= $STRIPE_SIZE" SERIALIZE_IO=$la14 [ "$SERIALIZE_IO" = YES ] && SERIALIZE_IO="yes" || SERIALIZE_IO="no" print "\tSERIALIZE_IO= $SERIALIZE_IO" # Add tag data if present TAG=$(LC_ALL=C ${getlvcb} -f "$LV") # Print it if valid if [[ -n $TAG ]]; then print "\tFS_TAG= $TAG" else print "\tFS_TAG=" fi print "\tDEV_SUBTYP=$DEV_SUBTYPE" # LV_USERID, LV_GROUPID, LV_MODES are only used on non-rootvg # volume groups that have the BIGVG attribute. if [ -n "$bigvg" ] && [ "$VG" != rootvg ] then print "\tLV_USERID= "`LC_ALL=C ${lquerylv} -L "$LVID" -u` print "\tLV_GROUPID= "`LC_ALL=C ${lquerylv} -L "$LVID" -g` print "\tLV_MODES= "`LC_ALL=C ${lquerylv} -L "$LVID" -m` fi stripesz= stripesz=$STRIPE_SIZE if [[ $MAPS = "yes" && -n $stripesz && $VG = "rootvg" ]] then stripewarn=yes fi if [[ $VG != "rootvg" && $bigvg == "svg" ]] then COPY_1_MIRROR_POOL=`echo "$LV_DATA" | ${grep} "COPY 1 MIRROR POOL" | ${awk} 'BEGIN{FS=":"} {print $2}' | ${awk} '{print $1}'` COPY_2_MIRROR_POOL=`echo "$LV_DATA" | ${grep} "COPY 2 MIRROR POOL" | ${awk} 'BEGIN{FS=":"} {print $2}' | ${awk} '{print $1}'` COPY_3_MIRROR_POOL=`echo "$LV_DATA" | ${grep} "COPY 3 MIRROR POOL" | ${awk} 'BEGIN{FS=":"} {print $2}' | ${awk} '{print $1}'` print "\tCOPY_1_MIRROR_POOL= $COPY_1_MIRROR_POOL" print "\tCOPY_2_MIRROR_POOL= $COPY_2_MIRROR_POOL" print "\tCOPY_3_MIRROR_POOL= $COPY_3_MIRROR_POOL" fi print "" done # With lv_data ####### END LV DATA ################# ####### PRINT FS DATA ################# fi print "##Commands used for fs_data; ${df}, ${lsjfs}, and ${lsjfs2}\n" [[ -s "$FS_TMP" ]] && cat $FS_TMP ##### END FS DATA ################# if [ $NAME != mkwpardata ] then if [ $VG = "rootvg" ] then if [[ "$WPARID" = "0" ]]; then print "post_install_data:" print "\tBOSINST_FILE= " fi else print "post_restvg:" print "\tRESTVG_FILE= " fi fi } > $VG_DATA [ "$?" != 0 ] && cleanup_m "$FILE_EC" "" if [ $NAME = mkwpardata ] then ${mkwpar} -e $WPAR -W -w -o - > $DATA_DIR/wpar.spec fi if [[ $stripewarn = "yes" ]] then ## Issue warning that the lv will be recreated with strips, ## and will not use the maps file ${dspmsg} -s $MSGSET $MSGCAT 28 \ "\n0512-053 %s: WARNING: The creation of\n\ map files was specified, however,\n\ at least one logical volume was striped.\n\ Striped logical volumes can not be created\n\ with map files. The striped logical volume may not\n\ be recreated in exactly the same place.\n" $NAME fi if [ -n "$MKSYSB_CALL" ] then kill $PID >/dev/null 2>&1 unset PID echo fi #### Check for duplicate filesystem/logical volumes in volume group data file dup_entry=`cat $VG_DATA | ${awk} '{if($0 ~ "FS_NAME" || $0 ~ "LOGICAL_VOLUME") {print $0}}' | sort | uniq -d | ${awk} '{print $2}'` if [ "$dup_entry" ] then ${dspmsg} -s $MSGSET $MSGCAT 29 \ "\n0512-056 %s: Duplicate fs_data and/or lv_data stanza %s \n\ specified in the %s file. The backup cannot continue.\n" $NAME $dup_entry $VG_DATA fi rm -r $FS_TMP $FS_MOUNT 2>/dev/null ### reset trap, cleanup any side effects, and exit 0 cleanup_m 0