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