target/mips: Move mmu_init() functions to tlb_helper.c
[qemu/ar7.git] / tests / qemu-iotests / 308
blobb30f4400f6199ab85f02dfbfbfd83f1ee76d493d
1 #!/usr/bin/env bash
3 # Test FUSE exports (in ways that are not captured by the generic
4 # tests)
6 # Copyright (C) 2020 Red Hat, Inc.
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 seq=$(basename "$0")
23 echo "QA output created by $seq"
25 status=1 # failure is the default!
27 _cleanup()
29 _cleanup_qemu
30 _cleanup_test_img
31 rmdir "$EXT_MP" 2>/dev/null
32 rm -f "$EXT_MP"
33 rm -f "$COPIED_IMG"
35 trap "_cleanup; exit \$status" 0 1 2 3 15
37 # get standard environment, filters and checks
38 . ./common.rc
39 . ./common.filter
40 . ./common.qemu
42 # Generic format, but needs a plain filename
43 _supported_fmt generic
44 if [ "$IMGOPTSSYNTAX" = "true" ]; then
45 _unsupported_fmt $IMGFMT
47 # We need the image to have exactly the specified size, and VPC does
48 # not allow that by default
49 _unsupported_fmt vpc
51 _supported_proto file # We create the FUSE export manually
52 _supported_os Linux # We need /dev/urandom
54 # $1: Export ID
55 # $2: Options (beyond the node-name and ID)
56 # $3: Expected return value (defaults to 'return')
57 # $4: Node to export (defaults to 'node-format')
58 fuse_export_add()
60 _send_qemu_cmd $QEMU_HANDLE \
61 "{'execute': 'block-export-add',
62 'arguments': {
63 'type': 'fuse',
64 'id': '$1',
65 'node-name': '${4:-node-format}',
67 } }" \
68 "${3:-return}" \
69 | _filter_imgfmt
72 # $1: Export ID
73 fuse_export_del()
75 _send_qemu_cmd $QEMU_HANDLE \
76 "{'execute': 'block-export-del',
77 'arguments': {
78 'id': '$1'
79 } }" \
80 'return'
82 _send_qemu_cmd $QEMU_HANDLE \
83 '' \
84 'BLOCK_EXPORT_DELETED'
87 # Return the length of the protocol file
88 # $1: Protocol node export mount point
89 # $2: Original file (to compare)
90 get_proto_len()
92 len1=$(stat -c '%s' "$1")
93 len2=$(stat -c '%s' "$2")
95 if [ "$len1" != "$len2" ]; then
96 echo 'ERROR: Length of export and original differ:' >&2
97 echo "$len1 != $len2" >&2
98 else
99 echo '(OK: Lengths of export and original are the same)' >&2
102 echo "$len1"
105 COPIED_IMG="$TEST_IMG.copy"
106 EXT_MP="$TEST_IMG.fuse"
108 echo '=== Set up ==='
110 # Create image with random data
111 _make_test_img 64M
112 $QEMU_IO -c 'write -s /dev/urandom 0 64M' "$TEST_IMG" | _filter_qemu_io
114 _launch_qemu
115 _send_qemu_cmd $QEMU_HANDLE \
116 "{'execute': 'qmp_capabilities'}" \
117 'return'
119 # Separate blockdev-add calls for format and protocol so we can remove
120 # the format layer later on
121 _send_qemu_cmd $QEMU_HANDLE \
122 "{'execute': 'blockdev-add',
123 'arguments': {
124 'driver': 'file',
125 'node-name': 'node-protocol',
126 'filename': '$TEST_IMG'
127 } }" \
128 'return'
130 _send_qemu_cmd $QEMU_HANDLE \
131 "{'execute': 'blockdev-add',
132 'arguments': {
133 'driver': '$IMGFMT',
134 'node-name': 'node-format',
135 'file': 'node-protocol'
136 } }" \
137 'return'
139 echo
140 echo '=== Mountpoint not present ==='
142 rmdir "$EXT_MP" 2>/dev/null
143 rm -f "$EXT_MP"
144 output=$(fuse_export_add 'export-err' "'mountpoint': '$EXT_MP'" error)
146 if echo "$output" | grep -q "Invalid parameter 'fuse'"; then
147 _notrun 'No FUSE support'
150 echo "$output"
152 echo
153 echo '=== Mountpoint is a directory ==='
155 mkdir "$EXT_MP"
156 fuse_export_add 'export-err' "'mountpoint': '$EXT_MP'" error
157 rmdir "$EXT_MP"
159 echo
160 echo '=== Mountpoint is a regular file ==='
162 touch "$EXT_MP"
163 fuse_export_add 'export-mp' "'mountpoint': '$EXT_MP'"
165 # Check that the export presents the same data as the original image
166 $QEMU_IMG compare -f raw -F $IMGFMT -U "$EXT_MP" "$TEST_IMG"
168 echo
169 echo '=== Mount over existing file ==='
171 # This is the coolest feature of FUSE exports: You can transparently
172 # make images in any format appear as raw images
173 fuse_export_add 'export-img' "'mountpoint': '$TEST_IMG'"
175 # Accesses both exports at the same time, so we get a concurrency test
176 $QEMU_IMG compare -f raw -F raw -U "$EXT_MP" "$TEST_IMG"
178 # Just to be sure, we later want to compare the data offline. Also,
179 # this allows us to see that cp works without complaining.
180 # (This is not a given, because cp will expect a short read at EOF.
181 # Internally, qemu does not allow short reads, so we have to check
182 # whether the FUSE export driver lets them work.)
183 cp "$TEST_IMG" "$COPIED_IMG"
185 # $TEST_IMG will be in mode 0400 because it is read-only; we are going
186 # to write to the copy, so make it writable
187 chmod 0600 "$COPIED_IMG"
189 echo
190 echo '=== Double export ==='
192 # We have already seen that exporting a node twice works fine, but you
193 # cannot export anything twice on the same mount point. The reason is
194 # that qemu has to stat the given mount point, and this would have to
195 # be answered by the same qemu instance if it already has an export
196 # there. However, it cannot answer the stat because it is itself
197 # caught up in that same stat.
198 fuse_export_add 'export-err' "'mountpoint': '$EXT_MP'" error
200 echo
201 echo '=== Remove export ==='
203 # Double-check that $EXT_MP appears as a non-empty file (the raw image)
204 $QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size'
206 fuse_export_del 'export-mp'
208 # See that the file appears empty again
209 $QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size'
211 echo
212 echo '=== Writable export ==='
214 fuse_export_add 'export-mp' "'mountpoint': '$EXT_MP', 'writable': true"
216 # Check that writing to the read-only export fails
217 $QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TEST_IMG" | _filter_qemu_io
219 # But here it should work
220 $QEMU_IO -f raw -c 'write -P 42 1M 64k' "$EXT_MP" | _filter_qemu_io
222 # (Adjust the copy, too)
223 $QEMU_IO -f raw -c 'write -P 42 1M 64k' "$COPIED_IMG" | _filter_qemu_io
225 echo
226 echo '=== Resizing exports ==='
228 # Here, we need to export the protocol node -- the format layer may
229 # not be growable, simply because the format does not support it.
231 # Remove all exports and the format node first so permissions will not
232 # get in the way
233 fuse_export_del 'export-mp'
234 fuse_export_del 'export-img'
236 _send_qemu_cmd $QEMU_HANDLE \
237 "{'execute': 'blockdev-del',
238 'arguments': {
239 'node-name': 'node-format'
240 } }" \
241 'return'
243 # Now export the protocol node
244 fuse_export_add \
245 'export-mp' \
246 "'mountpoint': '$EXT_MP', 'writable': true" \
247 'return' \
248 'node-protocol'
250 echo
251 echo '--- Try growing non-growable export ---'
253 # Get the current size so we can write beyond the EOF
254 orig_len=$(get_proto_len "$EXT_MP" "$TEST_IMG")
255 orig_disk_usage=$(stat -c '%b' "$TEST_IMG")
257 # Should fail (exports are non-growable by default)
258 # (Note that qemu-io can never write beyond the EOF, so we have to use
259 # dd here)
260 dd if=/dev/zero of="$EXT_MP" bs=1 count=64k seek=$orig_len 2>&1 \
261 | _filter_testdir | _filter_imgfmt
263 echo
264 echo '--- Resize export ---'
266 # But we can truncate it explicitly; even with fallocate
267 fallocate -o "$orig_len" -l 64k "$EXT_MP"
269 new_len=$(get_proto_len "$EXT_MP" "$TEST_IMG")
270 if [ "$new_len" != "$((orig_len + 65536))" ]; then
271 echo 'ERROR: Unexpected post-truncate image size:'
272 echo "$new_len != $((orig_len + 65536))"
273 else
274 echo 'OK: Post-truncate image size is as expected'
277 new_disk_usage=$(stat -c '%b' "$TEST_IMG")
278 if [ "$new_disk_usage" -gt "$orig_disk_usage" ]; then
279 echo 'OK: Disk usage grew with fallocate'
280 else
281 echo 'ERROR: Disk usage did not grow despite fallocate:'
282 echo "$orig_disk_usage => $new_disk_usage"
285 echo
286 echo '--- Try growing growable export ---'
288 # Now export as growable
289 fuse_export_del 'export-mp'
290 fuse_export_add \
291 'export-mp' \
292 "'mountpoint': '$EXT_MP', 'writable': true, 'growable': true" \
293 'return' \
294 'node-protocol'
296 # Now we should be able to write beyond the EOF
297 dd if=/dev/zero of="$EXT_MP" bs=1 count=64k seek=$new_len 2>&1 \
298 | _filter_testdir | _filter_imgfmt
300 new_len=$(get_proto_len "$EXT_MP" "$TEST_IMG")
301 if [ "$new_len" != "$((orig_len + 131072))" ]; then
302 echo 'ERROR: Unexpected post-grow image size:'
303 echo "$new_len != $((orig_len + 131072))"
304 else
305 echo 'OK: Post-grow image size is as expected'
308 echo
309 echo '--- Shrink export ---'
311 # Now go back to the original size
312 truncate -s "$orig_len" "$EXT_MP"
314 new_len=$(get_proto_len "$EXT_MP" "$TEST_IMG")
315 if [ "$new_len" != "$orig_len" ]; then
316 echo 'ERROR: Unexpected post-truncate image size:'
317 echo "$new_len != $orig_len"
318 else
319 echo 'OK: Post-truncate image size is as expected'
322 echo
323 echo '=== Tear down ==='
325 _send_qemu_cmd $QEMU_HANDLE \
326 "{'execute': 'quit'}" \
327 'return'
329 wait=yes _cleanup_qemu
331 echo
332 echo '=== Compare copy with original ==='
334 $QEMU_IMG compare -f raw -F $IMGFMT "$COPIED_IMG" "$TEST_IMG"
336 # success, all done
337 echo "*** done"
338 rm -f $seq.full
339 status=0