Formatting Many Raw Devices At Once Under Solaris

When you intend to use raw devices (e.g. for Oracle RAC) you might end up in formatting lots of disks manually. As the provided raw devices are often backed by a storage subsystem which uses a RAID configuration and where you have configured LUNs you want to use the entire space from that device.

I developed a short shell script to fdisk and format a raw device. The script takes care that the first cylinder is not used to not accidentally overwrite the partition table. The script uses prtvtoc to calculate the values used with fmthard -d.

To format raw devices use the following syntax:

fmtrawdev <raw device> <slice number>

On SPARC use /dev/rdsk/c1t12d0s2 and on x86 /dev/rdsk/c1t12d0p0 as the first argument.

Example on SPARC to create slice 6 on /dev/rdsk/c1t12d0 using the entire available space:

fmtrawdev /dev/rdsk/c1t12d0s2 6

On x86 this looks like:

fmtrawdev /dev/rdsk/c1t12d0p0 6

To format many raw devices on the same controller I use a for-loop in the shell:

for target in 4 5 6 7 8 9 10 11 12
do
  fmtrawdev /dev/rdsk/c1t${target}d0s2 6
done

The script:

#!/bin/bash

RAWDEV=$1
SLICE=$2
tmp=.fmtrawdev$$

# fdisk
echo "${RAWDEV}: fdisk; creating partition"
fdisk -B ${RAWDEV}

# Get VTOC
prtvtoc ${RAWDEV} > ${tmp}
# Bytes per sector?
bytes_per_sec=$(grep "bytes/sector" ${tmp} | awk '{print $2}')
# Sectors per cylinder?
sec_per_cyl=$(grep "sectors/cylinder" ${tmp} | awk '{print $2}')
# Bytes per cylinder?
bytes_per_cyl=$((bytes_per_sec * sec_per_cyl))
# Free/accessible cylinders?
acc_cyl=$(grep "accessible cylinders" ${tmp} | awk '{print $2}')
# Calculate free sectors (free space): sectors per cylinder * free cylinders - first cylinder
sec_count=$((sec_per_cyl * acc_cyl - sec_per_cyl))

# fmthard
echo "${RAWDEV}: creating slice ${SLICE} starting at sector ${sec_per_cyl} with length of ${sec_count} sectors"
fmthard -d 0:${SLICE}:1:${sec_per_cyl}:${sec_count} ${RAWDEV}

# Print information about space
size=$((sec_count * bytes_per_sec))
sizemb=$((size / 1024 / 1024))
sizegb=$((size / 1024 / 1024 / 1024))
echo "${RAWDEV}: slice ${SLICE} has size of ${size} bytes = ${sizemb} MB = ${sizegb} GB"

# Print usable space for Oracle
ora_size=$((size - bytes_per_cyl))
ora_sizemb=$((ora_size / 1024 / 1024))
ora_sizegb=$((ora_size / 1024 / 1024 / 1024))
echo "${RAWDEV}: for Oracle files use size of ${ora_size} bytes = ${ora_sizemb} MB = ${ora_sizegb} GB"

# Cleanup
rm ${tmp}

exit 0

Cleaning up

In case you need to clean out a device use dd. An example to write 10 MB data onto the device, destroying the partition table and first chunks of data. This way you prevent Oracle (e.g. ASM) from recognizing a device as used:

dd if=/dev/zero of=/dev/rdsk/c1t12d0s2 bs=$((1024 * 512 * 2)) count=10

To erase the entire device skip the count parameter and type:

dd if=/dev/zero of=/dev/rdsk/c1t12d0s2 bs=$((1024 * 512 * 2))

Use at your own risk! ;-)

HTH.

This entry was posted in System Administration and tagged , . Bookmark the permalink.