#!/sbin/sh -
# @(#)src/scripts/vxvm/solaris/upgrade/upgrade_start.sh	2.1.5.1 04/06/98 14:48:45 -  
#ident	"@(#)cvm:src/scripts/vxvm/solaris/upgrade/upgrade_start.sh	2.1.5.1"

# Copyright(C)1996 VERITAS Software Corporation.  ALL RIGHTS RESERVED.
# UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT
# LAWS OF THE UNITED STATES.  USE OF A COPYRIGHT NOTICE
# IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
# OR DISCLOSURE.
# 
# THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND
# TRADE SECRETS OF VERITAS SOFTWARE.  USE, DISCLOSURE,
# OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR
# EXPRESS WRITTEN PERMISSION OF VERITAS SOFTWARE.
# 
#               RESTRICTED RIGHTS LEGEND
# USE, DUPLICATION, OR DISCLOSURE BY THE GOVERNMENT IS
# SUBJECT TO RESTRICTIONS AS SET FORTH IN SUBPARAGRAPH
# (C) (1) (ii) OF THE RIGHTS IN TECHNICAL DATA AND
# COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013.
#               VERITAS SOFTWARE
# 1600 PLYMOUTH STREET, MOUNTAIN VIEW, CA 94043

# Script to perform first-phase checks and operations for an upgrade
# from VxVM 1.3/2.0/2.1 to VxVM 2.2

PATH=${VXVM_UPGRADE_PATH:-/usr/sbin:/sbin:/usr/bin:/etc/vx/bin}:$PATH
SAVEDIR=/VXVM2.2-UPGRADE
undo_file=$SAVEDIR/restore.sh
converted=$SAVEDIR/converted.vols
VOL_GHOST_LEN=1
VOL_FULL_SLICE=s2
nl='
'
tab='	'
SAVEIFS=$IFStab='	'
eval `vxparms`

tempf1=/tmp/vxupgrade.$$a
tempf2=/tmp/vxupgrade.$$b
tempf3=/tmp/vxupgrade.$$c
tempf4=/tmp/vxupgrade.$$d

# save /etc/system
cp /etc/vfstab $tempf3 || exit 10
cp /etc/system $tempf4 || exit 10

# undo - undo what have been done before abnormal termination
undo()
{
	echo "
Restoring /etc/vfstab..."
	cp $tempf3 /etc/vfstab

	echo "
Restoring /etc/system..."
 	cp $tempf4 /etc/system

	if [ -f $undo_file ]
	then
		echo "
Reattaching offlined mirrors..."
		sh -x $undo_file
	fi
	rm -rf $SAVEDIR

	echo "
Upgrade operation is incomplete.  Consult the Volume Manager documentation 
if you need further help."
	sync
}

quit()
{
	[ $1 -eq 0 ] || undo
	rm -f $tempf1 $tempf2 $tempf3 $tempf4
	exit $1
}

trap 'quit 2' INT HUP QUIT TERM 

wait_continue()
{
	echo "\nHit RETURN to continue.\c"
	read ANS
}

yes_or_no()
{
	while :
	do
		echo "\n$1? [$2] \c"
		ANS=
		read ANS
		case $ANS in
		"")	ANS=$2; break;;
		n|no)	ANS=no; break;;
		y|yes)	ANS=yes; break;;
		*)	echo "\nPlease answer \"yes\" or \"no\"."
			continue;;
		esac
	done
	[ $ANS = yes ]
}

get_drv_list() 
{
	dir_entry="`ls -ld \$1`"
	path=`expr "$dir_entry" : ".*\/devices\(.*\)"`
	[ -n "$path" ] || {
		echo "
get_drv_list: Invalid device path: $1"
		return 1
	}

	node=`basename $path`
	path=`dirname $path`

	while [ -n "$path" -a "X$node" != "X/" ]; do
		drv=`expr $node : "\(.*\)@.*"`
		echo $drv
		node=`basename $path`
		path=`dirname $path`
	done
}

