1#!/bin/ksh -p
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 https://opensource.org/licenses/CDDL-1.0.
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 2007 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26#
27
28#
29# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
30#
31
32. $STF_SUITE/include/libtest.shlib
33. $STF_SUITE/tests/functional/cli_root/zpool_clear/zpool_clear.cfg
34
35#
36# DESCRIPTION:
37# Verify 'zpool clear' can clear pool errors.
38#
39# STRATEGY:
40# 1. Create various configuration pools
41# 2. Make errors to pool
42# 3. Use zpool clear to clear errors
43# 4. Verify the errors has been cleared.
44#
45
46verify_runnable "global"
47
48function cleanup
49{
50        poolexists $TESTPOOL1 && \
51                log_must zpool destroy -f $TESTPOOL1
52
53	log_must rm -f $fbase.{0..2}
54}
55
56
57log_assert "Verify 'zpool clear' can clear errors of a storage pool."
58log_onexit cleanup
59
60#make raw files to create various configuration pools
61fbase=$TEST_BASE_DIR/file
62log_must truncate -s $FILESIZE $fbase.{0..2}
63set -A poolconf "mirror $fbase.0 $fbase.1 $fbase.2" \
64                "raidz1 $fbase.0 $fbase.1 $fbase.2" \
65                "raidz2 $fbase.0 $fbase.1 $fbase.2"
66
67function check_err # <pool> [<vdev>]
68{
69	typeset pool=$1
70	typeset	checkvdev=$2
71
72	[ "$(zpool status -x $pool)" = "pool '$pool' is healthy" ] && return
73
74	typeset -i skipstart=1
75	typeset vdev _ c_read c_write c_cksum rest
76	while read -r vdev _ c_read c_write c_cksum rest; do
77		if [ $skipstart -ne 0 ]; then
78			[ "$vdev" = "NAME" ] && skipstart=0
79                        continue
80                fi
81
82		if [ -n "$checkvdev" ]; then
83			[ "$vdev" = "$checkvdev" ] || continue
84		fi
85
86		[ $c_read$c_write$c_cksum = 000 ] || return
87	done < <(zpool status -x $pool | grep -ve "^$" -e "pool:" -e "state:" -e "config:" -e "errors:")
88}
89
90function do_testing #<clear type> <vdevs>
91{
92	typeset FS=$TESTPOOL1/fs
93	typeset file=/$FS/f
94	typeset type=$1
95	shift
96	typeset vdev="$@"
97	(( i = $RANDOM % 3 ))
98
99	log_must zpool create -f $TESTPOOL1 $vdev
100	log_must zfs create $FS
101	#
102	# Partially fill up the zfs filesystem in order to make data block
103	# errors.  It's not necessary to fill the entire filesystem.
104	#
105	avail=$(get_prop available $FS)
106	fill_mb=$(((avail / 1024 / 1024) * 25 / 100))
107	log_must dd if=/dev/urandom of=$file bs=$BLOCKSZ count=$fill_mb
108
109	#
110	# Make errors to the testing pool by overwrite the vdev device with
111	# dd command. We do not want to have a full overwrite. That
112	# may cause the system panic. So, we should skip the vdev label space.
113	#
114	typeset -i wcount=0
115	typeset -i size
116	case $FILESIZE in
117		*g|*G)
118			(( size = ${FILESIZE%%[g|G]} ))
119			(( wcount = size*1024*1024 - 512 ))
120			;;
121		*m|*M)
122			(( size = ${FILESIZE%%[m|M]} ))
123			(( wcount = size*1024 - 512 ))
124			;;
125		*k|*K)
126			(( size = ${FILESIZE%%[k|K]} ))
127			(( wcount = size - 512 ))
128			;;
129		*)
130			(( wcount = FILESIZE/1024 - 512 ))
131			;;
132	esac
133	dd if=/dev/zero of=$fbase.$i seek=512 bs=1024 count=$wcount conv=notrunc 2>/dev/null
134	sync_all_pools
135	log_must sync #ensure the vdev files are written out
136	log_must zpool scrub -w $TESTPOOL1
137
138	log_mustnot check_err $TESTPOOL1
139	typeset dev=
140	if [ "$type" = "device" ]; then
141		dev=$fbase.$i
142	fi
143
144	log_must zpool clear $TESTPOOL1 $dev
145	log_must check_err $TESTPOOL1 $dev
146
147	log_must zpool destroy $TESTPOOL1
148}
149
150log_note "'zpool clear' clears leaf-device error."
151for devconf in "${poolconf[@]}"; do
152	do_testing "device" $devconf
153done
154log_note "'zpool clear' clears top-level pool error."
155for devconf in "${poolconf[@]}"; do
156	do_testing "pool" $devconf
157done
158
159log_pass "'zpool clear' clears pool errors as expected."
160