xref: /qemu/tests/qemu-iotests/308 (revision 72c58ff8958f6e00ce361d1d568dc21e41c85f45)
1e6c79647SMax Reitz#!/usr/bin/env bash
29dd003a9SVladimir Sementsov-Ogievskiy# group: rw
3e6c79647SMax Reitz#
4e6c79647SMax Reitz# Test FUSE exports (in ways that are not captured by the generic
5e6c79647SMax Reitz# tests)
6e6c79647SMax Reitz#
7e6c79647SMax Reitz# Copyright (C) 2020 Red Hat, Inc.
8e6c79647SMax Reitz#
9e6c79647SMax Reitz# This program is free software; you can redistribute it and/or modify
10e6c79647SMax Reitz# it under the terms of the GNU General Public License as published by
11e6c79647SMax Reitz# the Free Software Foundation; either version 2 of the License, or
12e6c79647SMax Reitz# (at your option) any later version.
13e6c79647SMax Reitz#
14e6c79647SMax Reitz# This program is distributed in the hope that it will be useful,
15e6c79647SMax Reitz# but WITHOUT ANY WARRANTY; without even the implied warranty of
16e6c79647SMax Reitz# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17e6c79647SMax Reitz# GNU General Public License for more details.
18e6c79647SMax Reitz#
19e6c79647SMax Reitz# You should have received a copy of the GNU General Public License
20e6c79647SMax Reitz# along with this program.  If not, see <http://www.gnu.org/licenses/>.
21e6c79647SMax Reitz#
22e6c79647SMax Reitz
23e6c79647SMax Reitzseq=$(basename "$0")
24e6c79647SMax Reitzecho "QA output created by $seq"
25e6c79647SMax Reitz
26e6c79647SMax Reitzstatus=1	# failure is the default!
27e6c79647SMax Reitz
28e6c79647SMax Reitz_cleanup()
29e6c79647SMax Reitz{
30e6c79647SMax Reitz    _cleanup_qemu
31e6c79647SMax Reitz    _cleanup_test_img
32e6c79647SMax Reitz    rmdir "$EXT_MP" 2>/dev/null
33e6c79647SMax Reitz    rm -f "$EXT_MP"
34e6c79647SMax Reitz    rm -f "$COPIED_IMG"
35e6c79647SMax Reitz}
36e6c79647SMax Reitztrap "_cleanup; exit \$status" 0 1 2 3 15
37e6c79647SMax Reitz
38e6c79647SMax Reitz# get standard environment, filters and checks
39e6c79647SMax Reitz. ./common.rc
40e6c79647SMax Reitz. ./common.filter
41e6c79647SMax Reitz. ./common.qemu
42e6c79647SMax Reitz
43e6c79647SMax Reitz# Generic format, but needs a plain filename
44e6c79647SMax Reitz_supported_fmt generic
45e6c79647SMax Reitzif [ "$IMGOPTSSYNTAX" = "true" ]; then
46e6c79647SMax Reitz    _unsupported_fmt $IMGFMT
47e6c79647SMax Reitzfi
48e6c79647SMax Reitz# We need the image to have exactly the specified size, and VPC does
49e6c79647SMax Reitz# not allow that by default
50e6c79647SMax Reitz_unsupported_fmt vpc
51e6c79647SMax Reitz
52e6c79647SMax Reitz_supported_proto file # We create the FUSE export manually
53e6c79647SMax Reitz_supported_os Linux # We need /dev/urandom
54*c49dda72SEric Blake_require_disk_usage
55e6c79647SMax Reitz
56e6c79647SMax Reitz# $1: Export ID
57e6c79647SMax Reitz# $2: Options (beyond the node-name and ID)
58e6c79647SMax Reitz# $3: Expected return value (defaults to 'return')
59e6c79647SMax Reitz# $4: Node to export (defaults to 'node-format')
60e6c79647SMax Reitzfuse_export_add()
61e6c79647SMax Reitz{
628fc54f94SMax Reitz    # The grep -v is a filter for errors when /etc/fuse.conf does not contain
638fc54f94SMax Reitz    # user_allow_other.  (The error is benign, but it is printed by fusermount
648fc54f94SMax Reitz    # on the first mount attempt, so our export code cannot hide it.)
65e6c79647SMax Reitz    _send_qemu_cmd $QEMU_HANDLE \
66e6c79647SMax Reitz        "{'execute': 'block-export-add',
67e6c79647SMax Reitz          'arguments': {
68e6c79647SMax Reitz              'type': 'fuse',
69e6c79647SMax Reitz              'id': '$1',
70e6c79647SMax Reitz              'node-name': '${4:-node-format}',
71e6c79647SMax Reitz              $2
72e6c79647SMax Reitz          } }" \
73e6c79647SMax Reitz        "${3:-return}" \
748fc54f94SMax Reitz        | _filter_imgfmt \
758fc54f94SMax Reitz        | grep -v 'option allow_other only allowed if'
76e6c79647SMax Reitz}
77e6c79647SMax Reitz
78e6c79647SMax Reitz# $1: Export ID
79e6c79647SMax Reitzfuse_export_del()
80e6c79647SMax Reitz{
81effd60c8SStefan Hajnoczi    capture_events="BLOCK_EXPORT_DELETED" \
82e6c79647SMax Reitz    _send_qemu_cmd $QEMU_HANDLE \
83e6c79647SMax Reitz        "{'execute': 'block-export-del',
84e6c79647SMax Reitz          'arguments': {
85e6c79647SMax Reitz              'id': '$1'
86e6c79647SMax Reitz          } }" \
87e6c79647SMax Reitz        'return'
88e6c79647SMax Reitz
89effd60c8SStefan Hajnoczi    _wait_event $QEMU_HANDLE \
90e6c79647SMax Reitz        'BLOCK_EXPORT_DELETED'
91e6c79647SMax Reitz}
92e6c79647SMax Reitz
93e6c79647SMax Reitz# Return the length of the protocol file
94e6c79647SMax Reitz# $1: Protocol node export mount point
95e6c79647SMax Reitz# $2: Original file (to compare)
96e6c79647SMax Reitzget_proto_len()
97e6c79647SMax Reitz{
98e6c79647SMax Reitz    len1=$(stat -c '%s' "$1")
99e6c79647SMax Reitz    len2=$(stat -c '%s' "$2")
100e6c79647SMax Reitz
101e6c79647SMax Reitz    if [ "$len1" != "$len2" ]; then
102e6c79647SMax Reitz        echo 'ERROR: Length of export and original differ:' >&2
103e6c79647SMax Reitz        echo "$len1 != $len2" >&2
104e6c79647SMax Reitz    else
105e6c79647SMax Reitz        echo '(OK: Lengths of export and original are the same)' >&2
106e6c79647SMax Reitz    fi
107e6c79647SMax Reitz
108e6c79647SMax Reitz    echo "$len1"
109e6c79647SMax Reitz}
110e6c79647SMax Reitz
111e6c79647SMax ReitzCOPIED_IMG="$TEST_IMG.copy"
112e6c79647SMax ReitzEXT_MP="$TEST_IMG.fuse"
113e6c79647SMax Reitz
114e6c79647SMax Reitzecho '=== Set up ==='
115e6c79647SMax Reitz
116e6c79647SMax Reitz# Create image with random data
117e6c79647SMax Reitz_make_test_img 64M
118e6c79647SMax Reitz$QEMU_IO -c 'write -s /dev/urandom 0 64M' "$TEST_IMG" | _filter_qemu_io
119e6c79647SMax Reitz
120e6c79647SMax Reitz_launch_qemu
121e6c79647SMax Reitz_send_qemu_cmd $QEMU_HANDLE \
122e6c79647SMax Reitz    "{'execute': 'qmp_capabilities'}" \
123e6c79647SMax Reitz    'return'
124e6c79647SMax Reitz
125e6c79647SMax Reitz# Separate blockdev-add calls for format and protocol so we can remove
126e6c79647SMax Reitz# the format layer later on
127e6c79647SMax Reitz_send_qemu_cmd $QEMU_HANDLE \
128e6c79647SMax Reitz    "{'execute': 'blockdev-add',
129e6c79647SMax Reitz      'arguments': {
130e6c79647SMax Reitz          'driver': 'file',
131e6c79647SMax Reitz          'node-name': 'node-protocol',
132e6c79647SMax Reitz          'filename': '$TEST_IMG'
133e6c79647SMax Reitz      } }" \
134e6c79647SMax Reitz    'return'
135e6c79647SMax Reitz
136e6c79647SMax Reitz_send_qemu_cmd $QEMU_HANDLE \
137e6c79647SMax Reitz    "{'execute': 'blockdev-add',
138e6c79647SMax Reitz      'arguments': {
139e6c79647SMax Reitz          'driver': '$IMGFMT',
140e6c79647SMax Reitz          'node-name': 'node-format',
141e6c79647SMax Reitz          'file': 'node-protocol'
142e6c79647SMax Reitz      } }" \
143e6c79647SMax Reitz    'return'
144e6c79647SMax Reitz
145e6c79647SMax Reitzecho
146e6c79647SMax Reitzecho '=== Mountpoint not present ==='
147e6c79647SMax Reitz
148e6c79647SMax Reitzrmdir "$EXT_MP" 2>/dev/null
149e6c79647SMax Reitzrm -f "$EXT_MP"
150e6c79647SMax Reitzoutput=$(fuse_export_add 'export-err' "'mountpoint': '$EXT_MP'" error)
151e6c79647SMax Reitz
152ea29331bSMarkus Armbrusterif echo "$output" | grep -q "Parameter 'type' does not accept value 'fuse'"; then
153e6c79647SMax Reitz    _notrun 'No FUSE support'
154e6c79647SMax Reitzfi
155e6c79647SMax Reitz
156e6c79647SMax Reitzecho "$output"
157e6c79647SMax Reitz
158e6c79647SMax Reitzecho
159e6c79647SMax Reitzecho '=== Mountpoint is a directory ==='
160e6c79647SMax Reitz
161e6c79647SMax Reitzmkdir "$EXT_MP"
162e6c79647SMax Reitzfuse_export_add 'export-err' "'mountpoint': '$EXT_MP'" error
163e6c79647SMax Reitzrmdir "$EXT_MP"
164e6c79647SMax Reitz
165e6c79647SMax Reitzecho
166e6c79647SMax Reitzecho '=== Mountpoint is a regular file ==='
167e6c79647SMax Reitz
168e6c79647SMax Reitztouch "$EXT_MP"
169e6c79647SMax Reitzfuse_export_add 'export-mp' "'mountpoint': '$EXT_MP'"
170e6c79647SMax Reitz
171e6c79647SMax Reitz# Check that the export presents the same data as the original image
172e6c79647SMax Reitz$QEMU_IMG compare -f raw -F $IMGFMT -U "$EXT_MP" "$TEST_IMG"
173e6c79647SMax Reitz
174f29add26SMax Reitz# Some quick chmod tests
175f29add26SMax Reitzstat -c 'Permissions pre-chmod: %a' "$EXT_MP"
176f29add26SMax Reitz
177f29add26SMax Reitz# Verify that we cannot set +w
178f29add26SMax Reitzchmod u+w "$EXT_MP" 2>&1 | _filter_testdir | _filter_imgfmt
179f29add26SMax Reitzstat -c 'Permissions post-+w: %a' "$EXT_MP"
180f29add26SMax Reitz
181f29add26SMax Reitz# But that we can set, say, +x (if we are so inclined)
182f29add26SMax Reitzchmod u+x "$EXT_MP" 2>&1 | _filter_testdir | _filter_imgfmt
183f29add26SMax Reitzstat -c 'Permissions post-+x: %a' "$EXT_MP"
184f29add26SMax Reitz
185e6c79647SMax Reitzecho
186e6c79647SMax Reitzecho '=== Mount over existing file ==='
187e6c79647SMax Reitz
188e6c79647SMax Reitz# This is the coolest feature of FUSE exports: You can transparently
189e6c79647SMax Reitz# make images in any format appear as raw images
190e6c79647SMax Reitzfuse_export_add 'export-img' "'mountpoint': '$TEST_IMG'"
191e6c79647SMax Reitz
192e6c79647SMax Reitz# Accesses both exports at the same time, so we get a concurrency test
193e6c79647SMax Reitz$QEMU_IMG compare -f raw -F raw -U "$EXT_MP" "$TEST_IMG"
194e6c79647SMax Reitz
195e6c79647SMax Reitz# Just to be sure, we later want to compare the data offline.  Also,
196e6c79647SMax Reitz# this allows us to see that cp works without complaining.
197e6c79647SMax Reitz# (This is not a given, because cp will expect a short read at EOF.
198e6c79647SMax Reitz# Internally, qemu does not allow short reads, so we have to check
199e6c79647SMax Reitz# whether the FUSE export driver lets them work.)
200e6c79647SMax Reitzcp "$TEST_IMG" "$COPIED_IMG"
201e6c79647SMax Reitz
202e6c79647SMax Reitz# $TEST_IMG will be in mode 0400 because it is read-only; we are going
203e6c79647SMax Reitz# to write to the copy, so make it writable
204e6c79647SMax Reitzchmod 0600 "$COPIED_IMG"
205e6c79647SMax Reitz
206e6c79647SMax Reitzecho
207e6c79647SMax Reitzecho '=== Double export ==='
208e6c79647SMax Reitz
209e6c79647SMax Reitz# We have already seen that exporting a node twice works fine, but you
210e6c79647SMax Reitz# cannot export anything twice on the same mount point.  The reason is
211e6c79647SMax Reitz# that qemu has to stat the given mount point, and this would have to
212e6c79647SMax Reitz# be answered by the same qemu instance if it already has an export
213e6c79647SMax Reitz# there.  However, it cannot answer the stat because it is itself
214e6c79647SMax Reitz# caught up in that same stat.
215e6c79647SMax Reitzfuse_export_add 'export-err' "'mountpoint': '$EXT_MP'" error
216e6c79647SMax Reitz
217e6c79647SMax Reitzecho
218e6c79647SMax Reitzecho '=== Remove export ==='
219e6c79647SMax Reitz
220e6c79647SMax Reitz# Double-check that $EXT_MP appears as a non-empty file (the raw image)
22174163addSHanna Reitz$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | head -n 1
222e6c79647SMax Reitz
223e6c79647SMax Reitzfuse_export_del 'export-mp'
224e6c79647SMax Reitz
225e6c79647SMax Reitz# See that the file appears empty again
22674163addSHanna Reitz$QEMU_IMG info -f raw "$EXT_MP" | grep 'virtual size' | head -n 1
227e6c79647SMax Reitz
228e6c79647SMax Reitzecho
229e6c79647SMax Reitzecho '=== Writable export ==='
230e6c79647SMax Reitz
231e6c79647SMax Reitzfuse_export_add 'export-mp' "'mountpoint': '$EXT_MP', 'writable': true"
232e6c79647SMax Reitz
233e6c79647SMax Reitz# Check that writing to the read-only export fails
234e2eec281SHanna Reitzoutput=$($QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TEST_IMG" 2>&1 \
235e2eec281SHanna Reitz             | _filter_qemu_io | _filter_testdir | _filter_imgfmt)
236e2eec281SHanna Reitz
237e2eec281SHanna Reitz# Expected reference output: Opening the file fails because it has no
238e2eec281SHanna Reitz# write permission
239e2eec281SHanna Reitzreference="Could not open 'TEST_DIR/t.IMGFMT': Permission denied"
240e2eec281SHanna Reitz
241e2eec281SHanna Reitzif echo "$output" | grep -q "$reference"; then
242e2eec281SHanna Reitz    echo "Writing to read-only export failed: OK"
243e2eec281SHanna Reitzelif echo "$output" | grep -q "write failed: Permission denied"; then
244e2eec281SHanna Reitz    # With CAP_DAC_OVERRIDE (e.g. when running this test as root), the export
245e2eec281SHanna Reitz    # can be opened regardless of its file permissions, but writing will then
246e2eec281SHanna Reitz    # fail.  This is not the result for which we want to test, so count this as
247e2eec281SHanna Reitz    # a SKIP.
248e2eec281SHanna Reitz    _casenotrun "Opening RO export as R/W succeeded, perhaps because of" \
249e2eec281SHanna Reitz        "CAP_DAC_OVERRIDE"
250e2eec281SHanna Reitz
251e2eec281SHanna Reitz    # Still, write this to the reference output to make the test pass
252e2eec281SHanna Reitz    echo "Writing to read-only export failed: OK"
253e2eec281SHanna Reitzelse
254e2eec281SHanna Reitz    echo "Writing to read-only export failed: ERROR"
255e2eec281SHanna Reitz    echo "$output"
256e2eec281SHanna Reitzfi
257e6c79647SMax Reitz
258e6c79647SMax Reitz# But here it should work
259e6c79647SMax Reitz$QEMU_IO -f raw -c 'write -P 42 1M 64k' "$EXT_MP" | _filter_qemu_io
260e6c79647SMax Reitz
261e6c79647SMax Reitz# (Adjust the copy, too)
262e6c79647SMax Reitz$QEMU_IO -f raw -c 'write -P 42 1M 64k' "$COPIED_IMG" | _filter_qemu_io
263e6c79647SMax Reitz
264e6c79647SMax Reitzecho
265e6c79647SMax Reitzecho '=== Resizing exports ==='
266e6c79647SMax Reitz
267e6c79647SMax Reitz# Here, we need to export the protocol node -- the format layer may
268e6c79647SMax Reitz# not be growable, simply because the format does not support it.
269e6c79647SMax Reitz
270e6c79647SMax Reitz# Remove all exports and the format node first so permissions will not
271e6c79647SMax Reitz# get in the way
272e6c79647SMax Reitzfuse_export_del 'export-mp'
273e6c79647SMax Reitzfuse_export_del 'export-img'
274e6c79647SMax Reitz
275e6c79647SMax Reitz_send_qemu_cmd $QEMU_HANDLE \
276e6c79647SMax Reitz    "{'execute': 'blockdev-del',
277e6c79647SMax Reitz      'arguments': {
278e6c79647SMax Reitz          'node-name': 'node-format'
279e6c79647SMax Reitz      } }" \
280e6c79647SMax Reitz    'return'
281e6c79647SMax Reitz
282e6c79647SMax Reitz# Now export the protocol node
283e6c79647SMax Reitzfuse_export_add \
284e6c79647SMax Reitz    'export-mp' \
285e6c79647SMax Reitz    "'mountpoint': '$EXT_MP', 'writable': true" \
286e6c79647SMax Reitz    'return' \
287e6c79647SMax Reitz    'node-protocol'
288e6c79647SMax Reitz
289e6c79647SMax Reitzecho
290e6c79647SMax Reitzecho '--- Try growing non-growable export ---'
291e6c79647SMax Reitz
292e6c79647SMax Reitz# Get the current size so we can write beyond the EOF
293e6c79647SMax Reitzorig_len=$(get_proto_len "$EXT_MP" "$TEST_IMG")
294d2b3e32bSEric Blakeorig_disk_usage=$(disk_usage "$TEST_IMG")
295e6c79647SMax Reitz
296e6c79647SMax Reitz# Should fail (exports are non-growable by default)
297e6c79647SMax Reitz# (Note that qemu-io can never write beyond the EOF, so we have to use
298e6c79647SMax Reitz# dd here)
299e6c79647SMax Reitzdd if=/dev/zero of="$EXT_MP" bs=1 count=64k seek=$orig_len 2>&1 \
300e6c79647SMax Reitz    | _filter_testdir | _filter_imgfmt
301e6c79647SMax Reitz
302e6c79647SMax Reitzecho
303e6c79647SMax Reitzecho '--- Resize export ---'
304e6c79647SMax Reitz
305e6c79647SMax Reitz# But we can truncate it explicitly; even with fallocate
306e6c79647SMax Reitzfallocate -o "$orig_len" -l 64k "$EXT_MP"
307e6c79647SMax Reitz
308e6c79647SMax Reitznew_len=$(get_proto_len "$EXT_MP" "$TEST_IMG")
309e6c79647SMax Reitzif [ "$new_len" != "$((orig_len + 65536))" ]; then
310e6c79647SMax Reitz    echo 'ERROR: Unexpected post-truncate image size:'
311e6c79647SMax Reitz    echo "$new_len != $((orig_len + 65536))"
312e6c79647SMax Reitzelse
313e6c79647SMax Reitz    echo 'OK: Post-truncate image size is as expected'
314e6c79647SMax Reitzfi
315e6c79647SMax Reitz
316d2b3e32bSEric Blakenew_disk_usage=$(disk_usage "$TEST_IMG")
317e6c79647SMax Reitzif [ "$new_disk_usage" -gt "$orig_disk_usage" ]; then
318e6c79647SMax Reitz    echo 'OK: Disk usage grew with fallocate'
319e6c79647SMax Reitzelse
320e6c79647SMax Reitz    echo 'ERROR: Disk usage did not grow despite fallocate:'
321e6c79647SMax Reitz    echo "$orig_disk_usage => $new_disk_usage"
322e6c79647SMax Reitzfi
323e6c79647SMax Reitz
324e6c79647SMax Reitzecho
325e6c79647SMax Reitzecho '--- Try growing growable export ---'
326e6c79647SMax Reitz
327e6c79647SMax Reitz# Now export as growable
328e6c79647SMax Reitzfuse_export_del 'export-mp'
329e6c79647SMax Reitzfuse_export_add \
330e6c79647SMax Reitz    'export-mp' \
331e6c79647SMax Reitz    "'mountpoint': '$EXT_MP', 'writable': true, 'growable': true" \
332e6c79647SMax Reitz    'return' \
333e6c79647SMax Reitz    'node-protocol'
334e6c79647SMax Reitz
335e6c79647SMax Reitz# Now we should be able to write beyond the EOF
336e6c79647SMax Reitzdd if=/dev/zero of="$EXT_MP" bs=1 count=64k seek=$new_len 2>&1 \
337e6c79647SMax Reitz    | _filter_testdir | _filter_imgfmt
338e6c79647SMax Reitz
339e6c79647SMax Reitznew_len=$(get_proto_len "$EXT_MP" "$TEST_IMG")
340e6c79647SMax Reitzif [ "$new_len" != "$((orig_len + 131072))" ]; then
341e6c79647SMax Reitz    echo 'ERROR: Unexpected post-grow image size:'
342e6c79647SMax Reitz    echo "$new_len != $((orig_len + 131072))"
343e6c79647SMax Reitzelse
344e6c79647SMax Reitz    echo 'OK: Post-grow image size is as expected'
345e6c79647SMax Reitzfi
346e6c79647SMax Reitz
347e6c79647SMax Reitzecho
348e6c79647SMax Reitzecho '--- Shrink export ---'
349e6c79647SMax Reitz
350e6c79647SMax Reitz# Now go back to the original size
351e6c79647SMax Reitztruncate -s "$orig_len" "$EXT_MP"
352e6c79647SMax Reitz
353e6c79647SMax Reitznew_len=$(get_proto_len "$EXT_MP" "$TEST_IMG")
354e6c79647SMax Reitzif [ "$new_len" != "$orig_len" ]; then
355e6c79647SMax Reitz    echo 'ERROR: Unexpected post-truncate image size:'
356e6c79647SMax Reitz    echo "$new_len != $orig_len"
357e6c79647SMax Reitzelse
358e6c79647SMax Reitz    echo 'OK: Post-truncate image size is as expected'
359e6c79647SMax Reitzfi
360e6c79647SMax Reitz
361e6c79647SMax Reitzecho
362e6c79647SMax Reitzecho '=== Tear down ==='
363e6c79647SMax Reitz
364e6c79647SMax Reitz_send_qemu_cmd $QEMU_HANDLE \
365e6c79647SMax Reitz    "{'execute': 'quit'}" \
366e6c79647SMax Reitz    'return'
367e6c79647SMax Reitz
368e6c79647SMax Reitzwait=yes _cleanup_qemu
369e6c79647SMax Reitz
370e6c79647SMax Reitzecho
371e6c79647SMax Reitzecho '=== Compare copy with original ==='
372e6c79647SMax Reitz
373e6c79647SMax Reitz$QEMU_IMG compare -f raw -F $IMGFMT "$COPIED_IMG" "$TEST_IMG"
37427e0d8b5SHanna Czenczek_cleanup_test_img
37527e0d8b5SHanna Czenczek
37627e0d8b5SHanna Czenczekecho
37727e0d8b5SHanna Czenczekecho '=== Writing zeroes while unmapping ==='
37827e0d8b5SHanna Czenczek# Regression test for https://gitlab.com/qemu-project/qemu/-/issues/1507
37927e0d8b5SHanna Czenczek_make_test_img 64M
38027e0d8b5SHanna Czenczek$QEMU_IO -c 'write -s /dev/urandom 0 64M' "$TEST_IMG" | _filter_qemu_io
38127e0d8b5SHanna Czenczek
38227e0d8b5SHanna Czenczek_launch_qemu
38327e0d8b5SHanna Czenczek_send_qemu_cmd $QEMU_HANDLE \
38427e0d8b5SHanna Czenczek    "{'execute': 'qmp_capabilities'}" \
38527e0d8b5SHanna Czenczek    'return'
38627e0d8b5SHanna Czenczek
38727e0d8b5SHanna Czenczek_send_qemu_cmd $QEMU_HANDLE \
38827e0d8b5SHanna Czenczek    "{'execute': 'blockdev-add',
38927e0d8b5SHanna Czenczek      'arguments': {
39027e0d8b5SHanna Czenczek          'driver': '$IMGFMT',
39127e0d8b5SHanna Czenczek          'node-name': 'node-format',
39227e0d8b5SHanna Czenczek          'file': {
39327e0d8b5SHanna Czenczek              'driver': 'file',
39427e0d8b5SHanna Czenczek              'filename': '$TEST_IMG'
39527e0d8b5SHanna Czenczek          }
39627e0d8b5SHanna Czenczek      } }" \
39727e0d8b5SHanna Czenczek    'return'
39827e0d8b5SHanna Czenczek
39927e0d8b5SHanna Czenczekfuse_export_add 'export' "'mountpoint': '$EXT_MP', 'writable': true"
40027e0d8b5SHanna Czenczek
40127e0d8b5SHanna Czenczek# Try writing zeroes by unmapping
40227e0d8b5SHanna Czenczek$QEMU_IO -f raw -c 'write -zu 0 64M' "$EXT_MP" | _filter_qemu_io
40327e0d8b5SHanna Czenczek
40427e0d8b5SHanna Czenczek# Check the result
40527e0d8b5SHanna Czenczek$QEMU_IO -f raw -c 'read -P 0 0 64M' "$EXT_MP" | _filter_qemu_io
40627e0d8b5SHanna Czenczek
40727e0d8b5SHanna Czenczek_send_qemu_cmd $QEMU_HANDLE \
40827e0d8b5SHanna Czenczek    "{'execute': 'quit'}" \
40927e0d8b5SHanna Czenczek    'return'
41027e0d8b5SHanna Czenczek
41127e0d8b5SHanna Czenczekwait=yes _cleanup_qemu
41227e0d8b5SHanna Czenczek
41327e0d8b5SHanna Czenczek# Check the original image
41427e0d8b5SHanna Czenczek$QEMU_IO -c 'read -P 0 0 64M' "$TEST_IMG" | _filter_qemu_io
41527e0d8b5SHanna Czenczek
41627e0d8b5SHanna Czenczek_cleanup_test_img
417e6c79647SMax Reitz
418e6c79647SMax Reitz# success, all done
419e6c79647SMax Reitzecho "*** done"
420e6c79647SMax Reitzrm -f $seq.full
421e6c79647SMax Reitzstatus=0
422