# sliceinfo varprefix daname sliceno - get information on the given slice
sliceinfo()
{
	_prefix=$1
	set `vxpartinfo "/dev/rdsk/$2" $3 2> /dev/null`
	if [ $# -ne 5 ] 
	then
		return 1
	fi
	eval "${_prefix}_tag=$2"
	eval "${_prefix}_flags=$3"
	eval "${_prefix}_offset=$4"
	eval "${_prefix}_len=$5"
	return 0
}

# isfreeslice daname sliceno [tag] - test if given slice is free or
#				     uses the given tag
isfreeslice()
{
	list_member $1:$2 $pending_slices && return 1
	sliceinfo _isfree "$1" $2 || return 1
	[ $# -gt 2 -a "X$_isfree_tag" = "X$3" ] && return 0
	[ "X$_isfree_tag" = X0x0 ] && return 0
	return 1
}

# findfreeslice var "slicelist" daname [tag] - locate a free slice on
#					     the given disk
#
# Return the first free slice from the given slice list.
findfreeslice()
{
	for _ffree_slice in $2
	do
		isfreeslice $3 $_ffree_slice $4 && {
			eval "$1=\$_ffree_slice"
			allocslice $3 $_ffree_slice
			return 0
		}
	done
	eval "$1="
	return 1
}

# allocslice - "allocate a slice" preventing it from being reallocated
allocslice()
{
	append_list pending_slices $1:$2
}

# get_mountdevice dir basevarname dgvarname
#
# Locate dir in the vfstab file and set the following variables as
# appropriate:
#
#	basevarname_bdev	- the block device for the file system
#	basevarname_rdev	- the raw device for the file system
#	basevarname_disk	- the standard form disk (cNtNdN), if the
#				  root file system is on a regular disk
#	basevarname_vol		- the volume containing the file system,
#				  if the file system is on a volume
#
# If the optional third arg is given, then volumes in disk groups other
# than rootdg are allowed, and the disk group name will be stuffed in
# the variable named in $dgvarname.
get_mountdevice()
{
	# On Solaris read the /etc/vfstab to get mount information.
	__bdev=
	__cdev=
	__disk=
	__vol=
	__dg=
	exec 9<&0 < /etc/vfstab
	while read _special _fsckdev _mountp _fstype _fsckpass _automnt _mntopts
	do
		case ${_special} in
		'#'* | '')	#  Ignore comments, empty lines
				continue ;;
		'-')		#  Ignore no-action lines
				continue ;;
		esac

		if [ "${_mountp}" = "$1" ]
		then
			__bdev=$_special
			__cdev=$_fsckdev
			__disk=`expr "\${__bdev}" : '^/dev/dsk/\(.*\)s.\$'`
			__vol=`expr "\${__bdev}" : '^/dev/vx/dsk/\(.*\)'`
			case $__vol in
			*/*/*)	__vol=;;
			*/*)	__dg="`expr "\$__vol" : '\(.*\)/.*'`"
				__vol="`expr "\$__vol" : '.*/\(.*\)'`";;
			*)	__dg=rootdg;;
			esac
			break
		fi
	done
	exec <&9 9<&-
	# rootdisk will  be empty if the root is defined as a volume in
	# the /etc/vfstab file.

	eval "${2}_bdev=$__bdev ${2}_cdev=$__cdev ${2}_disk=$__disk"
	if [ $# -eq 2 ] && [ "X$__dg" != Xrootdg ]
	then
		eval "${2}_vol="
	elif [ $# -eq 2 ]
	then
		eval "${2}_vol=$__vol"
	else
		eval "${2}_vol=$__vol ${3}=$__dg"
	fi
}

#
# list_explode [-t fieldsep] listname var1 var2 ...
#
# Explode a list and store elements into the named variables.  If
# some variables could not be filled (because the named list didn't
# have enough members) return a non-zero status.
#
list_explode()
{
	_le_save=$IFS
	_le_ifs=$IFS
	[ "X$1" = X-t ] && {
		_le_ifs=$2
		shift 2
	}
	_le_list=$1
	shift
	_le_vars="$*"
	IFS="$_le_ifs"
	eval "set \$$_le_list"
	IFS="$_le_save"
	for _le_var in $_le_vars
	do
		[ $# -eq 0 ] && {
			return 1
		}
		eval "$_le_var=\$1"
		shift
	done
	return 0
}

append_list()
{
	_list=$1
	shift
	eval "set -- \$$_list \$*"
	eval "$_list=\$*"
}

list_member()
{
        _want=$1
        shift
        for i in $@
        do
                [ "X$_want" = "X$i" ] && return 0
        done
        return 1
}

# is_std_disk - test if a disk is standard format
is_std_disk()
{
	_isd_base=c[0-9][0-9]*t[0-9][0-9]*d[0-9][0-9]*
	_isd_slice=s[0-9][0-9]*
	case $1 in
	/dev/dsk/*s*)	expr "$1" : "^/dev/dsk/$_isd_base$_isd_slice\$";;
	/dev/rdsk/*s*)	expr "$1" : "^/dev/rdsk/$_isd_base$_isd_slice\$";;
	*s*)		expr "$1" : "^$_isd_base$_isd_slice";;
	*)		expr "$1" : "^$_isd_base$_isd_slice";;
	esac
}

# Some device manipulation routines. These are pretty much exactly
# their dogi_ equivalents, but we don't include vxadm_lib here, so
# they need to be replicated (sigh).
slice_rawpath()
{
	name=$1
	case "$name" in
		mc*)
			p="/dev/ap/rdsk/${name}";;
		c*)
			p="/dev/rdsk/${name}";;
		*) return 1;;
	esac

	if [ $# -gt 1 ]
	then
		eval "${2}=${p}"
	else
		echo "$p";
	fi
	return 0
}

# problems - print the problems banner (if not yet printed)
problems()
{
	[ -n "$problems_found" ] && return
	problems_found=yes
	echo "
The following conditions will prevent successful unencapsulation of
the requested file systems:"
}

echo \
"VERITAS Volume Manager VxVM 2.2 upgrade start script

This script checks for problems that prevent your system being upgraded from
previous releases of Volume Manager to the VxVM 2.2 release of the 
VERITAS Volume Manager.  The steps involved in an upgrade include converting 
key file systems defined on volumes into disk partitions and removal of 
the previous VxVM package before the VxVM 2.2 package is installed."

OS_VERSION=`eval uname -r`
#
# if the user is running OS version below 5.4, ask the user to
# upgrade the OS, but continue since the user might be running this
# to upgrade the OS.
#
 
OS_VERSION=`eval uname -r`
 
case ${OS_VERSION} in
	5.6) OS_VERSION=2.6
		echo "\nYou are running Solaris ${OS_VERSION}."
		;;
	5.5.1) OS_VERSION=2.5.1
		echo "\nYou are running Solaris ${OS_VERSION}."
		;;
        5.4) OS_VERSION=2.4
	echo "\nYou are running Solaris ${OS_VERSION}.";;
        5.5) OS_VERSION=2.5
	echo "\nYou are running Solaris ${OS_VERSION}.";;
        5.3) OS_VERSION=2.3
echo \
"
                ***  WARNING ***
	You are running Solaris version ${OS_VERSION}.
 
if you are running this script to upgrade from VxVM 1.3/2.0/2.1 to VxVM 2.2
make sure you upgrade to Solaris 2.4/2.5. The install/release notes describes
the order in which the upgrade should be done.";;
        *)
echo \
"
		  ***  WARNING ***
	You are running Solaris version less than 2.3.
If you are running this script to upgrade from VxVM 1.3/2.0/2.1 to VxVM 2.2
make sure you upgrade to Solaris 2.4/2.5. The install/release notes describes
the order in which the upgrade should be done.";; 

esac

wait_continue

SAVEDIR=/VXVM2.2-UPGRADE

if [ -d $SAVEDIR ]
then
	echo "
It appears that you have run this script before. If you are running
this script *again* before running upgrade_finish the following operation 
will *erase* all the status files saved in the previous upgrade_start 
script run."

	yes_or_no "Remove the previously saved upgrade start status files" no \
		|| exit 1
fi

rm -rf $SAVEDIR

mkdir -p /VXVM2.2-UPGRADE || {
	echo "
Cannot create the /VXVM2.2-UPGRADE directory."
	quit 1
}

#
# Check for trivial cases:
#   The VxVM package was not added (or has already been removed).
#   The vxinstall program has not yet been run.
#
# For these cases, there is no work to do.
#

pkginfo -q VRTSvxvm
VRTS=$?
pkginfo -q SUNWvxvm
SUNW=$?
if [ $VRTS -eq 1 ] && [ $SUNW -eq 1 ]
then
	echo "
The VxVM 1.3/2.0/2.1 package has not been installed on this system.  Follow
the instructions in the VxVM 2.2 release notes to add the VxVM
2.2 package from the CDROM".
	quit 0
fi
if [ $VRTS -eq 0 ]
then
	pkg="VRTSvxvm"
else
	pkg="SUNWvxvm"
fi

if [ -f /etc/vx/reconfig.d/state.d/install-db ]
then
	echo "
VxVM 1.3/2.0/2.1 is not in use on this system.  You can upgrade to VxVM 2.2
simply by removing the VxVM 1.3/2.0/2.1 package and by then using pkgadd to
add the package from the VxVM 2.2 CDROM.

To remove VxVM 1.3 or VxVM 2.0, use the command:

	pkgrm $pkg

Then follow the instructions in the VxVM 2.2 release notes to add
the VxVM 2.2 package from the CDROM."
	quit 0
fi

echo "
Checking for system volumes:"

okay=yes
echo "  swap ... \c"
swapvol="`swap -l | sed -n 's%^/dev/vx/dsk/\([^ 	]*\) .*%\1%p'`"
if [ -n "$swapvol" ]
then
	case $swapvol in
	*"$nl"*)	echo "defined on volumes:" ${swapvol}.;;
	*)		echo "defined on volume $swapvol.";;
	esac
	okay=no
fi
for dir in / /usr /usr/kvm /opt /var /var/adm
do
	dirvol=`mount | awk '
		\$1 == "'"$dir"'" {
			if ($3 ~ /^\/dev\/vx\/dsk\//) {
				print $3
			} else {
				print ""
			}
			exit
		}'`
	if [ -n "$dirvol" ]
	then
		dirvol="`expr "$dirvol" : '.*/\([^/]*\)'`"
		echo "  $dir ... defined on volume $dirvol"
		okay=no
	fi
done
if [ "$okay" != yes ]
then
	echo "
The above mentioned volumes have to be converted back into disk partitions 
before the upgrade from previous releases to VxVM 2.2 can continue.  
This is also required if you are trying to upgrade Solaris.
The following script will try to convert these volumes for you automatically.  
This script will only succeed if it can find one mirror(plex) which is online,
complete and contiguous for each of the above volumes.  If this is not true,
you have to convert the volumes manually to the above mentioned state and
then run this script again."
	yes_or_no "Let the script do the conversion" yes || quit 1
fi

rm -rf $SAVEDIR || quit 100
mkdir $SAVEDIR || quit 100

rm -f $undo_file $converted || quit 10


# save the current vxvm pkg info and OS info. 
# this is used upgrade_finish script to determine if either
# the OS or the vxvm was upgraded when the upgrade_finish
# script is run.

pkginfo -l $pkg > $SAVEDIR/VxVM_info_before_upgrade
uname -a > $SAVEDIR/OS_info_before_upgrade


# scan through the argument list looking for reasons why this script
# should fail.  Also, build up a list of work to be done, in terms of
# partitions to create

problems_found=
worklist=
pending_slices=
uncaproot=
fixroot=
i_ignore=yes
for dir in / /usr /usr/kvm /var /var/adm /opt
do
	get_mountdevice "$dir" fs fs_dg
	if [ -z "$fs_vol" ]
	then
		[ -z "$i_ignore" ] && {
			problems
			if [ -n "$fs_disk" ]
			then
				echo "
File system $dir is defined on disk $fs_disk not on a volume."
			else
				echo "
There is no file system defined for the $dir mountpoint."
			fi
		}
		continue
	fi
	[ "X$dir" = X/ ] && fixroot=yes
	if [ "X$fs_dg" != Xrootdg ]
	then
		problems
		echo "
Volume $fs_vol for file system $dir is not in the rootdg disk group"
		continue
	fi
	mirlist=`vxprint -p -n -e \
		 "nas > 0 && pl_state!=\"OFFLINE\" && pl_v_name=\"$fs_vol\""`

	# Choose one mirror to online and offline the others
	onmir=
	for mir in $mirlist
	do
		# Skip non-CONCAT mirror
		st=
		st=`vxprint -F %layout $mir`
		[ "X$st" = XCONCAT ] || continue

		# Skip non-complete mirror
		st=`vxprint -p -F '%complete' $mir`
		[ "X$st" = Xon ] || continue

		# Skip volatile mirrors
		st=`vxprint -p -F '%volatile' $mir`
		[ "X$st" != Xon ] || continue

		# Check states
		eval `vxprint -v -F "vst=%state vkst=%kstate" $fs_vol`
		eval `vxprint -p -F "plst=%state plkst=%kstate" $mir`
		if [ "X$vkst" = "XENABLED" ]
		then
			if [ "X$plst" != "XACTIVE" -o "X$plkst" != "XENABLED" ]
			then
				continue
			fi
		elif [ "X$plst" != "XCLEAN" ]
		then
			continue
		fi
		
		# Check its subdisk(s)
		sdlist=`vxprint -F '%pl_offset:%len:%da:%devoffset:%name' -s \
			-e "assoc==\"$mir\" && sd_pl_offset < assoc.assoc.len"|
			sort -n`

		offset=0
		cylcorrect=0
		mirlen=0
		contig=yes
		uncapsd=
		da=
		uncapsd=
		tag=
		for sdinfo in $sdlist
		do
			list_explode -t : sdinfo ploffset sdlen sdda \
					  sddevoffset sdname

			if [ "$mirlen" -eq 0 ] && [ $sdlen -eq $VOL_GHOST_LEN ]
			then
				cylcorrect=$VOL_GHOST_LEN
				mirlen=$cylcorrect
				continue
			fi

			if [ "X$sdda" = X- ]
			then
				echo "
The mirror $mir in volume $fs_vol for file system $dir contains
unusable subdisks."
				continue 2
			fi
	
			if [ "$mirlen" -gt $VOL_GHOST_LEN ]
			then
				echo "
The mirror $mir in volume $fs_vol for file system $dir contains
more than one subdisk.  You must move together and join all
subdisks in plex $mir before you can use it as the active mirror"
				continue 2	
			fi

			da=$sdda
			is_std_disk $da 2>&1 > /dev/null
			if [ $? -ne 0 ]
			then
				echo "
Disk $da in volume $fs_vol for file system $dir is not in the standard disk
name format.  The storage on that disk must be moved to another disk before
you can use $mir as the active mirror to unencapsulate the volume $fs_vol."
				continue 2
			fi

			# canonicalize the DA name
			disk=`expr $da : '\(c[0-9]*t[0-9]*d[0-9]*\)s*'`
			fulldev=${disk}$VOL_FULL_SLICE;

			STAT_SECPERCYL=
			eval "`vxparms -s "/dev/rdsk/$da"`"
			if [ -z "$STAT_SECPERCYL" ]
			then
				problems
				echo "
Cannot determine the cylinder size for disk $da in
volume $fs_vol for file system $dir.  Without this information, the
required alignment for partitions cannot be determined for the
unencapsulation."
				continue 2
			fi

			if [ `expr $sddevoffset % $STAT_SECPERCYL` -ne \
					$cylcorrect ]
			then
				echo "
Subdisk $sdname in volume $fs_vol for file system $dir is not cylinder aligned
on its disk.  Only plexes with cylinder aligned subdisks can be
onlined for unencapsulation."
				continue 2
			fi
			mirlen=`expr $mirlen + $sdlen`
			uncapsd=$sdname
		done

		[ $mirlen -gt $VOL_GHOST_LEN ] || {
			echo "
The mirror $mir in volume $fs_vol for file system $dir does not appear
to contain any data subdisks.  This mirror does not appear to be
usable and cannot be used as the active mirror to unencapsulate the file
system $dir."
			continue
		}
		onmir=$mir
		break
	done

	[ -n "$onmir" ] || {
		problems
		echo "
Volume $fs_vol for file system $dir has no usable mirror which is complete and
CONCAT.  Only volumes with one online, complete, contiguous mirror can be
unencapsulated."
		continue
	}

	# find a slice to hold the subdisk
	case $dir in
	/)	tag=$V_ROOT; tryslices=0; uncaproot=yes;;
	/usr)	tag=$V_USR;  tryslices='6 7 3 4 5 1';;
	/var)	tag=$V_VAR;  tryslices='7 3 4 5 1 6';;
	/opt)	tag=$V_STAND;tryslices='5 3 4 1 6 7';;
	*)	tag=$V_USR;  tryslices='1 4 5 3 7 6';;
	esac
	findfreeslice slice "$tryslices" $fulldev $tag || {
		problems
		if [ "X$dir" = X/ ]
		then
			echo "
Device $fulldev in volume $fs_vol for file system / does not have a
free slice 0.  Unencapsulation of a root file system requires
that slice 0 be available on the disk for that purpose.  If the
slice is not in use for anything important it can be removed with
the command:

	/etc/vx/bin/vxpartrm /dev/rdsk/$dev 0"
		else
			echo "
Device $dev in volume $fs_vol for file system $dir does not have a
reasonable slice available for use in unencapsulating the volume.
You can free up a slice for this file system using the command

	/etc/vx/bin/vxpartrm /dev/rdsk/$dev <slice-number>

Slice 0 is reserved for use by root file system slices, so free up
a different slice number."
		fi
		continue
	}

	if [ $cylcorrect -eq $VOL_GHOST_LEN ]
	then
		sdlen=`expr $sdlen + 1`
		sddevoffset=`expr $sddevoffset - 1`
	fi

	# Add the public-region offset
	slice_rawpath ${disk}s2 dpath
	pub_offset=
	vxprtvtoc -f $tempf1 $dpath
	exec 3<&0 <$tempf1
	while read d_slice d_tag d_flags d_start d_slice
	do
		if [ "X$d_tag" = "X$VOL_PUB_SLICE_TAG" ]
		then
			pub_offset=$d_start
		fi
	done
	exec <&3 3<&-

	if [ -z "$pub_offset" ]
	then
		problems
		echo "
