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 (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 $vdev1
85
86	while [[ $j -lt $iters ]]; do
87		((j = j + 1))
88		sleep 1
89
90		zpool create $pool $vdev0 $vdev1 || return 1
91
92		# The 'zfs destroy' command is retried because it can
93		# transiently return EBUSY when blkid is concurrently
94		# probing new volumes and therefore has them open.
95		typeset k=0;
96		while [[ $k -lt $retry ]]; do
97			((k = k + 1))
98
99			zpool destroy $pool && break
100			[ $k -eq $retry ] && return 1
101			sleep 3
102		done
103	done
104
105	rm -f $vdev0 $vdev1
106	return 0
107}
108
109# 1. Create 128 process each of which create/destroy a pool 5 times.
110typeset i=0
111while [[ $i -lt 128 ]]; do
112	zpool_stress $TESTPOOL-$i 5 &
113	typeset pid=$!
114
115	child_pids="$child_pids $pid"
116	child_pools="$child_pools $TESTPOOL-$i-$pid"
117	((i = i + 1))
118done
119
120# 2. Allow all process to run to completion.
121wait
122
123# 3. Verify all pools and their vdevs were destroyed.
124for pool in $child_pools; do
125	typeset vdev0="$TEST_BASE_DIR/$pool-vdev0.img"
126	typeset vdev1="$TEST_BASE_DIR/$pool-vdev1.img"
127
128	if poolexists $pool; then
129		log_fail "pool $pool exists"
130	fi
131
132	if [ -e $vdev0 ]; then
133		log_fail "pool vdev $vdev0 exists"
134	fi
135
136	if [ -e $vdev1 ]; then
137		log_fail "pool vdev $vdev1 exists"
138	fi
139done
140
141log_pass "Many 'zpool create' and 'zpool destroy' must succeed concurrently."
142