1#!/usr/local/bin/ksh93 -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 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 2013 Spectra Logic.  All rights reserved.
27# Use is subject to license terms.
28#
29# ident	"@(#)zfsd_zfsd_002_pos.ksh	1.0	12/08/10 SL"
30#
31. $STF_SUITE/tests/hotspare/hotspare.kshlib
32. $STF_SUITE/tests/zfsd/zfsd.kshlib
33. $STF_SUITE/include/libgnop.kshlib
34
35################################################################################
36#
37# __stc_assertion_start
38#
39# ID: zfsd_import_001_pos
40#
41# DESCRIPTION:
42#   If a removed drive gets reinserted while the pool is exported, it will
43#   replace its spare when reimported.
44#
45#   This also applies to drives that get reinserted while the machine is
46#   powered off.
47#
48#
49# STRATEGY:
50#	1. Create 1 storage pools with hot spares.
51#	2. Remove one disk
52#	3. Verify that the spare is in use.
53#	4. Export the pool
54#	5. Recreate the vdev
55#	6. Import the pool
56#	7. Verify that the vdev gets resilvered and the spare gets removed
57#	8. Use additional zpool history data to verify that the pool
58#	   finished resilvering _before_ zfsd detached the spare.
59#
60# TESTABILITY: explicit
61#
62# TEST_AUTOMATION_LEVEL: automated
63#
64# CODING STATUS: COMPLETED (2012-08-10)
65#
66# __stc_assertion_end
67#
68###############################################################################
69
70verify_runnable "global"
71
72function verify_assertion # spare_dev
73{
74	typeset spare_dev=$1
75	log_must destroy_gnop $REMOVAL_DISK
76
77	# Check to make sure ZFS sees the disk as removed
78	wait_for_pool_removal 20
79
80	# Wait for zfsd to activate the spare
81	wait_for_pool_dev_state_change 20 $spare_dev INUSE
82	log_must $ZPOOL status $TESTPOOL
83
84	# Export the pool
85	log_must $ZPOOL export $TESTPOOL
86
87	# Re-enable the  missing disk
88	log_must create_gnop $REMOVAL_DISK
89
90	# Import the pool
91	log_must $ZPOOL import $TESTPOOL
92
93	# Check that the disk has rejoined the pool
94	wait_for_pool_dev_state_change 20 $REMOVAL_DISK ONLINE
95
96	# Check that the pool resilvered
97	while ! is_pool_resilvered $TESTPOOL; do
98		$SLEEP 2
99	done
100	log_must $ZPOOL status $TESTPOOL
101
102	#Finally, check that the spare deactivated
103	wait_for_pool_dev_state_change 20 $spare_dev AVAIL
104
105	# Verify that the spare was detached after the scrub was complete
106	# Note that resilvers and scrubs are recorded identically in zpool
107	# history
108	$ZPOOL history -i $TESTPOOL | awk '
109		BEGIN {
110			scrub_txg=0;
111			detach_txg=0
112		}
113		/scrub done/ {
114			split($6, s, "[:\\]]");
115			t=s[2];
116			scrub_txg = scrub_txg > t ? scrub_txg : t
117		}
118		/vdev detach/ {
119			split($6, s, "[:\\]]");
120			t=s[2];
121			done_txg = done_txg > t ? done_txg : t
122		}
123		END {
124			print("Scrub completed at txg", scrub_txg);
125			print("Spare detached at txg", detach_txg);
126			exit(detach_txg > scrub_txg)
127		}'
128	[ $? -ne 0 ] && log_fail "The spare detached before the resilver completed"
129}
130
131
132log_assert "If a removed drive gets reinserted while the pool is exported, \
133	    it will replace its spare when reinserted."
134
135ensure_zfsd_running
136
137typeset REMOVAL_DISK=$DISK0
138typeset REMOVAL_NOP=${DISK0}.nop
139typeset SPARE_DISK=$DISK4
140typeset SPARE_NOP=${DISK4}.nop
141typeset OTHER_DISKS="${DISK1} ${DISK2} ${DISK3}"
142typeset OTHER_NOPS=${OTHER_DISKS//~(E)([[:space:]]+|$)/.nop\1}
143set -A MY_KEYWORDS "mirror" "raidz1" "raidz2"
144ensure_zfsd_running
145log_must create_gnops $REMOVAL_DISK $OTHER_DISKS $SPARE_DISK
146for keyword in "${MY_KEYWORDS[@]}" ; do
147	log_must create_pool $TESTPOOL $keyword $REMOVAL_NOP $OTHER_NOPS spare $SPARE_NOP
148	verify_assertion
149	destroy_pool "$TESTPOOL"
150done
151
152log_pass
153