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 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 (c) 2016, Lawrence Livermore National Security, LLC.
25#
26
27. $STF_SUITE/include/libtest.shlib
28. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.cfg
29
30#
31# DESCRIPTION:
32# Many 'zpool create' and 'zpool destroy' must succeed concurrently.
33#
34# STRATEGY:
35# 1. Create N process each of which create/destroy a pool M times.
36# 2. Allow all process to run to completion.
37# 3. Verify all pools and their vdevs were destroyed.
38#
39
40verify_runnable "global"
41
42if is_32bit; then
43	log_unsupported "Test case runs slowly on 32 bit"
44fi
45
46function cleanup
47{
48	if [[ -n "$child_pids" ]]; then
49		for wait_pid in $child_pids; do
50			kill $wait_pid 2>/dev/null
51		done
52	fi
53
54	if [[ -n "$child_pools" ]]; then
55		for pool in $child_pools; do
56			typeset vdev0="$TEST_BASE_DIR/$pool-vdev0.img"
57			typeset vdev1="$TEST_BASE_DIR/$pool-vdev1.img"
58
59			if poolexists $pool; then
60				destroy_pool $pool
61			fi
62
63			rm -f $vdev0 $vdev1
64		done
65	fi
66}
67
68log_onexit cleanup
69
70log_assert "Many 'zpool create' and 'zpool destroy' must succeed concurrently."
71
72child_pids=""
73child_pools=""
74
75function zpool_stress
76{
77	typeset pool=$1
78	typeset vdev0="$TEST_BASE_DIR/$pool-vdev0.img"
79	typeset vdev1="$TEST_BASE_DIR/$pool-vdev1.img"
80	typeset -i iters=$2
81	typeset retry=10
82	typeset j=0
83
84	truncate -s $FILESIZE $vdev0
85	truncate -s $FILESIZE $vdev1
86
87	while [[ $j -lt $iters ]]; do
88		((j = j + 1))
89		sleep 1
90
91		zpool create $pool $vdev0 $vdev1
92		if [ $? -ne 0 ]; then
93			return 1;
94		fi
95
96		# The 'zfs destroy' command is retried because it can
97		# transiently return EBUSY when blkid is concurrently
98		# probing new volumes and therefore has them open.
99		typeset k=0;
100		while [[ $k -lt $retry ]]; do
101			((k = k + 1))
102
103			zpool destroy $pool
104			if [ $? -eq 0 ]; then
105				break;
106			elif [ $k -eq $retry ]; then
107				return 1;
108			fi
109
110			sleep 3
111		done
112	done
113
114	rm -f $vdev0 $vdev1
115	return 0
116}
117
118# 1. Create 128 process each of which create/destroy a pool 5 times.
119typeset i=0
120while [[ $i -lt 128 ]]; do
121	typeset uuid=$(uuidgen | cut -c1-13)
122
123	zpool_stress $TESTPOOL-$uuid 5 &
124	typeset pid=$!
125
126	child_pids="$child_pids $pid"
127	child_pools="$child_pools $TESTPOOL-$uuid"
128	((i = i + 1))
129done
130
131# 2. Allow all process to run to completion.
132wait
133
134# 3. Verify all pools and their vdevs were destroyed.
135for pool in $child_pools; do
136	typeset vdev0="$TEST_BASE_DIR/$pool-vdev0.img"
137	typeset vdev1="$TEST_BASE_DIR/$pool-vdev1.img"
138
139	if poolexists $pool; then
140		log_fail "pool $pool exists"
141	fi
142
143	if [ -e $vdev0 ]; then
144		log_fail "pool vdev $vdev0 exists"
145	fi
146
147	if [ -e $vdev1 ]; then
148		log_fail "pool vdev $vdev1 exists"
149	fi
150done
151
152log_pass "Many 'zpool create' and 'zpool destroy' must succeed concurrently."
153