1# vim: filetype=sh
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22
23#
24# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26
27. $STF_SUITE/include/libtest.kshlib
28
29# Get file sum
30#
31# $1 full file name
32function getsum #fname
33{
34	(( ${#1} == 0 )) && \
35		log_fail "Need give file name."
36	return $($SUM $1 | $AWK '{print $1}')
37}
38
39# Define global variable checksum, get the original file sum.
40#
41origsum=$(getsum /etc/passwd)
42
43#
44# Setup or recover the test environment. Firstly, copy /etc/passwd to ZFS file
45# system or volume, then make a snapshot or clone. Repeat up to three times.
46#
47# $1 number of snapshot. Note: Currently only support three snapshots.
48# $2 indicate if it is necessary to create clone
49#
50function setup_snap_env
51{
52	typeset -i cnt=${1:-3}
53	typeset createclone=${2:-"false"}
54
55	if datasetnonexists $FS; then
56		log_must $ZFS create $FS
57		log_must $ZFS set mountpoint=$TESTDIR $FS
58	fi
59	# Volume can't be created in Local Zone.
60	if datasetnonexists $VOL && is_global_zone; then
61		log_must $ZFS create -V $VOLSIZE $VOL
62	fi
63
64	# Make sure $VOL is volume
65	typeset type=$(get_prop type $VOL)
66	if datasetexists $VOL && \
67		[[ $type == 'volume' ]]; then
68		#
69		# At the first time, Make a UFS file system in volume and
70		# mount it. Otherwise, only check if this ufs file system
71		# was mounted.
72		#
73		log_must eval "$ECHO "y" | \
74			$NEWFS /dev/zvol/$VOL > /dev/null 2>&1"
75
76		[[ ! -d $TESTDIR1 ]] && log_must $MKDIR $TESTDIR1
77
78		# Make sure the ufs filesystem hasn't been mounted,
79		# then mount the new ufs filesystem.
80		$MOUNT | grep -q "/dev/zvol/$VOL" > /dev/null 2>&1
81		if (( $? != 0 )); then
82			log_must $MOUNT \
83				/dev/zvol/$TESTPOOL/$TESTVOL $TESTDIR1
84		fi
85	fi
86
87	# Separately Create three snapshots for file system & volume
88	typeset -i ind=0
89	typeset dtst
90	for dtst in $FS $VOL; do
91		# Volume can be created in Local Zone.
92		if [[ $dtst == $VOL ]]; then
93			if ! is_global_zone; then
94				break
95			fi
96		fi
97
98		ind=0
99		while (( ind < cnt )); do
100			case $dtst in
101			$FS)
102				eval typeset snap=\$FSSNAP$ind
103				eval typeset clone=\$FSCLONE$ind
104				eval typeset fname=\$TESTDIR/\$TESTFILE$ind
105				;;
106			$VOL)
107				eval typeset snap=\$VOLSNAP$ind
108				eval typeset clone=\$VOLCLONE$ind
109				eval typeset fname=\$TESTDIR1/\$TESTFILE$ind
110				;;
111			esac
112
113			if datasetnonexists $snap; then
114				log_must $CP /etc/passwd $fname
115				#
116				# Take the snapshot with the zvol unmounted so
117				# that its filesystem's state will be
118				# consistent.
119				#
120				mount -u -o ro /dev/zvol/$TESTPOOL/$TESTVOL
121				log_must $ZFS snapshot $snap
122				mount -u -o rw /dev/zvol/$TESTPOOL/$TESTVOL
123			fi
124			if [[ $createclone == "true" ]]; then
125				if datasetnonexists $clone; then
126					log_must $ZFS clone $snap $clone
127				fi
128			fi
129			(( ind += 1 ))
130		done
131	done
132}
133
134function setup_clone_env
135{
136	setup_snap_env $1 "true"
137}
138
139#
140# Clean up the test environmnet
141#
142# $1 number of snapshot Note: Currently only support three snapshots.
143#
144function cleanup_env
145{
146	typeset -i cnt=${1:-3}
147	typeset -i ind=0
148	typeset dtst
149	typeset snap
150
151	$PKILL ${DD##*/}
152
153	$MOUNT | grep -q "/dev/zvol/$VOL" > /dev/null 2>&1
154	if (( $? == 0 )); then
155		log_must $UMOUNT -f $TESTDIR1
156	fi
157
158	[[ -d $TESTDIR ]] && log_must $RM -rf $TESTDIR/*
159	[[ -d $TESTDIR1 ]] && log_must $RM -rf $TESTDIR1/*
160
161	for dtst in $FS $VOL; do
162		for snap in $TESTSNAP $TESTSNAP1 $TESTSNAP2; do
163			if snapexists $dtst@$snap; then
164				 log_must $ZFS destroy -Rf $dtst@$snap
165			fi
166		done
167	done
168
169	# Restore original test environment
170	if datasetnonexists $FS ; then
171		log_must $ZFS create $FS
172	fi
173	if datasetnonexists $VOL ; then
174		if is_global_zone ; then
175			log_must $ZFS create -V $VOLSIZE $VOL
176		else
177			log_must $ZFS create $VOL
178		fi
179	fi
180}
181
182#
183# check if the specified files have specified status.
184#
185# $1 expected status
186# $2-n full file name
187# If it is true return 0, else return 1
188#
189function file_status
190{
191	(( $# == 0 )) && \
192		log_fail "The file name is not defined."
193
194	typeset opt
195	case $1 in
196		exist)	opt="-e" ;;
197		nonexist) opt="! -e" ;;
198		*) 	log_fail "Unsupported file status." ;;
199	esac
200
201	shift
202	while (( $# > 0 )); do
203		eval [[ $opt $1 ]] || return 1
204		shift
205	done
206
207	return 0
208}
209
210function files_exist
211{
212	file_status "exist" $@
213}
214
215function files_nonexist
216{
217	file_status "nonexist" $@
218}
219
220#
221# According to snapshot check if the file system was recovered to the right
222# point.
223#
224# $1 snapshot. fs@snap or vol@snap
225#
226function check_files
227{
228	typeset dtst=$1
229
230	if [[ $(get_prop type $dtst) != snapshot ]]; then
231		log_fail "Parameter must be a snapshot."
232	fi
233
234	typeset fsvol=${dtst%%@*}
235	typeset snap=${dtst##*@}
236	if [[ $(get_prop type $fsvol) == "filesystem" ]]; then
237		ind=""
238	else
239		ind="1"
240	fi
241
242	eval typeset file0=\$TESTDIR$ind/\$TESTFILE0
243	eval typeset file1=\$TESTDIR$ind/\$TESTFILE1
244	eval typeset file2=\$TESTDIR$ind/\$TESTFILE2
245
246	case $snap in
247		$TESTSNAP2)
248			log_must files_exist $file0 $file1 $file2
249
250			typeset sum0=$(getsum $file0)
251			typeset sum1=$(getsum $file1)
252			typeset sum2=$(getsum $file2)
253			if [[ $sum0 != $origsum || \
254				$sum1 != $origsum || sum2 != $origsum ]]
255			then
256				log_fail "After rollback, file sum is changed."
257			fi
258			;;
259		$TESTSNAP1)
260			log_must files_exist $file0 $file1
261			log_must files_nonexist $file2
262
263			typeset sum0=$(getsum $file0)
264			typeset sum1=$(getsum $file1)
265			if [[ $sum0 != $origsum || $sum1 != $origsum ]]
266			then
267				log_fail "After rollback, file sum is changed."
268			fi
269			;;
270		$TESTSNAP)
271			log_must files_exist $file0
272			log_must files_nonexist $file1 $file2
273
274			typeset sum0=$(getsum $file0)
275			if [[ $sum0 != $origsum ]]; then
276				log_fail "After rollback, file sum is changed."
277			fi
278			;;
279	esac
280}
281
282# According to dataset type, write file to different directories.
283#
284# $1 dataset
285#
286function write_mountpoint_dir
287{
288	typeset dtst=$1
289	typeset dir
290
291	if [[ $dtst == $FS ]]; then
292		dir=$TESTDIR
293		log_must ismounted $dir
294	else
295		dir=$TESTDIR1
296		log_must ismounted $dir "ufs"
297	fi
298	$DD if=/dev/urandom of=$dir/$TESTFILE1 &
299	log_must $SLEEP 3
300}
301