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