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