Unable to find the public slice offset for device $disk. Cannot
encapsulate the mirror $onmir of $fs_vol"
		continue
	fi
	sddevoffset=`expr $sddevoffset + $pub_offset`

	# add to the list of work to be done
	append_list worklist \
	   "$dir":$uncapsd:$fs_vol:$disk:$slice:$tag:$sddevoffset:$sdlen:$onmir
	[ -n "$displaywork" ] && displaywork="$displaywork$nl"
done

# quit if any problems were found
[ -n "$problems_found" ] && {
	echo "
Please correct these problems (if possible) and try again later."
	quit 1
}

# is there any work to do?
if [ -z "$worklist" ]
then
	echo "
None of the requested file systems are defined on volumes."
else
	# do the work
	echo "
Converting file systems from volumes to disk devices ...

 During the conversion the $VOLROOT/etc/vfstab file will be modified.  The old
 /etc/vfstab file will be saved in $SAVEDIR/upgrade_start_vfstab.SAV."

	wait_continue

	cp /etc/vfstab  $SAVEDIR/upgrade_start_vfstab.SAV || quit 10
	sync

	bootdisk=
	file=/etc/vfstab
	for work in $worklist
	do
		list_explode -t : work dir uncapsd vol disk slice tag start \
					size onmir || {
			echo "Internal Inconsistency"
			quit 1
		}

		# offline the other mirrors
		fs_vol=`vxprint -F "%assoc" $onmir`
		mirlist=`vxprint -p -n -e \
			 "nas > 0 && pl_state!=\"OFFLINE\" && \
				pl_v_name=\"$fs_vol\""`
		for mir in $mirlist
		do
			if [ "X$onmir" != "X$mir" ]
			then
				echo "
