1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
#!/bin/ksh -p
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
#
# DESCRIPTION:
# 'zfs destroy -r|-rf|-R|-Rf <fs|ctr|vol|snap>' should recursively destroy
# all children and clones based on options.
#
# STRATEGY:
# 1. Create test environment according to options. There are three test
# models can be created. Only ctr, fs & vol; with snap; with clone.
# 2. According to option, make the dataset busy or not.
# 3. Run 'zfs destroy [-rRf] <dataset>'
# 4. According to dataset and option, check if get the expected results.
#
verify_runnable "both"
#
# According to parameters, 1st, create suitable testing environment. 2nd,
# run 'zfs destroy $opt <dataset>'. 3rd, check the system status.
#
# $1 option of 'zfs destroy'
# $2 dataset will be destroyed.
#
function test_n_check
{
typeset opt=$1
typeset dtst=$2
if ! is_global_zone ; then
if [[ $dtst == $VOL || $dtst == $VOLSNAP ]]; then
log_note "UNSUPPORTED: Volume are unavailable in LZ."
return
fi
fi
# '-f' has no effect on non-filesystems
if [[ $opt == -f ]]; then
if [[ $dtst != $FS ]]; then
log_note "UNSUPPORTED: '-f ' is only available for " \
"leaf FS."
return
fi
fi
# Clean the test environment and make it clear.
datasetexists $CTR && destroy_dataset $CTR -Rf
# According to option create test compatible environment.
case $opt in
-r|-rf) setup_testenv snap ;;
-R|-Rf) setup_testenv clone ;;
-f) setup_testenv ;;
*) log_fail "Incorrect option: '$opt'." ;;
esac
#
# According to different dataset type, create busy condition when try to
# destroy this dataset.
#
typeset mpt_dir
case $dtst in
$CTR|$FS)
if [[ $opt == *f* ]]; then
mpt_dir=$(get_prop mountpoint $FS)
pidlist="$pidlist $(mkbusy \
$mpt_dir/$TESTFILE0)"
log_note "mkbusy $mpt_dir/$TESTFILE0 " \
"(pidlist: $pidlist)"
[[ -z $pidlist ]] && \
log_fail "Failure from mkbusy"
log_mustnot zfs destroy -rR $dtst
fi
;;
$VOL)
if [[ $opt == *f* ]]; then
pidlist="$pidlist $(mkbusy \
$TESTDIR1/$TESTFILE0)"
log_note "mkbusy $TESTDIR1/$TESTFILE0 " \
"(pidlist: $pidlist)"
[[ -z $pidlist ]] && \
log_fail "Failure from mkbusy"
log_mustnot zfs destroy -rR $dtst
fi
;;
$VOLSNAP)
if [[ $opt == *f* ]]; then
pidlist="$pidlist $(mkbusy \
$TESTDIR1/$TESTFILE0)"
log_note "mkbusy $TESTDIR1/$TESTFILE0 " \
"(pidlist: $pidlist)"
[[ -z $pidlist ]] && \
log_fail "Failure from mkbusy"
log_must_busy zfs destroy -rR $dtst
log_must zfs snapshot $dtst
fi
;;
$FSSNAP)
if [[ $opt == *f* ]]; then
mpt_dir=$(snapshot_mountpoint $dtst)
pidlist="$pidlist $(mkbusy $mpt_dir)"
log_note "mkbusy $mpt_dir (pidlist: $pidlist)"
[[ -z $pidlist ]] && \
log_fail "Failure from mkbusy"
if is_linux ; then
log_mustnot zfs destroy -rR $dtst
else
log_must zfs destroy -rR $dtst
log_must zfs snapshot $dtst
fi
fi
;;
*) log_fail "Unsupported dataset: '$dtst'."
esac
# Kill any lingering instances of mkbusy, and clear the list.
if is_linux ; then
[[ -z $pidlist ]] || log_must kill -TERM $pidlist
pidlist=""
log_mustnot pgrep -fl mkbusy
fi
# Firstly, umount ufs filesystem which was created by zfs volume.
if is_global_zone; then
log_must umount -f $TESTDIR1
fi
# Invoke 'zfs destroy [-rRf] <dataset>'
log_must_busy zfs destroy $opt $dtst
block_device_wait
# Kill any lingering instances of mkbusy, and clear the list.
if ! is_linux ; then
[[ -z $pidlist ]] || log_must kill -TERM $pidlist
pidlist=""
log_mustnot pgrep -fl mkbusy
fi
case $dtst in
$CTR) check_dataset datasetnonexists \
$CTR $FS $VOL $FSSNAP $VOLSNAP
if [[ $opt == *R* ]]; then
check_dataset datasetnonexists \
$FSCLONE $VOLCLONE
fi
;;
$FS) check_dataset datasetexists $CTR $VOL
check_dataset datasetnonexists $FS
if [[ $opt != -f ]]; then
check_dataset datasetexists $VOLSNAP
check_dataset datasetnonexists $FSSNAP
fi
if [[ $opt == *R* ]]; then
check_dataset datasetexists $VOLCLONE
check_dataset datasetnonexists $FSCLONE
fi
;;
$VOL) check_dataset datasetexists $CTR $FS $FSSNAP
check_dataset datasetnonexists $VOL $VOLSNAP
if [[ $opt == *R* ]]; then
check_dataset datasetexists $FSCLONE
check_dataset datasetnonexists $VOLCLONE
fi
;;
$FSSNAP)
check_dataset datasetexists $CTR $FS $VOL $VOLSNAP
check_dataset datasetnonexists $FSSNAP
if [[ $opt == *R* ]]; then
check_dataset datasetexists $VOLCLONE
check_dataset datasetnonexists $FSCLONE
fi
;;
$VOLSNAP)
check_dataset datasetexists $CTR $FS $VOL $FSSNAP
check_dataset datasetnonexists $VOLSNAP
if [[ $opt == *R* ]]; then
check_dataset datasetexists $FSCLONE
check_dataset datasetnonexists $VOLCLONE
fi
;;
esac
log_note "'zfs destroy $opt $dtst' passed."
}
log_assert "'zfs destroy -r|-R|-f|-rf|-Rf <fs|ctr|vol|snap>' should " \
"recursively destroy all children."
log_onexit cleanup_testenv
typeset dtst=""
typeset opt=""
typeset pidlist=""
for dtst in $CTR $FS $VOL $FSSNAP $VOLSNAP; do
for opt in "-r" "-R" "-f" "-rf" "-Rf"; do
log_note "Starting test: zfs destroy $opt $dtst"
test_n_check $opt $dtst
done
done
log_pass "'zfs destroy -r|-R|-f|-rf|-Rf <fs|ctr|vol|snap>' passed."
|