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, 2018 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. Checkpoint the pool as one last attempt to preserve old blocks.
32#	8. Overwrite the files.
33#	9. Export the pool.
34#	10. Verify that we can rewind the pool to the noted txg.
35#	11. Verify that the files are readable and retain their old data.
36#
37# DISCLAIMER:
38#	This test can fail since nothing guarantees that old MOS blocks aren't
39#	overwritten. Snapshots protect datasets and data files but not the MOS.
40#	sync_some_data_a_few_times interleaves file data and MOS data for a few
41#	txgs, thus increasing the odds that some txgs will have their MOS data
42#	left untouched.
43#
44
45verify_runnable "global"
46
47function custom_cleanup
48{
49	set_vdev_validate_skip 0
50	cleanup
51	log_must mdb_ctf_set_int zfs_vdev_min_ms_count 0t16
52	log_must mdb_ctf_set_int spa_allocators 0t4
53}
54
55log_onexit custom_cleanup
56
57function test_common
58{
59	typeset poolcreate="$1"
60	typeset addvdevs="$2"
61	typeset attachargs="${3:-}"
62	typeset detachvdev="${4:-}"
63	typeset removevdev="${5:-}"
64	typeset finalpool="${6:-}"
65
66	typeset poolcheck="$poolcreate"
67
68	log_must zpool create $TESTPOOL1 $poolcreate
69
70	log_must generate_data $TESTPOOL1 $MD5FILE
71
72	# syncing a few times while writing new data increases the odds that MOS
73	# metadata for some of the txgs will survive
74	log_must sync_some_data_a_few_times $TESTPOOL1
75	typeset txg
76	txg=$(get_last_txg_synced $TESTPOOL1)
77	log_must zfs snapshot -r $TESTPOOL1@snap1
78
79	#
80	# Perform config change operations
81	#
82	if [[ -n $addvdevs ]]; then
83		log_must zpool add -f $TESTPOOL1 $addvdevs
84	fi
85	if [[ -n $attachargs ]]; then
86		log_must zpool attach $TESTPOOL1 $attachargs
87	fi
88	if [[ -n $detachvdev ]]; then
89		log_must zpool detach $TESTPOOL1 $detachvdev
90	fi
91	if [[ -n $removevdev ]]; then
92		[[ -z $finalpool ]] &&
93		    log_fail "Must provide final pool status!"
94		log_must zpool remove $TESTPOOL1 $removevdev
95		log_must wait_for_pool_config $TESTPOOL1 "$finalpool"
96	fi
97	if [[ -n $pathstochange ]]; then
98		#
99		# Change device paths and re-import pool to update labels
100		#
101		zpool export $TESTPOOL1
102		for dev in $pathstochange; do
103			log_must mv $dev "${dev}_new"
104			poolcheck=$(echo "$poolcheck" | \
105			    sed "s:$dev:${dev}_new:g")
106		done
107		zpool import -d $DEVICE_DIR $TESTPOOL1
108	fi
109
110	#
111	# In an attempt to leave MOS data untouched so extreme
112	# rewind is successful during import we checkpoint the
113	# pool and hope that these MOS data are part of the
114	# checkpoint (e.g they stay around). If this goes as
115	# expected, then extreme rewind should rewind back even
116	# further than the time that we took the checkpoint.
117	#
118	# Note that, ideally we would want to take a checkpoint
119	# right after we recond the txg we plan to rewind to.
120	# But since we can't attach, detach or remove devices
121	# while having a checkpoint, we take it after the
122	# operation that changes the config.
123	#
124	log_must zpool checkpoint $TESTPOOL1
125
126	log_must overwrite_data $TESTPOOL1 ""
127
128	log_must zpool export $TESTPOOL1
129
130	log_must zpool import -d $DEVICE_DIR -T $txg $TESTPOOL1
131	log_must check_pool_config $TESTPOOL1 "$poolcheck"
132
133	log_must verify_data_md5sums $MD5FILE
134
135	# Cleanup
136	log_must zpool destroy $TESTPOOL1
137	if [[ -n $pathstochange ]]; then
138		for dev in $pathstochange; do
139			log_must mv "${dev}_new" $dev
140		done
141	fi
142	# Fast way to clear vdev labels
143	log_must zpool create -f $TESTPOOL2 $VDEV0 $VDEV1 $VDEV2 $VDEV3 $VDEV4
144	log_must zpool destroy $TESTPOOL2
145
146	log_note ""
147}
148
149function test_add_vdevs
150{
151	typeset poolcreate="$1"
152	typeset addvdevs="$2"
153
154	log_note "$0: pool '$poolcreate', add $addvdevs."
155
156	test_common "$poolcreate" "$addvdevs"
157}
158
159function test_attach_vdev
160{
161	typeset poolcreate="$1"
162	typeset attachto="$2"
163	typeset attachvdev="$3"
164
165	log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto."
166
167	test_common "$poolcreate" "" "$attachto $attachvdev"
168}
169
170function test_detach_vdev
171{
172	typeset poolcreate="$1"
173	typeset detachvdev="$2"
174
175	log_note "$0: pool '$poolcreate', detach $detachvdev."
176
177	test_common "$poolcreate" "" "" "$detachvdev"
178}
179
180function test_attach_detach_vdev
181{
182	typeset poolcreate="$1"
183	typeset attachto="$2"
184	typeset attachvdev="$3"
185	typeset detachvdev="$4"
186
187	log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto," \
188	    "then detach $detachvdev."
189
190	test_common "$poolcreate" "" "$attachto $attachvdev" "$detachvdev"
191}
192
193function test_remove_vdev
194{
195	typeset poolcreate="$1"
196	typeset removevdev="$2"
197	typeset finalpool="$3"
198
199	log_note "$0: pool '$poolcreate', remove $removevdev."
200
201	test_common "$poolcreate" "" "" "" "$removevdev" "$finalpool"
202}
203
204# Make the devices bigger to reduce chances of overwriting MOS metadata.
205increase_device_sizes $(( FILE_SIZE * 4 ))
206
207# Increase the number of metaslabs for small pools temporarily to
208# reduce the chance of reusing a metaslab that holds old MOS metadata.
209log_must mdb_ctf_set_int zfs_vdev_min_ms_count 0t150
210
211# Decrease the number of allocators for pools created during this test,
212# to increase the odds that metadata survives from old txgs.
213log_must mdb_ctf_set_int spa_allocators 0t1
214
215# Part of the rewind test is to see how it reacts to path changes
216typeset pathstochange="$VDEV0 $VDEV1 $VDEV2 $VDEV3"
217
218log_note " == test rewind after device addition == "
219
220test_add_vdevs "$VDEV0" "$VDEV1"
221test_add_vdevs "$VDEV0 $VDEV1" "$VDEV2"
222test_add_vdevs "$VDEV0" "$VDEV1 $VDEV2"
223test_add_vdevs "mirror $VDEV0 $VDEV1" "mirror $VDEV2 $VDEV3"
224test_add_vdevs "$VDEV0" "raidz $VDEV1 $VDEV2 $VDEV3"
225test_add_vdevs "$VDEV0" "log $VDEV1"
226test_add_vdevs "$VDEV0 log $VDEV1" "$VDEV2"
227
228log_note " == test rewind after device attach == "
229
230test_attach_vdev "$VDEV0" "$VDEV0" "$VDEV1"
231test_attach_vdev "mirror $VDEV0 $VDEV1" "$VDEV0" "$VDEV2"
232test_attach_vdev "$VDEV0 $VDEV1" "$VDEV0" "$VDEV2"
233
234log_note " == test rewind after device removal == "
235
236# Once we remove a device it will be overlooked in the device scan, so we must
237# preserve its original path
238pathstochange="$VDEV0 $VDEV2"
239test_remove_vdev "$VDEV0 $VDEV1 $VDEV2" "$VDEV1" "$VDEV0 $VDEV2"
240
241#
242# Path change and detach are incompatible. Detach changes the guid of the vdev
243# so we have no direct way to link the new path to an existing vdev.
244#
245pathstochange=""
246
247log_note " == test rewind after device detach == "
248
249test_detach_vdev "mirror $VDEV0 $VDEV1" "$VDEV1"
250test_detach_vdev "mirror $VDEV0 $VDEV1 mirror $VDEV2 $VDEV3" "$VDEV1"
251test_detach_vdev "$VDEV0 log mirror $VDEV1 $VDEV2" "$VDEV2"
252
253log_note " == test rewind after device attach followed by device detach == "
254
255#
256# We need to disable vdev validation since once we detach VDEV1, VDEV0 will
257# inherit the mirror tvd's guid and lose its original guid.
258#
259set_vdev_validate_skip 1
260test_attach_detach_vdev "$VDEV0" "$VDEV0" "$VDEV1" "$VDEV1"
261set_vdev_validate_skip 0
262
263log_pass "zpool import rewind after configuration change passed."
264