The mirror $mir in volume $fs_vol for the file system $dir will be offlined.
It will be reonlined when the upgrade is complete"
				vxmend off $mir || {
					echo "
Unexpected error when trying to offline $mir"
					quit 10
				}

				# save the online scripts in undo_file
				echo "vxmend on $mir || exit 1" >> \
					$undo_file || quit 10
			fi
		done

		dev=${disk}s$slice
		case $dir in
		/)	tag=$V_ROOT; bootdisk=$dev;;
		/usr)	tag=$V_USR;;
		/var)	tag=$V_VAR;;
		/opt)	tag=$V_STAND;;
		*)	tag=$V_USR;;
		esac
		echo "
Converting $dir from volume $vol to disk $dev ..." 
		vxpartadd /dev/rdsk/${disk}$VOL_FULL_SLICE $slice $tag 0x200 \
				$start $size

		get_mountdevice $dir fs 
 		sed -e \
		    "s;/dev/vx/dsk/$fs_vol\\([	 ]\\);/dev/dsk/$dev\\1;" \
	            -e \
		    "s;/dev/vx/rdsk/$fs_vol\\([	 ]\\);/dev/rdsk/$dev\\1;" \
				< $file > $file.SAV || quit 10
		mv $file.SAV $file || quit 10
		echo "$fs_vol	$dir	$dev" >> $converted || quit 10
	done
	sed "s/^\/dev\/vx\/dsk\/$swapvol/#\/dev\/vx\/dsk\/$swapvol/" $file > \
		$file.SAV || quit 10

	mv $file.SAV $file || quit 100

	# Comment out any remaining volume devices (or vxfs filesystems,
	# just to be kind) so that the upgrade process will not try and
	# mount them. This would fail, since the kernel running during the
	# upgrade doesn't have either vxfs or vxvm, and a bug in the
	# upgrade process prevents the upgrade from occurring.
	# Solaris Bug ID #1169594 and #1210910.
	awk '{
		if (($1 ~ /^\/dev\/vx/) || ($4 == "vxfs")) {
			print "#", $0;
		} else {
			print $0; 
		}}' $file > $file.SAV || quit 10
	mv $file.SAV $file || quit 100

	[ -f $undo_file ] && {
		echo "exit 0" >> $undo_file || quit 10
	}

	[ -z "$bootdisk" ] || {
		bootdev=
		bootpath=`ls -l /dev/rdsk/$bootdisk | awk '{print $11}'`
		[ -n "$bootpath" ] &&
			bootdev=`expr $bootpath : '.*devices\(.*\),raw'`
		if [ -n "$bootdev" ]
		then
			echo `eeprom boot-device` > $SAVEDIR/boot-device.SAV
			eeprom boot-device=$bootdev
			echo "
The boot device now is:
$bootdev
which may be different from the machine's default boot device.  Please write
it down now and use it as the boot device in the next reboot operation."
			wait_continue
		else
			echo "
The boot disk now is $bootdisk which may be different from the machine's
default boot disk.  Please write it down now and use it as the boot disk
in the next reboot operation."
			wait_continue
		fi
	}
fi

echo "
Preserving files to be restored after adding the VxVM 2.2 package ..."

mkdir $SAVEDIR/etc || quit 100
mkdir $SAVEDIR/etc/vx || quit 100

[ -f /etc/vx/volboot ] && (cp /etc/vx/volboot $SAVEDIR/etc/vx/. || quit 10)
[ -d /etc/vx/reconfig.d ] &&
		(cp -r /etc/vx/reconfig.d $SAVEDIR/etc/vx/. || quit 10)

grep "rootdev:/pseudo/vxio@0:0" /etc/system 1>&2 > /dev/null
if [ $? -eq 0 ]
then
	echo "
The following operation will modify the /etc/system file.  The old /etc/system
file will be saved in $SAVEDIR/upgrade_start_system.SAV."
	wait_continue
	cp /etc/system $SAVEDIR/upgrade_start_system.SAV || quit 100
	sync

	echo "Updating /etc/system..."

	file=/etc/system
	grep -v "rootdev:/pseudo/vxio@0:0" $file > $tempf1 || quit 100
	grep -v _is_volume $tempf1 > $tempf2 || quit 100
	mv $tempf2 $file || quit 100

	# remove the other drivers loaded by VxVM in the encapsulation
	awk '/^* vxvm_START/, /^* vxvm_END/' $file > $tempf1 || quit 100
	rootdisk=`awk '$1=="rootvol" {print $3}' $converted`
	[ -n "$rootdisk" ] || {
		echo "
Unexpected inconsistency in $converted"
		quit 1
	}
	get_drv_list /dev/dsk/$rootdisk > $tempf2
	if [ -s $tempf2 ]
	then
		cat $tempf2 | while read drv
				do
					grep $drv $tempf1 2>&1 > /dev/null
					if [ $? -eq 0 ]
					then
						grep -v "forceload: drv/$drv" \
						  $file > $file.SAV || quit 100
						mv $file.SAV $file || quit 100
					fi
				done
	fi
	touch $SAVEDIR/root_was_volume || quit 100
fi

vnames="`vxprint -QAqne v_open 2> /dev/null`"
vol_in_use=
if [ -n "$vnames" ]
then
	if [ -f $converted ]
	then
		for vol in $vnames
		do
			[ X$vol = "Xswapvol" ] && continue
			grep "$vol$tab" $converted 2>&1 > /dev/null
			case $? in
			0)	;;
			1)	echo "
NOTE: volume $vol is in use"; vol_in_use=yes; break;;
			*)	quit 100;;
			esac
		done
	else
			vol_in_use=yes
	fi
fi

if [ -f $SAVEDIR/root_was_volume ]
then
	if [ X$vol_in_use = "Xyes" ]
	then
		# some volumes are still in use, alert the administrator
	
		echo "
Some key file systems defined on VxVM 1.3/2.0/2.1 have been converted back 
into disk partitions. Some volumes are still in use, you will have to stop the 
volumes manually.

Consult the release/install notes for the next step."

	else

		# no volumes are in use

		echo "
Some key file systems defined on VxVM 1.3/2.0/2.1 have been converted back 
into disk partitions. No volumes are in use. 

Consult the release/install notes for the next step."	

	fi
	wait_continue
	sync
else
	if [ X$vol_in_use = "Xyes" ]
	then
		# some volumes are still in use, alert the administrator

		echo "
Some volumes are still in use, stop the volumes manually.
Consult the release/install notes for the next step."

	else

		# no volumes are in use

		echo "
No volumes are in use.
Consult the release/install notes for the next step."
	fi
fi

# touch $SAVEDIR/.start_runed to signal that the upgrade_start script
# has been run
# If one does an upgrade of Solaris to 2.5 after running this script
# and reboots, VXVM will start boot mode because the install-db is
# not there (look in vxvm_sysboot script) as it was removed by
# vxinstall during encapsulation. VXVM will hang in boot mode
# as the 2.5 libthread and libso libraries have not been copied
# over which is done only in upgrade_finish which is yet to be run. 
# let us touch a file to capture this case and look for this file
# in vxvm_sysboot to prevent vxvm from starting if upgrade_start
# script is run. This will not affect vxvm start up scripts for
# versions earlier than VxVM 2.2
touch $SAVEDIR/.start_runed || quit 100

