#!/bin/sh
########################################################################
# Version:  metafree v1.0
# Date: 4/8/03
# Usage: metafree [ soft_partition_device ]
# Description:
# Metafree with no arguments lists available unused disk space and 
# partitions which can be used in SVM. Metafree with a soft partition 
# device argument examines how much free space is available on the 
# component(logical device/partition) of which the soft partition 
# is configured. Metafree also warns of any misconfigured overlapping
# partitions (except backup slice 2).
# Metafree does not include any space of a disk partition which is in
# use by a state database.  For example, state databases may not consume
# all available cylinders of a partition.  In which case, this extra 
# space may be used for future metadevices by skipping over the replicas.
# In other words, database replicas are considered to consume the entire
# raw partition and not included in metafree's output.
#
# Common Uses:
# Executing metafree with an existing soft partition as the argument
# lists how much space is used for each soft partition using the same disk 
# component(logical volume/whole disk/slice).  It will also list how
# much space is available to either grow the existing soft partition 
# or create new soft partitions.
#
# Executing metafree with no arguments lists the total space availabe
# on the disks seen by the system for use with SVM.  Disk space is 
# displayed in the following categories:
# Disk:  The disk is not currently configured under SVM control
# Unpartitioned: Disk cylinders which are available that have not been 
#                partitioned using format. In other words, this is 
#                the space which is unallocated via the partition map
#                The available cylinders are usually represented by 
#                partition 2 which is the entire disk.
# Partition: Partitions which are available for SVM configuration.  
#            That is, they are not being used as a metadevice or raw 
#            slice for database replicas.  
# 
# Note: This script displays a warning message if partitions overlap
# (except slice 2).  The script will continue, however, you may receive 
# innacurate results as this is not recommended configuration.
# 
# Note: Slice 2 (overlap partition) is considered to encompass the entire 
# disk.  If SVM uses slice 2, the entire disk is considered unavailable
# for SVM control.  Basically, do not use partition 2 as a subset of
# the cylinders available.
#
# You must be root to execute this script because it requires the 
# prtvtoc command to be executed. No modifications or configuration 
# changes are made to the system using this script.
########################################################################

/usr/bin/id | grep "root" > /dev/null
if [ $? -ne 0 ]; then
  echo "You must be root to execute $0"
  exit  1 
fi

/usr/bin/which metastat | grep metastat > /dev/null
if [ $? -ne 0 ] ; then
  echo "You must have SVM commands in \$PATH"
  exit 3 
fi

metadb 1>/dev/null 2>/dev/null
if [ $? -ne 0 ] ; then
  echo "SDS is not used on this host"
  exit 2
fi

