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/zfs_mount/zfs_mount.kshlib
34. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
35
36#
37# DESCRIPTION:
38#	Once a pool has been exported, but one or more devices are
39#	overlapped with other exported pool, import should handle
40#	this kind of situation properly.
41#
42# STRATEGY:
43#	1. Repeat 1-3, create two test pools upon device files separately.
44#	   These two pools should have one or more devices are overlapped.
45#	   using the various combinations.
46#		- Regular pool
47#		- Mirror
48#		- Raidz
49#	2. Create necessary filesystem and test files.
50#	3. Export the test pool.
51#	4. Verify 'zpool import -d' with these two pools will have results
52#	   as described:
53#		- Regular, report error while any number of devices failing.
54#		- Mirror could withstand (N-1) devices failing
55#		  before data integrity is compromised
56#		- Raidz could withstand one devices failing
57#		  before data integrity is compromised
58#
59
60verify_runnable "global"
61
62# See issue: https://github.com/openzfs/zfs/issues/6839
63if ! is_illumos; then
64	log_unsupported "Test case may be slow"
65fi
66
67set -A vdevs "" "mirror" "raidz" "draid"
68
69function verify
70{
71	typeset pool=$1
72	typeset fs=$2
73	typeset mtpt=$3
74	typeset health=$4
75	typeset file=$5
76	typeset checksum1=$6
77
78	typeset myhealth
79	typeset mymtpt
80	typeset checksum2
81
82	log_must poolexists $pool
83
84	myhealth=$(zpool list -H -o health $pool)
85
86	[[ $myhealth == $health ]] || \
87		log_fail "$pool: Incorrect health ($myhealth), " \
88			"expected ($health)."
89
90	log_must ismounted $pool/$fs
91
92	mymtpt=$(get_prop mountpoint $pool/$fs)
93	[[ $mymtpt == $mtpt ]] || \
94		log_fail "$pool/$fs: Incorrect mountpoint ($mymtpt), " \
95			"expected ($mtpt)."
96
97	[[ ! -e $mtpt/$file ]] && \
98		log_fail "$mtpt/$file missing after import."
99
100	read -r checksum2 _ < <(cksum $mymtpt/$file)
101	log_must [ "$checksum1" = "$checksum2" ]
102
103	return 0
104
105}
106
107function cleanup
108{
109	log_must cd $DEVICE_DIR
110
111	for pool in $TESTPOOL1 $TESTPOOL2; do
112		if poolexists "$pool" ; then
113			cleanup_filesystem $pool $TESTFS
114			destroy_pool $pool
115		fi
116	done
117
118	[[ -e $DEVICE_DIR/$DEVICE_ARCHIVE ]] && \
119		log_must tar xf $DEVICE_DIR/$DEVICE_ARCHIVE
120}
121
122function cleanup_all
123{
124	cleanup
125
126	# recover dev files
127	typeset i=0
128	while (( i < $MAX_NUM )); do
129		typeset file=${DEVICE_DIR}/${DEVICE_FILE}$i
130		if  [[ -e $file ]]; then
131			log_must rm $file
132		fi
133		log_must mkfile $FILE_SIZE $file
134		((i += 1))
135	done
136
137	log_must rm -f $DEVICE_DIR/$DEVICE_ARCHIVE
138	log_must cd $CWD
139
140}
141
142log_onexit cleanup_all
143
144log_assert "Verify that import could handle device overlapped."
145
146CWD=$PWD
147
148log_must cd $DEVICE_DIR
149log_must tar cf $DEVICE_DIR/$DEVICE_ARCHIVE ${DEVICE_FILE}*
150
151read -r checksum1 < <(cksum $MYTESTFILE)
152
153typeset -i i=0
154typeset -i j=0
155typeset -i count=0
156typeset -i num=0
157typeset vdev1=""
158typeset vdev2=""
159typeset action
160
161while (( num < $GROUP_NUM )); do
162	vdev1="$vdev1 ${DEVICE_DIR}/${DEVICE_FILE}$num"
163	(( num = num + 1 ))
164done
165
166while (( i < ${#vdevs[*]} )); do
167	j=0
168	while (( j < ${#vdevs[*]} )); do
169
170		(( j != 0 )) && \
171			log_must tar xf $DEVICE_DIR/$DEVICE_ARCHIVE
172
173		typeset -i overlap=1
174		typeset -i begin
175		typeset -i end
176
177		while (( overlap <= $GROUP_NUM )); do
178			vdev2=""
179			(( begin = $GROUP_NUM - overlap ))
180			(( end = 2 * $GROUP_NUM - overlap - 1 ))
181			(( num = begin ))
182			while (( num <= end )); do
183				vdev2="$vdev2 ${DEVICE_DIR}/${DEVICE_FILE}$num"
184				(( num = num + 1 ))
185			done
186
187			setup_filesystem "$vdev1" $TESTPOOL1 $TESTFS $TESTDIR1 \
188				"" ${vdevs[i]}
189			log_must cp $MYTESTFILE $TESTDIR1/$TESTFILE0
190			log_must zfs umount $TESTDIR1
191			poolexists $TESTPOOL1 && \
192				log_must zpool export $TESTPOOL1
193
194			setup_filesystem "$vdev2" $TESTPOOL2 $TESTFS $TESTDIR2 \
195				"" ${vdevs[j]}
196			log_must cp $MYTESTFILE $TESTDIR2/$TESTFILE0
197			log_must zfs umount $TESTDIR2
198			poolexists $TESTPOOL2 && \
199				log_must zpool export $TESTPOOL2
200
201			action=log_must
202			case "${vdevs[i]}" in
203				'mirror') (( overlap == $GROUP_NUM )) && \
204					action=log_mustnot
205					;;
206				'raidz')  (( overlap > 1 )) && \
207					action=log_mustnot
208					;;
209				'draid')  (( overlap > 1 )) && \
210					action=log_mustnot
211					;;
212				'')  action=log_mustnot
213					;;
214			esac
215
216			$action zpool import -d $DEVICE_DIR $TESTPOOL1
217			log_must zpool import -d $DEVICE_DIR $TESTPOOL2
218
219			if [[ $action == log_must ]]; then
220				verify "$TESTPOOL1" "$TESTFS" "$TESTDIR1" \
221					"DEGRADED" "$TESTFILE0" "$checksum1"
222			fi
223
224			verify "$TESTPOOL2" "$TESTFS" "$TESTDIR2" \
225				"ONLINE" "$TESTFILE0" "$checksum1"
226
227			cleanup
228
229			(( overlap = overlap + 1 ))
230
231		done
232
233		((j = j + 1))
234	done
235
236	((i = i + 1))
237done
238
239log_pass "Import could handle device overlapped."
240