sync
quit 0
# Copyright(C)1996 VERITAS Software Corporation.  ALL RIGHTS RESERVED.
# UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT
# LAWS OF THE UNITED STATES.  USE OF A COPYRIGHT NOTICE
# IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
# OR DISCLOSURE.
# 
# THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND
# TRADE SECRETS OF VERITAS SOFTWARE.  USE, DISCLOSURE,
# OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR
# EXPRESS WRITTEN PERMISSION OF VERITAS SOFTWARE.
# 
#               RESTRICTED RIGHTS LEGEND
# USE, DUPLICATION, OR DISCLOSURE BY THE GOVERNMENT IS
# SUBJECT TO RESTRICTIONS AS SET FORTH IN SUBPARAGRAPH
# (C) (1) (ii) OF THE RIGHTS IN TECHNICAL DATA AND
# COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013.
#               VERITAS SOFTWARE
# 1600 PLYMOUTH STREET, MOUNTAIN VIEW, CA 94043

# Script to perform first-phase checks and operations for an upgrade
# from VxVM 1.3/2.0/2.1 to VxVM 2.2

PATH=${VXVM_UPGRADE_PATH:-/usr/sbin:/sbin:/usr/bin:/etc/vx/bin}:$PATH
SAVEDIR=/VXVM2.2-UPGRADE
undo_file=$SAVEDIR/restore.sh
converted=$SAVEDIR/converted.vols
VOL_GHOST_LEN=1
VOL_FULL_SLICE=s2
nl='
'
tab='	'
SAVEIFS=$IFStab='	'
eval `vxparms`

tempf1=/tmp/vxupgrade.$$a
tempf2=/tmp/vxupgrade.$$b
tempf3=/tmp/vxupgrade.$$c
tempf4=/tmp/vxupgrade.$$d

# save /etc/system
cp /etc/vfstab $tempf3 || exit 10
cp /etc/system $tempf4 || exit 10

# undo - undo what have been done before abnormal termination
undo()
{
	echo "
Restoring /etc/vfstab..."
	cp $tempf3 /etc/vfstab

	echo "
Restoring /etc/system..."
 	cp $tempf4 /etc/system

	if [ -f $undo_file ]
	then
		echo "
Reattaching offlined mirrors..."
		sh -x $undo_file
	fi
	rm -rf $SAVEDIR

	echo "
Upgrade operation is incomplete.  Consult the Volume Manager documentation 
if you need further help."
	sync
}

quit()
{
	[ $1 -eq 0 ] || undo
	rm -f $tempf1 $tempf2 $tempf3 $tempf4
	exit $1
}

trap 'quit 2' INT HUP QUIT TERM 

wait_continue()
{
	echo "\nHit RETURN to continue.\c"
	read ANS
}

yes_or_no()
{
	while :
	do
		echo "\n$1? [$2] \c"
		ANS=
		read ANS
		case $ANS in
		"")	ANS=$2; break;;
		n|no)	ANS=no; break;;
		y|yes)	ANS=yes; break;;
		*)	echo "\nPlease answer \"yes\" or \"no\"."
			continue;;
		esac
	done
	[ $ANS = yes ]
}

get_drv_list() 
{
	dir_entry="`ls -ld \$1`"
	path=`expr "$dir_entry" : ".*\/devices\(.*\)"`
	[ -n "$path" ] || {
		echo "
get_drv_list: Invalid device path: $1"
		return 1
	}

	node=`basename $path`
	path=`dirname $path`

	while [ -n "$path" -a "X$node" != "X/" ]; do
		drv=`expr $node : "\(.*\)@.*"`
		echo $drv
		node=`basename $path`
		path=`dirname $path`
	done
}

