1#!/usr/bin/ksh -p
2
3#
4# This file and its contents are supplied under the terms of the
5# Common Development and Distribution License ("CDDL"), version 1.0.
6# You may only use this file in accordance with the terms of version
7# 1.0 of the CDDL.
8#
9# A full copy of the text of the CDDL should have accompanied this
10# source.  A copy of the CDDL is also available via the Internet at
11# http://www.illumos.org/license/CDDL.
12#
13
14#
15# Copyright (c) 2016 by Delphix. All rights reserved.
16#
17
18. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
19
20#
21# DESCRIPTION:
22#	It should be possible to rewind a pool beyond a configuration change.
23#
24# STRATEGY:
25#	1. Create a pool.
26#	2. Generate files and remember their md5sum.
27#	3. Note last synced txg.
28#	4. Take a snapshot to make sure old blocks are not overwritten.
29#	5. Perform zpool add/attach/detach/remove operation.
30#	6. Change device paths if requested and re-import pool.
31#	7. Overwrite the files.
32#	8. Export the pool.
33#	9. Verify that we can rewind the pool to the noted txg.
34#	10. Verify that the files are readable and retain their old data.
35#
36# DISCLAIMER:
37#	This test can fail since nothing guarantees that old MOS blocks aren't
38#	overwritten. Snapshots protect datasets and data files but not the MOS.
39#	sync_some_data_a_few_times interleaves file data and MOS data for a few
40#	txgs, thus increasing the odds that some txgs will have their MOS data
41#	left untouched.
42#
43
44verify_runnable "global"
45
46function custom_cleanup
47{
48	set_vdev_validate_skip 0
49	cleanup
50}
51
52log_onexit custom_cleanup
53
54function test_common
55{
56	typeset poolcreate="$1"
57	typeset addvdevs="$2"
58	typeset attachargs="${3:-}"
59	typeset detachvdev="${4:-}"
60	typeset removevdev="${5:-}"
61	typeset finalpool="${6:-}"
62
63	typeset poolcheck="$poolcreate"
64
65	log_must zpool create $TESTPOOL1 $poolcreate
66
67	log_must generate_data $TESTPOOL1 $MD5FILE
68
69	# syncing a few times while writing new data increases the odds that MOS
70	# metadata for some of the txgs will survive
71	log_must sync_some_data_a_few_times $TESTPOOL1
72	typeset txg
73	txg=$(get_last_txg_synced $TESTPOOL1)
74	log_must zfs snapshot -r $TESTPOOL1@snap1
75
76	#
77	# Perform config change operations
78	#
79	if [[ -n $addvdev ]]; then
80		log_must zpool add -f $TESTPOOL1 $addvdev
81	fi
82	if [[ -n $attachargs ]]; then
83		log_must zpool attach $TESTPOOL1 $attachargs
84	fi
85	if [[ -n $detachvdev ]]; then
86		log_must zpool detach $TESTPOOL1 $detachvdev
87	fi
88	if [[ -n $removevdev ]]; then
89		[[ -z $finalpool ]] &&
90		    log_fail "Must provide final pool status!"
91		log_must zpool remove $TESTPOOL1 $removevdev
92		log_must wait_for_pool_config $TESTPOOL1 "$finalpool"
93	fi
94	if [[ -n $pathstochange ]]; then
95		#
96		# Change device paths and re-import pool to update labels
97		#
98		sudo zpool export $TESTPOOL1
99		for dev in $pathstochange; do
100			log_must mv $dev "${dev}_new"
101			poolcheck=$(echo "$poolcheck" | \
102			    sed "s:$dev:${dev}_new:g")
103		done
104		sudo zpool import -d $DEVICE_DIR $TESTPOOL1
105	fi
106
107	log_must overwrite_data $TESTPOOL1 ""
108
109	log_must zpool export $TESTPOOL1
110
111	log_must zpool import -d $DEVICE_DIR -T $txg $TESTPOOL1
112	log_must check_pool_config $TESTPOOL1 "$poolcheck"
113
114	log_must verify_data_md5sums $MD5FILE
115
116	# Cleanup
117	log_must zpool destroy $TESTPOOL1
118	if [[ -n $pathstochange ]]; then
119		for dev in $pathstochange; do
120			log_must mv "${dev}_new" $dev
121		done
122	fi
123	# Fast way to clear vdev labels
124	log_must zpool create -f $TESTPOOL2 $VDEV0 $VDEV1 $VDEV2 $VDEV3 $VDEV4
125	log_must zpool destroy $TESTPOOL2
126
127	log_note ""
128}
129
130function test_add_vdevs
131{
132	typeset poolcreate="$1"
133	typeset addvdevs="$2"
134
135	log_note "$0: pool '$poolcreate', add $addvdevs."
136
137	test_common "$poolcreate" "$addvdevs"
138}
139
140function test_attach_vdev
141{
142	typeset poolcreate="$1"
143	typeset attachto="$2"
144	typeset attachvdev="$3"
145
146	log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto."
147
148	test_common "$poolcreate" "" "$attachto $attachvdev"
149}
150
151function test_detach_vdev
152{
153	typeset poolcreate="$1"
154	typeset detachvdev="$2"
155
156	log_note "$0: pool '$poolcreate', detach $detachvdev."
157
158	test_common "$poolcreate" "" "" "$detachvdev"
159}
160
161function test_attach_detach_vdev
162{
163	typeset poolcreate="$1"
164	typeset attachto="$2"
165	typeset attachvdev="$3"
166	typeset detachvdev="$4"
167
168	log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto," \
169	    "then detach $detachvdev."
170
171	test_common "$poolcreate" "" "$attachto $attachvdev" "$detachvdev"
172}
173
174function test_remove_vdev
175{
176	typeset poolcreate="$1"
177	typeset removevdev="$2"
178	typeset finalpool="$3"
179
180	log_note "$0: pool '$poolcreate', remove $removevdev."
181
182	test_common "$poolcreate" "" "" "" "$removevdev" "$finalpool"
183}
184
185# Make the devices bigger to reduce chances of overwriting MOS metadata.
186increase_device_sizes $(( FILE_SIZE * 4 ))
187
188# Part of the rewind test is to see how it reacts to path changes
189typeset pathstochange="$VDEV0 $VDEV1 $VDEV2 $VDEV3"
190
191log_note " == test rewind after device addition == "
192
193test_add_vdevs "$VDEV0" "$VDEV1"
194test_add_vdevs "$VDEV0 $VDEV1" "$VDEV2"
195test_add_vdevs "$VDEV0" "$VDEV1 $VDEV2"
196test_add_vdevs "mirror $VDEV0 $VDEV1" "mirror $VDEV2 $VDEV3"
197test_add_vdevs "$VDEV0" "raidz $VDEV1 $VDEV2 $VDEV3"
198test_add_vdevs "$VDEV0" "log $VDEV1"
199test_add_vdevs "$VDEV0 log $VDEV1" "$VDEV2"
200
201log_note " == test rewind after device attach == "
202
203test_attach_vdev "$VDEV0" "$VDEV0" "$VDEV1"
204test_attach_vdev "mirror $VDEV0 $VDEV1" "$VDEV0" "$VDEV2"
205test_attach_vdev "$VDEV0 $VDEV1" "$VDEV0" "$VDEV2"
206
207log_note " == test rewind after device removal == "
208
209# Once we remove a device it will be overlooked in the device scan, so we must
210# preserve its original path
211pathstochange="$VDEV0 $VDEV2"
212test_remove_vdev "$VDEV0 $VDEV1 $VDEV2" "$VDEV1" "$VDEV0 $VDEV2"
213
214#
215# Path change and detach are incompatible. Detach changes the guid of the vdev
216# so we have no direct way to link the new path to an existing vdev.
217#
218pathstochange=""
219
220log_note " == test rewind after device detach == "
221
222test_detach_vdev "mirror $VDEV0 $VDEV1" "$VDEV1"
223test_detach_vdev "mirror $VDEV0 $VDEV1 mirror $VDEV2 $VDEV3" "$VDEV1"
224test_detach_vdev "$VDEV0 log mirror $VDEV1 $VDEV2" "$VDEV2"
225
226log_note " == test rewind after device attach followed by device detach == "
227
228#
229# We need to disable vdev validation since once we detach VDEV1, VDEV0 will
230# inherit the mirror tvd's guid and lose its original guid.
231#
232set_vdev_validate_skip 1
233test_attach_detach_vdev "$VDEV0" "$VDEV0" "$VDEV1" "$VDEV1"
234set_vdev_validate_skip 0
235
236log_pass "zpool import rewind after configuration change passed."
237