diskpart () {

TOTAL=0

echo
echo "Unused Device			MB Available"
echo "----------------------------------------------"

# Build string of drives being used in SVM
MDISK=`metastat | grep c[0-9][0-9]*t[0-9][0-9]*d | sed "s!.*\(c[0-9][0-9]*t[0-9][0-9]*d[0-9][0-9]*s[0-9][0-9]*\).*!\1!" | sort | uniq`

# Build string of drives seen by the system
FDISK=`format < /dev/null | grep c[0-9][0-9]*t[0-9][0-9]*d | cut -d"." -f2 | awk '{print $1}' | sort | uniq`

# Check for overlapping partitions (excluding partition 2) which may give false unused partitions
for DISK in $FDISK
do
  PREV=-1
  for SEC in `prtvtoc /dev/rdsk/${DISK}s2 | grep -v "^*" | grep -v "^ *2 " | awk '{print $4, $6}' | sort -n`
  do
    if [ $SEC -le $PREV ]; then
      echo "WARNING: Disk $DISK has overlapping partitions."
      echo
      break
    fi
    PREV=$SEC
  done
done


# Check for totally unused disks
UNUSED=UNUSED
for DRV in $FDISK
do
  FLAG=0
  for DSK in $MDISK
  do
    DSK=`echo $DSK | cut -d"s" -f1`
    if [ "$DRV" = "$DSK" ]; then
      FLAG=1
      break
    fi
  done 

  if [ $FLAG -eq 0 ]; then
    # Remove metadb partitions from list
    DBF=0
    for DB in `metadb | grep c[0-9] | cut -d"/" -f4 | cut -d"s" -f1`
    do
       [ "$DRV" = "$DB" ] && DBF=1 && break
    done

    if [ $DBF -eq 0 ]; then
      DEVICE=/dev/rdsk/${DRV}s2
      [ ! -c $DEVICE ] && echo "Device $DEVICE does not exist. Abort. " && exit
      CBS=`prtvtoc $DEVICE | egrep "(sectors\/cylinder|accessible cyl)" | awk 'BEGIN { total = 1 } { total = total * $2 } END { print total }'`
      CMB=`expr $CBS / 1024 / 2`
      TOTAL=`expr $TOTAL + $CMB`
      echo "Disk: $DRV			$CMB"
      UNUSED="$UNUSED $DRV"
    fi
  fi
done

# Check for unpartitioned/unallocated disk space
for DISK in $FDISK
do

  # Remove unused disks from the list
  for U in $UNUSED
  do
    echo $DISK | grep $U > /dev/null
    [ $? -eq 0 ] && continue 2
  done

  END=`prtvtoc /dev/rdsk/${DISK}s2 | egrep "(sectors\/cylinder|accessible cyl)" | awk 'BEGIN { total = 1 } { total = total * $2 } END { print total }'`
  STR=`prtvtoc /dev/rdsk/${DISK}s2 |  grep -v "^*" | grep -v "^ *2 " | awk '{print $4, $6}' | sort -n` 
  STR="0 $STR $END"
  NUM=0
  UPS=0
  for SEC in $STR
  do
   NUM=`expr $NUM + 1`  
   if [ $NUM -eq 1 ]; then 
     FIRST=$SEC
   else
     SECOND=$SEC
     DIFF=`expr $SECOND - $FIRST`
     [ $DIFF -eq 1 ] && DIFF=0
     UPS=`expr $UPS + $DIFF`
     NUM=0
   fi
  done
  MB=`expr $UPS / 1024 / 2`
  [ $MB -ne 0 ] && echo "Unpartitioned: $DISK	 	$MB" && TOTAL=`expr $TOTAL + $MB`
done

# See if any of the disks have available partitions that are
# not being used by SVM
for DRV in $FDISK
do
  FLAG=0
  DEVICE=/dev/rdsk/${DRV}s2
  [ ! -c $DEVICE ] && echo "Device $DEVICE does not exist." && continue
  for PART in `prtvtoc $DEVICE | grep -v "^*" | awk '{print $1}'`
  do
    [ $PART -eq 2 ] && continue
    for DSK in $MDISK
    do
      DPART=${DRV}s${PART}
      if [ "$DPART" = "$DSK" ]; then
        FLAG=1
        break
      fi
    done

    if [ $FLAG -eq 0 ]; then
 
      # If this partition is on a disk where SVM uses slice 2; then the slice is not available
      # because slice 2 is the whole disk
      metastat | grep ${DRV}s2 > /dev/null
      [ $? -eq 0 ] && break

      # Remove unused disks from partition list
      for U in $UNUSED
      do
        echo $DPART | grep $U > /dev/null
        [ $? -eq 0 ] && continue 2
      done

     # Remove metadb partitions from list
     for DB in `metadb | grep c[0-9] | cut -d"/" -f4`
     do
        [ "$DPART" = "$DB" ] && continue 2
     done

     # Remove mounted filesystems from list
     df -kl | grep "$DPART" > /dev/null
     [ $? -eq 0 ] && break

     PBS=`prtvtoc /dev/dsk/$DPART | grep -v "^*" | grep "^ *${PART} " | awk '{print $5}'`
     PMB=`expr $PBS / 1024 / 2`
     TOTAL=`expr $TOTAL + $PMB`
     echo "Partition: $DPART		$PMB"

    fi
    FLAG=0
  done
done

echo "----------------------------------------------"
echo
echo "Total MB Avail: $TOTAL"
echo

}

softpart () {

COMP=`metastat $DEV | egrep "Component:|Device:" | cut -d":" -f2 | awk '{print $1}'` 

echo
echo "Soft partitions configured on SVM Component: $COMP"

TOTAL=0
echo
echo "Soft Partition			MB Used"
echo "---------------------------------------"
for SOFT in `metastat | grep "Soft Part"| cut -d":" -f1`
do
  metastat $SOFT | egrep "Component: $COMP|Device: $COMP" > /dev/null
  [ $? -ne 0 ] && continue
  SBS=`metastat $SOFT | grep "Size:" | cut -d":" -f2 | head -1 | awk '{print $1}'`
  SMB=`expr $SBS / 1024 / 2`
  echo "$SOFT				$SMB"
  TOTAL=`expr $TOTAL + $SMB`
done

echo $COMP | grep "^d[0-9][0-9]*" > /dev/null
if [ $? -ne 0 ]; then
  DEVICE=/dev/rdsk/$COMP
  [ ! -c $DEVICE ] && echo "Device $DEVICE does not exist. Abort. " && exit
  CBS=`prtvtoc $DEVICE | egrep "(sectors\/cylinder|accessible cyl)" | awk 'BEGIN { total = 1 } { total = total * $2 } END { print total }'`
else
  CBS=`metastat $COMP | grep "Size:" | cut -d":" -f2 | head -1 | awk '{print $1}'`
fi
CMB=`expr $CBS / 1024 / 2`
AVAIL=`expr $CMB - $TOTAL`
USED=`expr $CMB - $AVAIL`

echo "---------------------------------------"
echo
echo Total MB: $CMB 
echo Total MB Used: $USED
echo Total MB Avail: $AVAIL
echo
}

# Main code
DEV=$1
if [ -z "$1" ]; then
  diskpart
else
  metastat | grep "Soft Part" | grep "^${DEV}:" >/dev/null
  [ $? -ne 0 ] && echo "ERROR: $DEV is not a soft partition." && exit
  softpart
fi