# sliceinfo varprefix daname sliceno - get information on the given slice
sliceinfo()
{
	_prefix=$1
	set `vxpartinfo "/dev/rdsk/$2" $3 2> /dev/null`
	if [ $# -ne 5 ] 
	then
		return 1
	fi
	eval "${_prefix}_tag=$2"
	eval "${_prefix}_flags=$3"
	eval "${_prefix}_offset=$4"
	eval "${_prefix}_len=$5"
	return 0
}

# isfreeslice daname sliceno [tag] - test if given slice is free or
#				     uses the given tag
isfreeslice()
{
	list_member $1:$2 $pending_slices && return 1
	sliceinfo _isfree "$1" $2 || return 1
	[ $# -gt 2 -a "X$_isfree_tag" = "X$3" ] && return 0
	[ "X$_isfree_tag" = X0x0 ] && return 0
	return 1
}

# findfreeslice var "slicelist" daname [tag] - locate a free slice on
#					     the given disk
#
# Return the first free slice from the given slice list.
findfreeslice()
{
	for _ffree_slice in $2
	do
		isfreeslice $3 $_ffree_slice $4 && {
			eval "$1=\$_ffree_slice"
			allocslice $3 $_ffree_slice
			return 0
		}
	done
	eval "$1="
	return 1
}

# allocslice - "allocate a slice" preventing it from being reallocated
allocslice()
{
	append_list pending_slices $1:$2
}

# get_mountdevice dir basevarname dgvarname
#
# Locate dir in the vfstab file and set the following variables as
# appropriate:
#
#	basevarname_bdev	- the block device for the file system
#	basevarname_rdev	- the raw device for the file system
#	basevarname_disk	- the standard form disk (cNtNdN), if the
#				  root file system is on a regular disk
#	basevarname_vol		- the volume containing the file system,
#				  if the file system is on a volume
#
# If the optional third arg is given, then volumes in disk groups other
# than rootdg are allowed, and the disk group name will be stuffed in
# the variable named in $dgvarname.
get_mountdevice()
{
	# On Solaris read the /etc/vfstab to get mount information.
	__bdev=
	__cdev=
	__disk=
	__vol=
	__dg=
	exec 9<&0 < /etc/vfstab
	while read _special _fsckdev _mountp _fstype _fsckpass _automnt _mntopts
	do
		case ${_special} in
		'#'* | '')	#  Ignore comments, empty lines
				continue ;;
		'-')		#  Ignore no-action lines
				continue ;;
		esac

		if [ "${_mountp}" = "$1" ]
		then
			__bdev=$_special
			__cdev=$_fsckdev
			__disk=`expr "\${__bdev}" : '^/dev/dsk/\(.*\)s.\$'`
			__vol=`expr "\${__bdev}" : '^/dev/vx/dsk/\(.*\)'`
			case $__vol in
			*/*/*)	__vol=;;
			*/*)	__dg="`expr "\$__vol" : '\(.*\)/.*'`"
				__vol="`expr "\$__vol" : '.*/\(.*\)'`";;
			*)	__dg=rootdg;;
			esac
			break
		fi
	done
	exec <&9 9<&-
	# rootdisk will  be empty if the root is defined as a volume in
	# the /etc/vfstab file.

	eval "${2}_bdev=$__bdev ${2}_cdev=$__cdev ${2}_disk=$__disk"
	if [ $# -eq 2 ] && [ "X$__dg" != Xrootdg ]
	then
		eval "${2}_vol="
	elif [ $# -eq 2 ]
	then
		eval "${2}_vol=$__vol"
	else
		eval "${2}_vol=$__vol ${3}=$__dg"
	fi
}

#
# list_explode [-t fieldsep] listname var1 var2 ...
#
# Explode a list and store elements into the named variables.  If
# some variables could not be filled (because the named list didn't
# have enough members) return a non-zero status.
#
list_explode()
{
	_le_save=$IFS
	_le_ifs=$IFS
	[ "X$1" = X-t ] && {
		_le_ifs=$2
		shift 2
	}
	_le_list=$1
	shift
	_le_vars="$*"
	IFS="$_le_ifs"
	eval "set \$$_le_list"
	IFS="$_le_save"
	for _le_var in $_le_vars
	do
		[ $# -eq 0 ] && {
			return 1
		}
		eval "$_le_var=\$1"
		shift
	done
	return 0
}

append_list()
{
	_list=$1
	shift
	eval "set -- \$$_list \$*"
	eval "$_list=\$*"
}

list_member()
{
        _want=$1
        shift
        for i in $@
        do
                [ "X$_want" = "X$i" ] && return 0
        done
        return 1
}

# is_std_disk - test if a disk is standard format
is_std_disk()
{
	_isd_base=c[0-9][0-9]*t[0-9][0-9]*d[0-9][0-9]*
	_isd_slice=s[0-9][0-9]*
	case $1 in
	/dev/dsk/*s*)	expr "$1" : "^/dev/dsk/$_isd_base$_isd_slice\$";;
	/dev/rdsk/*s*)	expr "$1" : "^/dev/rdsk/$_isd_base$_isd_slice\$";;
	*s*)		expr "$1" : "^$_isd_base$_isd_slice";;
	*)		expr "$1" : "^$_isd_base$_isd_slice";;
	esac
}

# Some device manipulation routines. These are pretty much exactly
# their dogi_ equivalents, but we don't include vxadm_lib here, so
# they need to be replicated (sigh).
slice_rawpath()
{
	name=$1
	case "$name" in
		mc*)
			p="/dev/ap/rdsk/${name}";;
		c*)
			p="/dev/rdsk/${name}";;
		*) return 1;;
	esac

	if [ $# -gt 1 ]
	then
		eval "${2}=${p}"
	else
		echo "$p";
	fi
	return 0
}

# problems - print the problems banner (if not yet printed)
problems()
{
	[ -n "$problems_found" ] && return
	problems_found=yes
	echo "
The following conditions will prevent successful unencapsulation of
the requested file systems:"
}

echo \
"VERITAS Volume Manager VxVM 2.2 upgrade start script

This script checks for problems that prevent your system being upgraded from
previous releases of Volume Manager to the VxVM 2.2 release of the 
VERITAS Volume Manager.  The steps involved in an upgrade include converting 
key file systems defined on volumes into disk partitions and removal of 
the previous VxVM package before the VxVM 2.2 package is installed."

OS_VERSION=`eval uname -r`
#
# if the user is running OS version below 5.4, ask the user to
# upgrade the OS, but continue since the user might be running this
# to upgrade the OS.
#
 
OS_VERSION=`eval uname -r`
 
case ${OS_VERSION} in
	5.6) OS_VERSION=2.6
		echo "\nYou are running Solaris ${OS_VERSION}."
		;;
	5.5.1) OS_VERSION=2.5.1
		echo "\nYou are running Solaris ${OS_VERSION}."
		;;
        5.4) OS_VERSION=2.4
	echo "\nYou are running Solaris ${OS_VERSION}.";;
        5.5) OS_VERSION=2.5
	echo "\nYou are running Solaris ${OS_VERSION}.";;
        5.3) OS_VERSION=2.3
echo \
"
                ***  WARNING ***
	You are running Solaris version ${OS_VERSION}.
 
if you are running this script to upgrade from VxVM 1.3/2.0/2.1 to VxVM 2.2
make sure you upgrade to Solaris 2.4/2.5. The install/release notes describes
the order in which the upgrade should be done.";;
        *)
echo \
"
		  ***  WARNING ***
	You are running Solaris version less than 2.3.
If you are running this script to upgrade from VxVM 1.3/2.0/2.1 to VxVM 2.2
make sure you upgrade to Solaris 2.4/2.5. The install/release notes describes
the order in which the upgrade should be done.";; 

esac

wait_continue

SAVEDIR=/VXVM2.2-UPGRADE

if [ -d $SAVEDIR ]
then
	echo "
It appears that you have run this script before. If you are running
this script *again* before running upgrade_finish the following operation 
will *erase* all the status files saved in the previous upgrade_start 
script run."

	yes_or_no "Remove the previously saved upgrade start status files" no \
		|| exit 1
fi

rm -rf $SAVEDIR

mkdir -p /VXVM2.2-UPGRADE || {
	echo "
Cannot create the /VXVM2.2-UPGRADE directory."
	quit 1
}

#
# Check for trivial cases:
#   The VxVM package was not added (or has already been removed).
#   The vxinstall program has not yet been run.
#
# For these cases, there is no work to do.
#

pkginfo -q VRTSvxvm
VRTS=$?
pkginfo -q SUNWvxvm
SUNW=$?
if [ $VRTS -eq 1 ] && [ $SUNW -eq 1 ]
then
	echo "
The VxVM 1.3/2.0/2.1 package has not been installed on this system.  Follow
the instructions in the VxVM 2.2 release notes to add the VxVM
2.2 package from the CDROM".
	quit 0
fi
if [ $VRTS -eq 0 ]
then
	pkg="VRTSvxvm"
else
	pkg="SUNWvxvm"
fi

if [ -f /etc/vx/reconfig.d/state.d/install-db ]
then
	echo "
VxVM 1.3/2.0/2.1 is not in use on this system.  You can upgrade to VxVM 2.2
simply by removing the VxVM 1.3/2.0/2.1 package and by then using pkgadd to
add the package from the VxVM 2.2 CDROM.

To remove VxVM 1.3 or VxVM 2.0, use the command:

	pkgrm $pkg

Then follow the instructions in the VxVM 2.2 release notes to add
the VxVM 2.2 package from the CDROM."
	quit 0
fi

echo "
Checking for system volumes:"

okay=yes
echo "  swap ... \c"
swapvol="`swap -l | sed -n 's%^/dev/vx/dsk/\([^ 	]*\) .*%\1%p'`"
if [ -n "$swapvol" ]
then
	case $swapvol in
	*"$nl"*)	echo "defined on volumes:" ${swapvol}.;;
	*)		echo "defined on volume $swapvol.";;
	esac
	okay=no
fi
for dir in / /usr /usr/kvm /opt /var /var/adm
do
	dirvol=`mount | awk '
		\$1 == "'"$dir"'" {
			if ($3 ~ /^\/dev\/vx\/dsk\//) {
				print $3
			} else {
				print ""
			}
			exit
		}'`
	if [ -n "$dirvol" ]
	then
		dirvol="`expr "$dirvol" : '.*/\([^/]*\)'`"
		echo "  $dir ... defined on volume $dirvol"
		okay=no
	fi
done
if [ "$okay" != yes ]
then
	echo "
The above mentioned volumes have to be converted back into disk partitions 
before the upgrade from previous releases to VxVM 2.2 can continue.  
This is also required if you are trying to upgrade Solaris.
The following script will try to convert these volumes for you automatically.  
This script will only succeed if it can find one mirror(plex) which is online,
complete and contiguous for each of the above volumes.  If this is not true,
you have to convert the volumes manually to the above mentioned state and
then run this script again."
	yes_or_no "Let the script do the conversion" yes || quit 1
fi

rm -rf $SAVEDIR || quit 100
mkdir $SAVEDIR || quit 100

rm -f $undo_file $converted || quit 10


# save the current vxvm pkg info and OS info. 
# this is used upgrade_finish script to determine if either
# the OS or the vxvm was upgraded when the upgrade_finish
# script is run.

pkginfo -l $pkg > $SAVEDIR/VxVM_info_before_upgrade
uname -a > $SAVEDIR/OS_info_before_upgrade


# scan through the argument list looking for reasons why this script
# should fail.  Also, build up a list of work to be done, in terms of
# partitions to create

problems_found=
worklist=
pending_slices=
uncaproot=
fixroot=
i_ignore=yes
for dir in / /usr /usr/kvm /var /var/adm /opt
do
	get_mountdevice "$dir" fs fs_dg
	if [ -z "$fs_vol" ]
	then
		[ -z "$i_ignore" ] && {
			problems
			if [ -n "$fs_disk" ]
			then
				echo "
File system $dir is defined on disk $fs_disk not on a volume."
			else
				echo "
There is no file system defined for the $dir mountpoint."
			fi
		}
		continue
	fi
	[ "X$dir" = X/ ] && fixroot=yes
	if [ "X$fs_dg" != Xrootdg ]
	then
		problems
		echo "
Volume $fs_vol for file system $dir is not in the rootdg disk group"
		continue
	fi
	mirlist=`vxprint -p -n -e \
		 "nas > 0 && pl_state!=\"OFFLINE\" && pl_v_name=\"$fs_vol\""`

	# Choose one mirror to online and offline the others
	onmir=
	for mir in $mirlist
	do
		# Skip non-CONCAT mirror
		st=
		st=`vxprint -F %layout $mir`
		[ "X$st" = XCONCAT ] || continue

		# Skip non-complete mirror
		st=`vxprint -p -F '%complete' $mir`
		[ "X$st" = Xon ] || continue

		# Skip volatile mirrors
		st=`vxprint -p -F '%volatile' $mir`
		[ "X$st" != Xon ] || continue

		# Check states
		eval `vxprint -v -F "vst=%state vkst=%kstate" $fs_vol`
		eval `vxprint -p -F "plst=%state plkst=%kstate" $mir`
		if [ "X$vkst" = "XENABLED" ]
		then
			if [ "X$plst" != "XACTIVE" -o "X$plkst" != "XENABLED" ]
			then
				continue
			fi
		elif [ "X$plst" != "XCLEAN" ]
		then
			continue
		fi
		
		# Check its subdisk(s)
		sdlist=`vxprint -F '%pl_offset:%len:%da:%devoffset:%name' -s \
			-e "assoc==\"$mir\" && sd_pl_offset < assoc.assoc.len"|
			sort -n`

		offset=0
		cylcorrect=0
		mirlen=0
		contig=yes
		uncapsd=
		da=
		uncapsd=
		tag=
		for sdinfo in $sdlist
		do
			list_explode -t : sdinfo ploffset sdlen sdda \
					  sddevoffset sdname

			if [ "$mirlen" -eq 0 ] && [ $sdlen -eq $VOL_GHOST_LEN ]
			then
				cylcorrect=$VOL_GHOST_LEN
				mirlen=$cylcorrect
				continue
			fi

			if [ "X$sdda" = X- ]
			then
				echo "
The mirror $mir in volume $fs_vol for file system $dir contains
unusable subdisks."
				continue 2
			fi
	
			if [ "$mirlen" -gt $VOL_GHOST_LEN ]
			then
				echo "
The mirror $mir in volume $fs_vol for file system $dir contains
more than one subdisk.  You must move together and join all
subdisks in plex $mir before you can use it as the active mirror"
				continue 2	
			fi

			da=$sdda
			is_std_disk $da 2>&1 > /dev/null
			if [ $? -ne 0 ]
			then
				echo "
Disk $da in volume $fs_vol for file system $dir is not in the standard disk
name format.  The storage on that disk must be moved to another disk before
you can use $mir as the active mirror to unencapsulate the volume $fs_vol."
				continue 2
			fi

			# canonicalize the DA name
			disk=`expr $da : '\(c[0-9]*t[0-9]*d[0-9]*\)s*'`
			fulldev=${disk}$VOL_FULL_SLICE;

			STAT_SECPERCYL=
			eval "`vxparms -s "/dev/rdsk/$da"`"
			if [ -z "$STAT_SECPERCYL" ]
			then
				problems
				echo "
Cannot determine the cylinder size for disk $da in
volume $fs_vol for file system $dir.  Without this information, the
required alignment for partitions cannot be determined for the
unencapsulation."
				continue 2
			fi

			if [ `expr $sddevoffset % $STAT_SECPERCYL` -ne \
					$cylcorrect ]
			then
				echo "
Subdisk $sdname in volume $fs_vol for file system $dir is not cylinder aligned
on its disk.  Only plexes with cylinder aligned subdisks can be
onlined for unencapsulation."
				continue 2
			fi
			mirlen=`expr $mirlen + $sdlen`
			uncapsd=$sdname
		done

		[ $mirlen -gt $VOL_GHOST_LEN ] || {
			echo "
The mirror $mir in volume $fs_vol for file system $dir does not appear
to contain any data subdisks.  This mirror does not appear to be
usable and cannot be used as the active mirror to unencapsulate the file
system $dir."
			continue
		}
		onmir=$mir
		break
	done

	[ -n "$onmir" ] || {
		problems
		echo "
Volume $fs_vol for file system $dir has no usable mirror which is complete and
CONCAT.  Only volumes with one online, complete, contiguous mirror can be
unencapsulated."
		continue
	}

	# find a slice to hold the subdisk
	case $dir in
	/)	tag=$V_ROOT; tryslices=0; uncaproot=yes;;
	/usr)	tag=$V_USR;  tryslices='6 7 3 4 5 1';;
	/var)	tag=$V_VAR;  tryslices='7 3 4 5 1 6';;
	/opt)	tag=$V_STAND;tryslices='5 3 4 1 6 7';;
	*)	tag=$V_USR;  tryslices='1 4 5 3 7 6';;
	esac
	findfreeslice slice "$tryslices" $fulldev $tag || {
		problems
		if [ "X$dir" = X/ ]
		then
			echo "
Device $fulldev in volume $fs_vol for file system / does not have a
free slice 0.  Unencapsulation of a root file system requires
that slice 0 be available on the disk for that purpose.  If the
slice is not in use for anything important it can be removed with
the command:

	/etc/vx/bin/vxpartrm /dev/rdsk/$dev 0"
		else
			echo "
Device $dev in volume $fs_vol for file system $dir does not have a
reasonable slice available for use in unencapsulating the volume.
You can free up a slice for this file system using the command

	/etc/vx/bin/vxpartrm /dev/rdsk/$dev <slice-number>

Slice 0 is reserved for use by root file system slices, so free up
a different slice number."
		fi
		continue
	}

	if [ $cylcorrect -eq $VOL_GHOST_LEN ]
	then
		sdlen=`expr $sdlen + 1`
		sddevoffset=`expr $sddevoffset - 1`
	fi

	# Add the public-region offset
	slice_rawpath ${disk}s2 dpath
	pub_offset=
	vxprtvtoc -f $tempf1 $dpath
	exec 3<&0 <$tempf1
	while read d_slice d_tag d_flags d_start d_slice
	do
		if [ "X$d_tag" = "X$VOL_PUB_SLICE_TAG" ]
		then
			pub_offset=$d_start
		fi
	done
	exec <&3 3<&-

	if [ -z "$pub_offset" ]
	then
		problems
		echo "
