1# Copyright (c) 2012 Edward Tomasz Napierała <trasz@FreeBSD.org>
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6# 1. Redistributions of source code must retain the above copyright
7#    notice, this list of conditions and the following disclaimer.
8# 2. Redistributions in binary form must reproduce the above copyright
9#    notice, this list of conditions and the following disclaimer in the
10#    documentation and/or other materials provided with the distribution.
11#
12# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22# SUCH DAMAGE.
23#
24# $FreeBSD$
25#
26
27check_diskinfo()
28{
29	local md=$1
30	local mediasize_in_bytes=$2
31	local mediasize_in_sectors=$3
32	local sectorsize=${4:-512}
33	local stripesize=${5:-0}
34	local stripeoffset=${6:-0}
35
36	atf_check -s exit:0 \
37	    -o match:"/dev/$md *$sectorsize *$mediasize_in_bytes *$mediasize_in_sectors *$stripesize *$stripeoffset" \
38	    -x "diskinfo /dev/$md | expand"
39}
40
41cleanup_common()
42{
43	if [ -f mdconfig.out ]; then
44		mdconfig -d -u $(sed -e 's/md//' mdconfig.out)
45	fi
46}
47
48atf_test_case attach_vnode_non_explicit_type cleanup
49attach_vnode_non_explicit_type_head()
50{
51	atf_set "descr" "Tests out -a / -f without -t"
52}
53attach_vnode_non_explicit_type_body()
54{
55	local md
56	local size_in_mb=1024
57
58	atf_check -s exit:0 -x "truncate -s ${size_in_mb}m xxx"
59	atf_check -s exit:0 -o save:mdconfig.out -x 'mdconfig -af xxx'
60	md=$(cat mdconfig.out)
61	atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md"
62	check_diskinfo "$md" "1073741824" "2097152"
63	# This awk strips the file path.
64	atf_check -s exit:0 -o match:"^$md vnode ${size_in_mb}M$" \
65	    -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'"
66}
67attach_vnode_non_explicit_type_cleanup()
68{
69	cleanup_common
70}
71
72atf_test_case attach_vnode_implicit_a_f cleanup
73attach_vnode_implicit_a_f_head()
74{
75	atf_set "descr" "Tests out implied -a / -f without -t"
76}
77attach_vnode_implicit_a_f_body()
78{
79	local md
80	local size_in_mb=1024
81
82	atf_check -s exit:0 -x "truncate -s ${size_in_mb}m xxx"
83	atf_check -s exit:0 -o save:mdconfig.out -x 'mdconfig xxx'
84	md=$(cat mdconfig.out)
85	atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md"
86	check_diskinfo "$md" "1073741824" "2097152"
87	# This awk strips the file path.
88	atf_check -s exit:0 -o match:"^$md vnode ${size_in_mb}M$" \
89	    -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'"
90}
91attach_vnode_implicit_a_f_cleanup()
92{
93	cleanup_common
94}
95
96atf_test_case attach_vnode_explicit_type cleanup
97attach_vnode_explicit_type_head()
98{
99	atf_set "descr" "Tests out implied -a / -f with -t vnode"
100}
101attach_vnode_explicit_type_body()
102{
103	local md
104	local size_in_mb=1024
105
106	atf_check -s exit:0 -x "truncate -s ${size_in_mb}m xxx"
107	atf_check -s exit:0 -o save:mdconfig.out -x 'mdconfig -af xxx -t vnode'
108	md=$(cat mdconfig.out)
109	atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md"
110	check_diskinfo "$md" "1073741824" "2097152"
111	# This awk strips the file path.
112	atf_check -s exit:0 -o match:"^$md vnode ${size_in_mb}M$" \
113	    -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'"
114}
115attach_vnode_explicit_type_cleanup()
116{
117	[ -f mdconfig.out ] && mdconfig -d -u $(sed -e 's/md//' mdconfig.out)
118	rm -f mdconfig.out xxx
119}
120
121atf_test_case attach_vnode_smaller_than_file cleanup
122attach_vnode_smaller_than_file_head()
123{
124	atf_set "descr" "Tests mdconfig -s with size less than the file size"
125}
126attach_vnode_smaller_than_file_body()
127{
128	local md
129	local size_in_mb=128
130
131	atf_check -s exit:0 -x "truncate -s 1024m xxx"
132	atf_check -s exit:0 -o save:mdconfig.out \
133	    -x "mdconfig -af xxx -s ${size_in_mb}m"
134	md=$(cat mdconfig.out)
135	atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md"
136	check_diskinfo "$md" "134217728" "262144"
137	# This awk strips the file path.
138	atf_check -s exit:0 -o match:"^$md vnode ${size_in_mb}M$" \
139	    -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'"
140}
141attach_vnode_smaller_than_file_cleanup()
142{
143	cleanup_common
144}
145
146atf_test_case attach_vnode_larger_than_file cleanup
147attach_vnode_larger_than_file_head()
148{
149	atf_set "descr" "Tests mdconfig -s with size greater than the file size"
150}
151attach_vnode_larger_than_file_body()
152{
153	local md
154	local size_in_gb=128
155
156	atf_check -s exit:0 -x "truncate -s 1024m xxx"
157	atf_check -s exit:0 -o save:mdconfig.out \
158	    -x "mdconfig -af xxx -s ${size_in_gb}g"
159	md=$(cat mdconfig.out)
160	atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md"
161	check_diskinfo "$md" "137438953472" "268435456"
162	# This awk strips the file path.
163	atf_check -s exit:0 -o match:"^$md vnode ${size_in_gb}G$" \
164	    -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'"
165}
166attach_vnode_larger_than_file_cleanup()
167{
168	cleanup_common
169}
170
171atf_test_case attach_vnode_sector_size cleanup
172attach_vnode_sector_size_head()
173{
174	atf_set "descr" "Tests mdconfig -S with a backing file"
175}
176attach_vnode_sector_size_body()
177{
178	local md
179	local size_in_mb=1024
180
181	atf_check -s exit:0 -x "truncate -s ${size_in_mb}m xxx"
182	atf_check -s exit:0 -o save:mdconfig.out \
183	    -x "mdconfig -af xxx -S 2048"
184	md=$(cat mdconfig.out)
185	atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md"
186	check_diskinfo "$md" "1073741824" "524288" "2048"
187	# This awk strips the file path.
188	atf_check -s exit:0 -o match:"^$md vnode ${size_in_mb}M$" \
189	    -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'"
190}
191attach_vnode_sector_size_cleanup()
192{
193	cleanup_common
194}
195
196atf_test_case attach_malloc cleanup
197attach_malloc_head()
198{
199	atf_set "descr" "Tests mdconfig with -t malloc"
200}
201attach_malloc_body()
202{
203	local md
204	local size_in_mb=1024
205
206	atf_check -s exit:0 -o save:mdconfig.out \
207	    -x 'mdconfig -a -t malloc -s 1g'
208	md=$(cat mdconfig.out)
209	atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md"
210	check_diskinfo "$md" "1073741824" "2097152"
211	# This awk strips the file path.
212	atf_check -s exit:0 -o match:"^$md malloc ${size_in_mb}M$" \
213	    -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'"
214}
215attach_malloc_cleanup()
216{
217	cleanup_common
218}
219
220atf_test_case attach_swap cleanup
221attach_swap_head()
222{
223	atf_set "descr" "Tests mdconfig with -t swap"
224}
225attach_swap_body()
226{
227	local md
228	local size_in_mb=1024
229
230	atf_check -s exit:0 -o save:mdconfig.out \
231	    -x 'mdconfig -a -t swap -s 1g'
232	md=$(cat mdconfig.out)
233	atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md"
234	check_diskinfo "$md" "1073741824" "2097152"
235	# This awk strips the file path.
236	atf_check -s exit:0 -o match:"^$md swap ${size_in_mb}M$" \
237	    -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'"
238}
239attach_swap_cleanup()
240{
241	cleanup_common
242}
243
244atf_test_case attach_with_specific_unit_number cleanup
245attach_with_specific_unit_number_head()
246{
247	atf_set "descr" "Tests mdconfig with a unit specified by -u"
248}
249attach_with_specific_unit_number_body()
250{
251	local md_unit=99
252	local size_in_mb=10
253
254	local md="md${md_unit}"
255
256	echo "$md" > mdconfig.out
257
258	atf_check -s exit:0 -o empty \
259	    -x "mdconfig -a -t malloc -s ${size_in_mb}m -u $md_unit"
260	check_diskinfo "$md" "10485760" "20480"
261	# This awk strips the file path.
262	atf_check -s exit:0 -o match:"^$md malloc "$size_in_mb"M$" \
263	    -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'"
264}
265attach_with_specific_unit_number_cleanup()
266{
267	cleanup_common
268}
269
270atf_test_case attach_size_rounddown cleanup
271attach_size_rounddown()
272{
273	atf_set "descr" "Verify that md provider sizes are a multiple of the sector size"
274}
275attach_size_rounddown_body()
276{
277	local md
278	local ss=8192
279	local ms=$(($ss + 4096))
280	local ms2=$((2 * $ss + 4096))
281
282	# Use a sector size that's a likely multiple of PAGE_SIZE, as md(4)
283	# expects that for swap MDs.
284	atf_check -s exit:0 -o save:mdconfig.out -e empty \
285	    -x "mdconfig -a -t swap -S $ss -s ${ms}b"
286	md=$(cat mdconfig.out)
287	# 12288 bytes should be rounded down to one sector.
288	check_diskinfo "$md" 8192 1 $ss
289
290	# Resize and verify that the new size was also rounded down.
291	atf_check -s exit:0 -o empty -e empty \
292	    -x "mdconfig -r -u ${md#md} -s ${ms2}b"
293	check_diskinfo "$md" 16384 2 $ss
294}
295attach_size_rounddown()
296{
297	cleanup_common
298}
299
300atf_init_test_cases()
301{
302	atf_add_test_case attach_vnode_non_explicit_type
303	atf_add_test_case attach_vnode_explicit_type
304	atf_add_test_case attach_vnode_smaller_than_file
305	atf_add_test_case attach_vnode_larger_than_file
306	atf_add_test_case attach_vnode_sector_size
307	atf_add_test_case attach_malloc
308	atf_add_test_case attach_swap
309	atf_add_test_case attach_with_specific_unit_number
310	atf_add_test_case attach_size_rounddown
311}
312