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. $STF_SUITE/include/libgnop.kshlib
29. $STF_SUITE/tests/hotplug/hotplug.cfg
30
31#
32# create lofi devices
33#
34# $1-n files
35#
36function create_lofi_device
37{
38	typeset lofi_files="$@"
39
40	typeset file
41	for file in $lofi_files ; do
42		if ! $LOFIADM $file > /dev/null 2>&1 ; then
43			insert_device $file
44			if (($? != 0)); then
45				return 1
46			fi
47		fi
48
49		shift
50	done
51
52	return 0
53}
54
55#
56# Check and destroy lofi devices
57#
58# $1-n lofi files or deviece
59#
60function destroy_lofi_device
61{
62	typeset -i ret=0
63	typeset dev_file="$@"
64
65	typeset file
66	for file in $dev_file ; do
67		if $LOFIADM $file > /dev/null 2>&1; then
68			$LOFIADM -d $file -f
69			if (($? != 0)); then
70				((ret += 1))
71			fi
72		fi
73	done
74
75	return $ret
76}
77
78#
79# Setup test environment using DISKS[1-4]
80#
81# $1 pool type
82#
83function setup_testenv
84{
85	typeset type=$1
86
87	if [[ -z $type ]]; then
88		log_fail "Usage: setup_testenv <type>"
89	fi
90
91	log_must $ZPOOL create -f \
92		$TESTPOOL $type ${DISK0}.nop ${DISK1}.nop ${DISK2}.nop ${DISK3}.nop
93}
94
95#
96# Cleanup test envirnment according to pool name
97#
98# $1 pool
99#
100function cleanup_testenv
101{
102	destroy_pool $TESTPOOL
103}
104
105
106#
107# Start a background process to write file on given pool.
108#
109# $1 pool
110#
111function start_bg_write
112{
113	typeset pool=$1
114
115	if datasetnonexists $pool; then
116		return 1
117	fi
118
119	typeset mntpnt=$(get_prop mountpoint $pool)
120
121	while true; do
122		$DD if=/dev/random of=$mntpnt/foo count=10
123		$SYNC
124		$SLEEP 1
125	done &
126	BG_PID=$!
127
128	return 0
129}
130
131#
132# Kill the background write process.
133#
134function kill_bg_write
135{
136	typeset -i ret=0
137
138	if [[ -n $BG_PID ]]; then
139		kill -9 $BG_PID
140		ret=$?
141
142		if ((ret == 0)); then
143			BG_PID=''
144		fi
145	fi
146
147	$SLEEP 10
148	return $ret
149}
150
151#
152# Insert a given file into a given device slot
153#
154# $1 file
155# $2 device
156#
157function insert_device
158{
159	typeset file=$1
160	typeset device=$2
161
162	if [[ -z $file ]]; then
163		return 1
164	fi
165
166	#
167	# Make sure insert device succeed within 60 seconds
168	#
169	typeset -i i=0
170	while ((i < 6)); do
171		$SLEEP 10
172
173		$LOFIADM -a $file $device -f > /dev/null 2>&1
174		if (($? == 0)); then
175			return 0
176		fi
177
178		((i += 1))
179	done
180
181	return 1
182}
183
184#
185# Remove the given lofi device
186#
187# $1 device or file
188#
189function remove_device
190{
191	typeset devfile=$1
192
193	if [[ -z $devfile ]]; then
194		return 1
195	fi
196
197	#
198	# Make sure remove device succeed within 60 seconds
199	#
200	typeset -i i=0
201	while ((i < 6)); do
202		$SLEEP 10
203		$LOFIADM -d $devfile -f
204		if (($? == 0)); then
205			return 0
206		fi
207
208		((i += 1))
209	done
210
211	return 1
212}
213
214#
215# Verify the given devices have expected status in pool
216#
217# $1 pool
218# $2 device
219# $3 expected status
220#
221function verify_device_status
222{
223	typeset pool=$1
224	typeset device=$2
225	typeset expect_stat=$3
226
227	if [[ -z $pool || -z $expect_stat || -z $device ]]; then
228		log_note "Usage: verify_device_status <pool> <device> <status>"
229		return 1
230	fi
231
232	#
233	# 1.5 minute disk status checking, make sure zpool sync disk status.
234	#
235	typeset -i i=0
236	while ((i < 9)); do
237		$SLEEP 10
238
239		typeset str=$($ZPOOL status $pool | $GREP "lofi" | \
240			$AWK '{print $1 " " $2}')
241		typeset real_stat=${str##*$device }
242		real_stat=$($ECHO $real_stat | $AWK '{print $1}')
243
244		if [[ "$expect_stat" == "$real_stat" ]]; then
245			return 0
246		fi
247
248		((i += 1))
249	done
250
251	log_note "Expected status($expect_stat), " \
252		 "see status($real_stat) for $device"
253	$ZPOOL status -v $pool
254
255	return 1
256}
257
258#
259# Output fma event id to given file, the default output file is $FILE_EVENT_ID
260#
261function getfmri
262{
263	eval typeset output_file=${1:-$FILE_EVENT_ID}
264#
265# fmadm faulty output include several sections below
266#
267
268# --------------- ------------------------------------  -------------- ---------
269# TIME            EVENT-ID                              MSG-ID         SEVERITY
270# --------------- ------------------------------------  -------------- ---------
271# Aug 31 22:34:19 ec648a9e-0c9f-c495-e176-e38ba212e278  ZFS-8000-D3    Major
272# Aug 31 19:44:59 d69cdd12-b0cf-62ea-d0a3-8d2e9ebfeb50  ZFS-8000-D3
273# Aug 31 19:35:16 7213f0d5-00d4-ea32-ddfc-98cdd683c27e  ZFS-8000-D3
274# Aug 31 19:29:11 33424bef-a973-4dae-94ef-cb97f2cb0759  ZFS-8000-D3
275# Aug 31 17:07:26 74219b66-ead4-6d2b-bbad-bc40547ca02e  ZFS-8000-GH
276#
277# Fault class : fault.fs.zfs.device
278#
279# Description : A ZFS device failed.  Refer to http://sun.com/msg/ZFS-8000-D3 for
280#               more information.
281#
282# Response    : No automated response will occur.
283#
284# Impact      : Fault tolerance of the pool may be compromised.
285#
286# Action      : Run 'zpool status -x' and replace the bad device.
287#
288	$FMADM faulty | $NAWK '
289		BEGIN {
290			start = 0
291		}
292		/^---/ && /---$/ {
293			if (start == 0) {
294				start = 1
295			}
296		}
297		/^TIME/ && /SEVERITY$/ {
298			if (start == 1) {
299				start = 2
300			}
301		}
302		/^---/ && /---$/ {
303			if (start == 2) {
304				start = 3
305				continue
306			}
307		}
308		/^$/ {
309			start = 0
310		}
311		(start == 3) {print $4}' > $output_file
312}
313
314#
315# Verify if ZFS FMA faulty error message are generated.
316#
317# $1 TRUE or FALSE
318#
319function fma_faulty
320{
321	#
322	# 1.5 minute for FMA faulty checking, make sure FMA sync with ZFS status
323	#
324	typeset expect=${1:-TRUE}
325
326	typeset -i fsize
327	typeset -i i=0
328	while ((i < 9)); do
329		$SLEEP 10
330
331		#
332		# try to get fma faulty
333		#
334		getfmri $FILE_EVENT_ID
335		fsize=$($LS -ld $FILE_EVENT_ID | $AWK '{print $5}')
336
337		case $expect in
338			TRUE)
339				if (( fsize != 0 )); then
340					return 0
341				fi
342				;;
343			FALSE)
344				if (( fsize == 0 )); then
345					return 0
346				fi
347				;;
348			*)
349				return 1
350		esac
351
352		((i += 1))
353	done
354
355	return 1
356}
357
358#
359# Create fresh file
360#
361# $1 file size
362# $2 file name
363#
364function create_file
365{
366	typeset size=$1
367	typeset file=$2
368
369	if [[ -z $size || -z $file ]]; then
370		log_note "Usage: create_file <size> <file>"
371		return 1
372	fi
373	if [[ -f $file ]]; then
374		$RM -f $file
375	fi
376	$MKFILE $size $file
377	return $?
378}
379
380#
381# Unmount all filesystem, and disable syseventd and fmd piror to
382# unloading ZFS module
383#
384function unload_zfs
385{
386	# destroy /dev/zvol link
387	log_must $ZFS volfini
388
389	log_must $ZFS unmount -f -a
390	log_must $SVCADM disable -t sysevent fmd
391	$SLEEP 10
392
393	#
394	# 1 minute for ZFS module unload checking
395	#
396	# For example:
397	#
398	# 192 fffffffff7c92000  99858 182   1  zfs (ZFS storage pool version 6)
399	#
400	typeset -i i=0
401	while ((i < 10)); do
402		typeset id=$($MODINFO | $GREP "ZFS storage" | $AWK '{print $1}')
403
404		if [[ -n $id ]]; then
405			$MODUNLOAD -i $id
406			if (($? == 0)) ; then
407				return 0
408			fi
409		else
410			return 0
411		fi
412
413		$SLEEP 6
414		((i += 1))
415	done
416
417	return 1
418}
419
420#
421#  Load ZFS module and remount all filesystem
422#
423function load_zfs
424{
425	typeset -i ret=0
426	$SVCADM enable sysevent fmd
427	((ret |= $?))
428
429	$SLEEP 10
430
431	$ZFS mount -a
432	((ret |= $?))
433
434	# create /dev/zvol link
435	$ZFS volinit
436	((ret |= $?))
437
438	return $ret
439}
440
441#
442# Convert file name to device name or reverse.
443#
444# $1-n lofi files or devices
445#
446function convert_lofi
447{
448	typeset n list
449
450	for n in "$@"; do
451		typeset item=$($LOFIADM $n)
452		list="$list $item"
453
454		shift
455	done
456
457	$ECHO $list
458}
459