Unable to find the public slice offset for device $disk. Cannot
encapsulate the mirror $onmir of $fs_vol"
		continue
	fi
	sddevoffset=`expr $sddevoffset + $pub_offset`

	# add to the list of work to be done
	append_list worklist \
	   "$dir":$uncapsd:$fs_vol:$disk:$slice:$tag:$sddevoffset:$sdlen:$onmir
	[ -n "$displaywork" ] && displaywork="$displaywork$nl"
done

# quit if any problems were found
[ -n "$problems_found" ] && {
	echo "
Please correct these problems (if possible) and try again later."
	quit 1
}

# is there any work to do?
if [ -z "$worklist" ]
then
	echo "
None of the requested file systems are defined on volumes."
else
	# do the work
	echo "
Converting file systems from volumes to disk devices ...

 During the conversion the $VOLROOT/etc/vfstab file will be modified.  The old
 /etc/vfstab file will be saved in $SAVEDIR/upgrade_start_vfstab.SAV."

	wait_continue

	cp /etc/vfstab  $SAVEDIR/upgrade_start_vfstab.SAV || quit 10
	sync

	bootdisk=
	file=/etc/vfstab
	for work in $worklist
	do
		list_explode -t : work dir uncapsd vol disk slice tag start \
					size onmir || {
			echo "Internal Inconsistency"
			quit 1
		}

		# offline the other mirrors
		fs_vol=`vxprint -F "%assoc" $onmir`
		mirlist=`vxprint -p -n -e \
			 "nas > 0 && pl_state!=\"OFFLINE\" && \
				pl_v_name=\"$fs_vol\""`
		for mir in $mirlist
		do
			if [ "X$onmir" != "X$mir" ]
			then
				echo "
