From: rca@Ingres.COM (Bob Arnold)
Subject: Re: WANTED: Unix administration horror stories !
Reply-To: rca@Ingres.COM (Bob Arnold)
Organization: Ask Computer Systems Inc., Ingres Division, Alameda CA 94501
Date: 15 Oct 92 02:57:35 GMT

In article <Bw1G0s.49D@gumby.ocs.com> obi@gumby.ocs.com writes:
>I once mistakenly partitioned my Sun's boot disk so that the swap
>partition overlapped the usr partition. The machine ran fine for a long
>time (many months), presumably because the swap space was always nearly
>empty. Then, one day there was a memory parity error and the system crash
>dumped at the *end* of the swap partition. What should have been a simple
>reboot after the crash dump turned into a long and painful re-install of
>the entire system (Suns cannot boot without a /usr partition).

Seems we've had a number of overlapping partition horror stories in
this thread.  After a similar and very recent painful struggle with one
here, I decided to check our Suns.

That required a bit of coding, which at 5k is worth the bandwidth :-)

It would have to be modified for other OS, and perhaps for your
environment as well.  "df" outputs, checklist/fstab/vfstab formats,
available filesystem types, and methods of discovering disk
partitioning info (dkinfo, chpt -q, disktab, diskpart, prtvtoc, ...)
are notoriously different across UNIXs.

We use raw partitions for raw ingres log files on some hosts (surprise :-)
so the code attempts to tease those partitions out of fstab entries and
comments.  Swap partitions are also snagged out of fstab.

This code has been tested by tweaking the partition table of an
otherwise unused disk and running the script against it.  It has also
been run on most of our Suns, and we found one small time bomb waiting
to go off.  We now run it on every new Sun and newly attached disks. 

Use it at your own risk, of course.  No warranty or guarantee of any sort
is implied.  I hope you find it useful, though, giving you neither a false
sense of security nor any false alarms.  

Proactive is better than Reactive, for sure!

		Bob

  __   _    _   Bob Arnold		Ingres, An ASK Corporation
|/  \ / \  / \| 			1080 Marina Village Parkway
|    /    /   |				Alameda, CA, 94501
|    \__/ \__/| rca@ingres.com		510/748-2819

-------------------------------------------------------------------------------
#!/bin/sh
# chkoverlap - check overlapping disk partitions on suns
#	* works only on suns (so far)
#	* written by Bob Arnold 9/22/92
# Use at your own risk.  No warranty or guarantee of any sort is implied.
# Hopefully, you will find it useful.

badnewsonly=false		# assume we report good news too
showhost=false			# assume we show hostname
overlap=false			# assume we don't find overlap
filter=/tmp/$pr.filter		# filter egrep-ified from $usedparts
rpt=/tmp/$pr.rpt		# final report
tmp=/tmp/$pr.tmp		# scratch file
usedparts=/tmp/$pr.used		# list of used partitions
splithead=/tmp/chko.		# for split of egrep RE if it's too long
arch=`arch`			# Sun architecture, we hope
host=`hostname`			# get hostname of this machine
rmlist="$filter $rpt $tmp $usedparts ${splithead}*"	# files to clean up
USAGE="usage: $pr [-b|badnewsonly] [-s|showhost]
       $pr [-h|help]"

case "$arch" in
sun*)	: do nothing since we are ok ;;
*)	echo "$pr: This script only works on Suns." ; exit 1 ;;
esac

for arg in $* ; do
	case $arg in
	-b*|b*)	badnewsonly=true ;;
	-h*|h*)	echo "$USAGE" ; exit ;;
	-s*|s*)	showhost=true ;;
	esac
done

## build list of used partitions
# first, make sure we haven't left anything around
rm -f $rmlist
# first, get filesystems and root swap partition from df of local filesystems
df -t 4.2 \
| awk '
	/^\/dev\// {
		print $1, $NF
		if ($NF == "/") {
			print $1, "root_swap"
		}
	}' \
| sed -e '/ root_swap$/s/. /b /' > $usedparts
# a brief diversion here to get the name of the used filesystem
rootdev=`sed -n -e 's,/dev/\([^ ]*\) /$,\1,p' $usedparts`
# next, get used partitions from fstab; this list will mostly overlap the
# df output.  But it would include any swap partitions and "ignored"
# partitions ("ignored" partitions are probably Ingres raw log partitions).
egrep '^/dev/' /etc/fstab \
| awk '{print $1, $2}' \
| sed -e 's/ swap$/ fstab_swap/' >> $usedparts
# third, get raw ingres log partitions from fstab comments
awk '
	/^\#/ {
		# if this line mentions an Ingres raw log partition
		if ( $0 ~ /[iI]ngres.*[lL]og|[rR]aw.*[lL]og/ ) {
			# try to get the device name from this line
			gotdev=0
			for (i=1;i<=NF;i++) {
				if ($i~/\/dev\//) {
					print $1, "ingres_raw_log"
					gotdev=1
				}
			}
			# if this line did not have the device name, try the next line
			if (gotdev==0) {
				trynext=1
			}
		} else if (trynext==1) {
			trynext=0
			for (i=1; i<=NF; i++) {
				if ($i~/\/dev\//) {
					print $1, "ingres_raw_log"
					gotdev=1
				}
			}
		}
	}
