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 2009 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26
27. $STF_SUITE/include/libtest.kshlib
28. $STF_SUITE/tests/cli_root/zfs_set/zfs_set_common.kshlib
29. $STF_SUITE/tests/cache/cache.kshlib
30
31function cleanup_env
32{
33	inject_clear
34	poolexists $TESTPOOL && \
35		destroy_pool $TESTPOOL
36	[[ -d $TESTDIR ]] && \
37		log_must $RM -rf $TESTDIR
38}
39
40#
41# Inject an error into object
42# 	$1: data,dnode,mos,mosdir,config,bplist,spacemap,metaslab,errlog
43#	$2: if $1 is data or dnode, $2 should be a file or dir.
44#		otherwise, $2 should be poolname
45#	$3: "io" or "checksum"
46#	$4: expect return value of zinject, default is 0
47#
48function inject_fault #type, object, error, expect
49{
50	typeset type=$1
51	typeset object=$2
52	typeset error=${3:-io}
53	typeset -i expect=${4:-0}
54
55	if (( expect == 0 )); then
56		log_must eval '$ZINJECT -t $type -e $error \
57			-m -a -q $object > /dev/null 2>&1'
58	else
59		log_mustnot eval '$ZINJECT -t $type -e $error \
60			-m -a -q $object > /dev/null 2>&1'
61	fi
62	$SLEEP 1
63	return 0
64}
65
66#
67# Clear all registrated handler and do scrub to keep integrity
68#
69function inject_clear
70{
71	log_must eval '$ZINJECT -c all > /dev/null 2>&1'
72	$SLEEP 1
73	if poolexists $TESTPOOL ; then
74		while ! check_pool_status $TESTPOOL "state" "ONLINE" ; do
75			log_must $ZPOOL clear $TESTPOOL
76			$SLEEP 2
77		done
78		log_must $ZPOOL scrub $TESTPOOL
79		while ! is_pool_scrubbed $TESTPOOL && ! is_pool_resilvered $TESTPOOL ; do
80			$SLEEP 2
81		done
82	fi
83	return 0
84}
85
86#
87# Inject a fault into a particular device
88#	$1: device name
89#	$2: pool name
90#	$3: errno, can either be 'nxio' (the default) or 'io'.
91#
92function inject_device #device, pool, errno
93{
94	typeset device=$1
95	typeset pool=$2
96	typeset errno=$3
97
98	log_must eval '$ZINJECT -d $device -e $errno -q $pool > /dev/null 2>&1'
99	$SLEEP 1
100	return 0
101}
102
103#
104# Check if the ereport is occurred after the given timestamp
105#
106function check_ereport #timestamp, etype
107{
108	typeset etime=$1
109	typeset ereport
110	typeset -i i=0
111	typeset -i maxtimes=20
112
113	shift
114
115	for type in $@ ; do
116		i=0
117		while (( i < maxtimes )); do
118			(( i = i + 1 ))
119			ereport=$($FMDUMP -t "$etime" -e -v -c $type | \
120				$NAWK '(NR != 1) {print $0}')
121			if [[ -n $ereport ]]; then
122				break
123			elif (( i == maxtimes )) ; then
124				$FMDUMP -t "$etime" -e -v
125				log_fail "$type not found"
126			fi
127			$SLEEP 3
128		done
129	done
130	return 0
131}
132
133#
134# Check if the fault is occurred after the given timestamp
135#
136function check_fault #timestamp, fault_class
137{
138	typeset after_time=$1
139	typeset ereport
140	typeset -i i=0
141	typeset -i maxtimes=20
142
143	shift
144
145	for fault in $@ ; do
146		i=0
147		while (( i < maxtimes )); do
148			(( i = i + 1 ))
149			ereport=$($FMDUMP -av -t "$after_time" | $GREP $fault)
150			if [[ -n $ereport ]]; then
151				break
152			elif (( i == maxtimes )) ; then
153				$FMDUMP -av -t "$after_time"
154				log_fail "$fault not found"
155			fi
156			$SLEEP 3
157		done
158	done
159	return 0
160}
161
162#
163# Check if 'zpool status -v' contain the permanent error as expected
164#
165function check_status #poolname, errors
166{
167	typeset poolname=$1
168	typeset errors=$2
169
170	for err in $errors ; do
171		ereport=$($ZPOOL status -v $poolname | $GREP "$err")
172		if [[ -z $ereport ]]; then
173			$ZPOOL status -v $poolname
174			log_fail "$err not found"
175		fi
176	done
177	return 0
178}
179
180#
181# Invoke the trigger function according to the fault type corresponded
182#
183function trigger_inject #etype, object, objtype
184{
185	typeset etype=$1
186	typeset object=$2
187	typeset objtype=$3
188
189	if [[ $etype == "bplist" ]] ; then
190		$ECHO "ZFS Fault Harness" > $object
191	fi
192
193	case $objtype in
194		dir)
195			$LS -l $object > /dev/null 2>&1
196			;;
197		file)
198			$CAT $object > /dev/null 2>&1
199			;;
200	esac
201}
202
203function populate_test_env #basedir #count
204{
205	typeset basedir=$1
206	typeset -i count=$2
207	typeset -i i=1
208
209	if [[ -d $basedir ]]; then
210		log_must $RM -rf $basedir/*
211	else
212		log_must $MKDIR -p $basedir
213	fi
214
215	while (( i <= count )); do
216		$ECHO "ZFS Fault Harness" > $basedir/testfile.$i
217		$MKDIR -p $basedir/testdir.$i
218		(( i = i + 1 ))
219	done
220
221	return 0
222}
223