The mirror $mir in volume $fs_vol for the file system $dir will be offlined.
It will be reonlined when the upgrade is complete"
				vxmend off $mir || {
					echo "
Unexpected error when trying to offline $mir"
					quit 10
				}

				# save the online scripts in undo_file
				echo "vxmend on $mir || exit 1" >> \
					$undo_file || quit 10
			fi
		done

		dev=${disk}s$slice
		case $dir in
		/)	tag=$V_ROOT; bootdisk=$dev;;
		/usr)	tag=$V_USR;;
		/var)	tag=$V_VAR;;
		/opt)	tag=$V_STAND;;
		*)	tag=$V_USR;;
		esac
		echo "
Converting $dir from volume $vol to disk $dev ..." 
		vxpartadd /dev/rdsk/${disk}$VOL_FULL_SLICE $slice $tag 0x200 \
				$start $size

		get_mountdevice $dir fs 
 		sed -e \
		    "s;/dev/vx/dsk/$fs_vol\\([	 ]\\);/dev/dsk/$dev\\1;" \
	            -e \
		    "s;/dev/vx/rdsk/$fs_vol\\([	 ]\\);/dev/rdsk/$dev\\1;" \
				< $file > $file.SAV || quit 10
		mv $file.SAV $file || quit 10
		echo "$fs_vol	$dir	$dev" >> $converted || quit 10
	done
	sed "s/^\/dev\/vx\/dsk\/$swapvol/#\/dev\/vx\/dsk\/$swapvol/" $file > \
		$file.SAV || quit 10

	mv $file.SAV $file || quit 100

	# Comment out any remaining volume devices (or vxfs filesystems,
	# just to be kind) so that the upgrade process will not try and
	# mount them. This would fail, since the kernel running during the
	# upgrade doesn't have either vxfs or vxvm, and a bug in the
	# upgrade process prevents the upgrade from occurring.
	# Solaris Bug ID #1169594 and #1210910.
	awk '{
		if (($1 ~ /^\/dev\/vx/) || ($4 == "vxfs")) {
			print "#", $0;
		} else {
			print $0; 
		}}' $file > $file.SAV || quit 10
	mv $file.SAV $file || quit 100

	[ -f $undo_file ] && {
		echo "exit 0" >> $undo_file || quit 10
	}

	[ -z "$bootdisk" ] || {
		bootdev=
		bootpath=`ls -l /dev/rdsk/$bootdisk | awk '{print $11}'`
		[ -n "$bootpath" ] &&
			bootdev=`expr $bootpath : '.*devices\(.*\),raw'`
		if [ -n "$bootdev" ]
		then
			echo `eeprom boot-device` > $SAVEDIR/boot-device.SAV
			eeprom boot-device=$bootdev
			echo "
The boot device now is:
$bootdev
which may be different from the machine's default boot device.  Please write
it down now and use it as the boot device in the next reboot operation."
			wait_continue
		else
			echo "
The boot disk now is $bootdisk which may be different from the machine's
default boot disk.  Please write it down now and use it as the boot disk
in the next reboot operation."
			wait_continue
		fi
	}
fi

echo "
Preserving files to be restored after adding the VxVM 2.2 package ..."

mkdir $SAVEDIR/etc || quit 100
mkdir $SAVEDIR/etc/vx || quit 100

[ -f /etc/vx/volboot ] && (cp /etc/vx/volboot $SAVEDIR/etc/vx/. || quit 10)
[ -d /etc/vx/reconfig.d ] &&
		(cp -r /etc/vx/reconfig.d $SAVEDIR/etc/vx/. || quit 10)

grep "rootdev:/pseudo/vxio@0:0" /etc/system 1>&2 > /dev/null
if [ $? -eq 0 ]
then
	echo "
The following operation will modify the /etc/system file.  The old /etc/system
file will be saved in $SAVEDIR/upgrade_start_system.SAV."
	wait_continue
	cp /etc/system $SAVEDIR/upgrade_start_system.SAV || quit 100
	sync

	echo "Updating /etc/system..."

	file=/etc/system
	grep -v "rootdev:/pseudo/vxio@0:0" $file > $tempf1 || quit 100
	grep -v _is_volume $tempf1 > $tempf2 || quit 100
	mv $tempf2 $file || quit 100

	# remove the other drivers loaded by VxVM in the encapsulation
	awk '/^* vxvm_START/, /^* vxvm_END/' $file > $tempf1 || quit 100
	rootdisk=`awk '$1=="rootvol" {print $3}' $converted`
	[ -n "$rootdisk" ] || {
		echo "
Unexpected inconsistency in $converted"
		quit 1
	}
	get_drv_list /dev/dsk/$rootdisk > $tempf2
	if [ -s $tempf2 ]
	then
		cat $tempf2 | while read drv
				do
					grep $drv $tempf1 2>&1 > /dev/null
					if [ $? -eq 0 ]
					then
						grep -v "forceload: drv/$drv" \
						  $file > $file.SAV || quit 100
						mv $file.SAV $file || quit 100
					fi
				done
	fi
	touch $SAVEDIR/root_was_volume || quit 100
fi

vnames="`vxprint -QAqne v_open 2> /dev/null`"
vol_in_use=
if [ -n "$vnames" ]
then
	if [ -f $converted ]
	then
		for vol in $vnames
		do
			[ X$vol = "Xswapvol" ] && continue
			grep "$vol$tab" $converted 2>&1 > /dev/null
			case $? in
			0)	;;
			1)	echo "
NOTE: volume $vol is in use"; vol_in_use=yes; break;;
			*)	quit 100;;
			esac
		done
	else
			vol_in_use=yes
	fi
fi

if [ -f $SAVEDIR/root_was_volume ]
then
	if [ X$vol_in_use = "Xyes" ]
	then
		# some volumes are still in use, alert the administrator
	
		echo "
Some key file systems defined on VxVM 1.3/2.0/2.1 have been converted back 
into disk partitions. Some volumes are still in use, you will have to stop the 
volumes manually.

Consult the release/install notes for the next step."

	else

		# no volumes are in use

		echo "
Some key file systems defined on VxVM 1.3/2.0/2.1 have been converted back 
into disk partitions. No volumes are in use. 

Consult the release/install notes for the next step."	

	fi
	wait_continue
	sync
else
	if [ X$vol_in_use = "Xyes" ]
	then
		# some volumes are still in use, alert the administrator

		echo "
Some volumes are still in use, stop the volumes manually.
Consult the release/install notes for the next step."

	else

		# no volumes are in use

		echo "
No volumes are in use.
Consult the release/install notes for the next step."
	fi
fi

# touch $SAVEDIR/.start_runed to signal that the upgrade_start script
# has been run
# If one does an upgrade of Solaris to 2.5 after running this script
# and reboots, VXVM will start boot mode because the install-db is
# not there (look in vxvm_sysboot script) as it was removed by
# vxinstall during encapsulation. VXVM will hang in boot mode
# as the 2.5 libthread and libso libraries have not been copied
# over which is done only in upgrade_finish which is yet to be run. 
# let us touch a file to capture this case and look for this file
# in vxvm_sysboot to prevent vxvm from starting if upgrade_start
# script is run. This will not affect vxvm start up scripts for
# versions earlier than VxVM 2.2
touch $SAVEDIR/.start_runed || quit 100

sync
quit 0
