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) 2023 Klara, Inc.
30#
31
32. $STF_SUITE/include/libtest.shlib
33. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
34. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
35
36#
37# DESCRIPTION:
38# 	Verify that pool imports by same name only have one winner
39#
40# STRATEGY:
41#	1. Create 4 single disk pools with the same name
42#	2. Generate some ZIL records (for a longer import)
43#	3. Export the pools
44#	4. Import the pools in parallel
45#	5. Repeat with using matching guids
46#
47
48verify_runnable "global"
49
50POOLNAME="import_pool"
51DEV_DIR_PREFIX="$DEVICE_DIR/$POOLNAME"
52VDEVSIZE=$((512 * 1024 * 1024))
53
54log_assert "parallel pool imports by same name only have one winner"
55
56# each pool has its own device directory
57for i in {0..3}; do
58	log_must mkdir -p ${DEV_DIR_PREFIX}$i
59	log_must truncate -s $VDEVSIZE ${DEV_DIR_PREFIX}$i/${DEVICE_FILE}$i
60done
61
62function cleanup
63{
64	zinject -c all
65	log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 0
66	log_must set_tunable64 METASLAB_DEBUG_LOAD 0
67
68	destroy_pool $POOLNAME
69
70	log_must rm -rf $DEV_DIR_PREFIX*
71}
72
73log_onexit cleanup
74
75log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 1
76log_must set_tunable64 METASLAB_DEBUG_LOAD 1
77
78function import_pool
79{
80	typeset dir=$1
81	typeset pool=$2
82	typeset newname=$3
83
84	SECONDS=0
85	errmsg=$(zpool import -N -d $dir -f $pool $newname 2>&1 > /dev/null)
86	if [[ $? -eq 0 ]]; then
87		touch $dir/imported
88		echo "imported $pool in $SECONDS secs"
89	elif [[ $errmsg == *"cannot import"* ]]; then
90		echo "pool import failed: $errmsg, waited $SECONDS secs"
91		touch $dir/failed
92	fi
93}
94
95#
96# create four exported pools with the same name
97#
98for i in {0..3}; do
99	log_must zpool create $POOLNAME ${DEV_DIR_PREFIX}$i/${DEVICE_FILE}$i
100	log_must zpool export $POOLNAME
101done
102log_must zinject -P import -s 10 $POOLNAME
103
104#
105# import the pools in parallel, expecting only one winner
106#
107for i in {0..3}; do
108	import_pool ${DEV_DIR_PREFIX}$i $POOLNAME &
109done
110wait
111
112# check the result of background imports
113typeset num_imports=0
114typeset num_cannot=0
115for i in {0..3}; do
116	if [[ -f ${DEV_DIR_PREFIX}$i/imported ]]; then
117		((num_imports += 1))
118	fi
119	if [[ -f ${DEV_DIR_PREFIX}$i/failed ]]; then
120		((num_cannot += 1))
121		loser=$i
122	fi
123done
124[[ $num_imports -eq "1" ]] || log_fail "expecting an import"
125[[ $num_cannot -eq "3" ]] || \
126    log_fail "expecting 3 pool exists errors, found $num_cannot"
127
128log_note "$num_imports imported and $num_cannot failed (expected)"
129
130log_pass "parallel pool imports by same name only have one winner"
131