' /etc/fstab >> $usedparts
# finally, strip floppies, cdroms, and leading "/dev/" from $usedparts,
# and sort uniq lines too
sed -e '/^\/dev\/fd/d' -e '/^\/dev\/sr/d' -e 's,\#*/dev/,,' $usedparts \
| sort +0u -1 > $tmp
mv $tmp $usedparts

## build list of used disks
disklist=`sed -e 's/. .*//' $usedparts | sort -u`

## build egrep command to grab *used* partitions from list
## of *available* partitions
# create egrep filter
awk '{print "^" $1 " "}' $usedparts > $filter
# If there are too many filesystems, egrep will barf on the filter, saying
# egrep: regular expression too long
# In that case we have to split the filter into pieces and then create
# an egrep command that can handle them all
# To test for that condition, we have to feed the filter something it is
# guaranteed to find, i.e. the root device (which we figured out earlier)
# followed by a <SPACE>
if echo "$rootdev " | egrep -f $filter > /dev/null 2>&1 ; then
	egrepcmd="egrep -f $filter"
else
	split -5 $filter $splithead
	for i in ${splithead}* ; do
		if test -z "$egrepcmd" ; then
			egrepcmd="egrep -f $i"
		else
			egrepcmd="$egrepcmd | egrep -f $i"
		fi
	done
fi

## put check of each disk into $rpt
# gnarly code gets info about partitioning of each disk,
# egreps for partitions we're really using,
# joins that info to $usedparts and sorts it by starting cylinder
# (which is *key* because the following awk algorithm depends on it),
# shoving that output into an awk script to do the actual overlap check
for disk in $disklist ; do
	dkinfo $disk 2>&1 \
	| sed -e '/^[a-z][a-z][0-9]:/d' \
	      -e '/No such device or address/d' \
	      -e '/cylinders.*heads.*track/d' \
	| awk '
		$1  ~ /^[a-h]:/ {printf("%s%s %s ", "'$disk'", $1, $4)}
		$1 !~ /^[a-h]:/ {print $NF}
	' \
	| sed -e 's/[:(]//g' \
	| awk '{print $1, $3, $2}' \
	| eval $egrepcmd \
	| join - $usedparts \
	| sort +1n -2 \
	| awk '
		BEGIN {n=0}
		# load arrays from each input line
		{ part[n]=$1; startcyl[n]=$2; ncyl[n]=$3; mtpt[n]=$4; line[n]=$0; n++ }
		# now check arrays to see if any partitions overlap
		END {
			for (i=0; i+1<n; i++) {
				if ((startcyl[i]+ncyl[i]-1) >= startcyl[i+1]) {
					print line[i], "OVERLAP", line[i+1]
				}
			}
		}
	' >> $rpt
done

## final results !!
test -s $rpt && overlap=true
case $badnewsonly in
false)	test ! -s $rpt && echo OK > $rpt ;;
esac

case $showhost$badnewsonly in
truetrue)	echo -n "$host	" ; test $overlap = true && cat $rpt ;;
falsetrue)	:		  ; test $overlap = true && cat $rpt ;;
truefalse)	echo -n "$host	" ; cat $rpt ;;
falsefalse)	:		  ; cat $rpt ;;
esac

## clean up and quit
rm -f $rmlist
if test $overlap = "true" ; then
	exit 1
else
	exit 0
fi
--
  __   _    _   Bob Arnold		Ingres, An ASK Corporation
|/  \ / \  / \| 			1080 Marina Village Parkway
|    /    /   |				Alameda, CA, 94501
|    \__/ \__/| rca@ingres.com		510/748-2819
Newsgroups: comp.unix.admin,comp.unix.programmer