aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-01-14 15:56:30 +0000
committerPeter Maydell <peter.maydell@linaro.org>2022-01-14 15:56:30 +0000
commit1cd2ad11d37c48f284f557954e1df675b126264c (patch)
tree09d75bcd7b586c4aa78cef09364e4020a573a8d4 /tests
parent0b3f07ebf2954d28debd7493fef551152e08875b (diff)
parente5e748739562268ef4063ee77bf53ad7040b25c7 (diff)
downloadqemu-1cd2ad11d37c48f284f557954e1df675b126264c.zip
qemu-1cd2ad11d37c48f284f557954e1df675b126264c.tar.gz
qemu-1cd2ad11d37c48f284f557954e1df675b126264c.tar.bz2
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches - qemu-storage-daemon: Add vhost-user-blk help - block-backend: Fix use-after-free for BDS pointers after aio_poll() - qemu-img: Fix sparseness of output image with unaligned ranges - vvfat: Fix crashes in read-write mode - Fix device deletion events with -device JSON syntax - Code cleanups # gpg: Signature made Fri 14 Jan 2022 13:50:16 GMT # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: iotests/testrunner.py: refactor test_field_width block: drop BLK_PERM_GRAPH_MOD qemu-img: make is_allocated_sectors() more efficient iotests: Test qemu-img convert of zeroed data cluster vvfat: Fix vvfat_write() for writes before the root directory vvfat: Fix size of temporary qcow file iotests/308: Fix for CAP_DAC_OVERRIDE iotests/stream-error-on-reset: New test block-backend: prevent dangling BDS pointers across aio_poll() qapi/block: Restrict vhost-user-blk to CONFIG_VHOST_USER_BLK_SERVER qemu-storage-daemon: Add vhost-user-blk help docs: Correct 'vhost-user-blk' spelling softmmu: fix device deletion events with -device JSON syntax include/sysemu/blockdev.h: remove drive_get_max_devs include/sysemu/blockdev.h: remove drive_mark_claimed_by_board and inline drive_def block_int: make bdrv_backing_overridden static Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rwxr-xr-xtests/qemu-iotests/1221
-rw-r--r--tests/qemu-iotests/122.out2
-rw-r--r--tests/qemu-iotests/273.out4
-rwxr-xr-xtests/qemu-iotests/30825
-rw-r--r--tests/qemu-iotests/308.out2
-rw-r--r--tests/qemu-iotests/testrunner.py21
-rwxr-xr-xtests/qemu-iotests/tests/stream-error-on-reset140
-rw-r--r--tests/qemu-iotests/tests/stream-error-on-reset.out5
-rw-r--r--tests/qtest/device-plug-test.c19
9 files changed, 201 insertions, 18 deletions
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
index efb260d..be0f6b7 100755
--- a/tests/qemu-iotests/122
+++ b/tests/qemu-iotests/122
@@ -251,6 +251,7 @@ $QEMU_IO -c "write -P 0 0 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_test
$QEMU_IO -c "write 0 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
$QEMU_IO -c "write 8k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
$QEMU_IO -c "write 17k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
+$QEMU_IO -c "write -P 0 65k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
for min_sparse in 4k 8k; do
echo
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
index 8fbdac2..e18766e 100644
--- a/tests/qemu-iotests/122.out
+++ b/tests/qemu-iotests/122.out
@@ -192,6 +192,8 @@ wrote 1024/1024 bytes at offset 8192
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 1024/1024 bytes at offset 17408
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 66560
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
convert -S 4k
[{ "start": 0, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out
index 4e840b6..6a74a81 100644
--- a/tests/qemu-iotests/273.out
+++ b/tests/qemu-iotests/273.out
@@ -204,7 +204,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"name": "file",
"parent": 5,
"shared-perm": [
- "graph-mod",
"write-unchanged",
"consistent-read"
],
@@ -219,7 +218,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"name": "backing",
"parent": 5,
"shared-perm": [
- "graph-mod",
"resize",
"write-unchanged",
"write",
@@ -233,7 +231,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"name": "file",
"parent": 3,
"shared-perm": [
- "graph-mod",
"write-unchanged",
"consistent-read"
],
@@ -246,7 +243,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"name": "backing",
"parent": 3,
"shared-perm": [
- "graph-mod",
"resize",
"write-unchanged",
"write",
diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308
index 2e3f8f4..bde4aac 100755
--- a/tests/qemu-iotests/308
+++ b/tests/qemu-iotests/308
@@ -230,8 +230,29 @@ echo '=== Writable export ==='
fuse_export_add 'export-mp' "'mountpoint': '$EXT_MP', 'writable': true"
# Check that writing to the read-only export fails
-$QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TEST_IMG" 2>&1 \
- | _filter_qemu_io | _filter_testdir | _filter_imgfmt
+output=$($QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TEST_IMG" 2>&1 \
+ | _filter_qemu_io | _filter_testdir | _filter_imgfmt)
+
+# Expected reference output: Opening the file fails because it has no
+# write permission
+reference="Could not open 'TEST_DIR/t.IMGFMT': Permission denied"
+
+if echo "$output" | grep -q "$reference"; then
+ echo "Writing to read-only export failed: OK"
+elif echo "$output" | grep -q "write failed: Permission denied"; then
+ # With CAP_DAC_OVERRIDE (e.g. when running this test as root), the export
+ # can be opened regardless of its file permissions, but writing will then
+ # fail. This is not the result for which we want to test, so count this as
+ # a SKIP.
+ _casenotrun "Opening RO export as R/W succeeded, perhaps because of" \
+ "CAP_DAC_OVERRIDE"
+
+ # Still, write this to the reference output to make the test pass
+ echo "Writing to read-only export failed: OK"
+else
+ echo "Writing to read-only export failed: ERROR"
+ echo "$output"
+fi
# But here it should work
$QEMU_IO -f raw -c 'write -P 42 1M 64k' "$EXT_MP" | _filter_qemu_io
diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out
index fc47bb1..e4467a1 100644
--- a/tests/qemu-iotests/308.out
+++ b/tests/qemu-iotests/308.out
@@ -95,7 +95,7 @@ virtual size: 0 B (0 bytes)
'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true
} }
{"return": {}}
-qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
+Writing to read-only export failed: OK
wrote 65536/65536 bytes at offset 1048576
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 1048576
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
index 0feaa39..15788f9 100644
--- a/tests/qemu-iotests/testrunner.py
+++ b/tests/qemu-iotests/testrunner.py
@@ -174,19 +174,17 @@ class TestRunner(ContextManager['TestRunner']):
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
self._stack.close()
- def test_print_one_line(self, test: str, starttime: str,
+ def test_print_one_line(self, test: str,
+ test_field_width: int,
+ starttime: str,
endtime: Optional[str] = None, status: str = '...',
lasttime: Optional[float] = None,
thistime: Optional[float] = None,
description: str = '',
- test_field_width: Optional[int] = None,
end: str = '\n') -> None:
""" Print short test info before/after test run """
test = os.path.basename(test)
- if test_field_width is None:
- test_field_width = 8
-
if self.makecheck and status != '...':
if status and status != 'pass':
status = f' [{status}]'
@@ -328,7 +326,7 @@ class TestRunner(ContextManager['TestRunner']):
casenotrun=casenotrun)
def run_test(self, test: str,
- test_field_width: Optional[int] = None,
+ test_field_width: int,
mp: bool = False) -> TestResult:
"""
Run one test and print short status
@@ -347,20 +345,21 @@ class TestRunner(ContextManager['TestRunner']):
if not self.makecheck:
self.test_print_one_line(test=test,
+ test_field_width=test_field_width,
status = 'started' if mp else '...',
starttime=start,
lasttime=last_el,
- end = '\n' if mp else '\r',
- test_field_width=test_field_width)
+ end = '\n' if mp else '\r')
res = self.do_run_test(test, mp)
end = datetime.datetime.now().strftime('%H:%M:%S')
- self.test_print_one_line(test=test, status=res.status,
+ self.test_print_one_line(test=test,
+ test_field_width=test_field_width,
+ status=res.status,
starttime=start, endtime=end,
lasttime=last_el, thistime=res.elapsed,
- description=res.description,
- test_field_width=test_field_width)
+ description=res.description)
if res.casenotrun:
print(res.casenotrun)
diff --git a/tests/qemu-iotests/tests/stream-error-on-reset b/tests/qemu-iotests/tests/stream-error-on-reset
new file mode 100755
index 0000000..7eaedb2
--- /dev/null
+++ b/tests/qemu-iotests/tests/stream-error-on-reset
@@ -0,0 +1,140 @@
+#!/usr/bin/env python3
+# group: rw quick
+#
+# Test what happens when a stream job completes in a blk_drain().
+#
+# Copyright (C) 2022 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import iotests
+from iotests import imgfmt, qemu_img_create, qemu_io_silent, QMPTestCase
+
+
+image_size = 1 * 1024 * 1024
+data_size = 64 * 1024
+base = os.path.join(iotests.test_dir, 'base.img')
+top = os.path.join(iotests.test_dir, 'top.img')
+
+
+# We want to test completing a stream job in a blk_drain().
+#
+# The blk_drain() we are going to use is a virtio-scsi device resetting,
+# which we can trigger by resetting the system.
+#
+# In order to have the block job complete on drain, we (1) throttle its
+# base image so we can start the drain after it has begun, but before it
+# completes, and (2) make it encounter an I/O error on the ensuing write.
+# (If it completes regularly, the completion happens after the drain for
+# some reason.)
+
+class TestStreamErrorOnReset(QMPTestCase):
+ def setUp(self) -> None:
+ """
+ Create two images:
+ - base image {base} with {data_size} bytes allocated
+ - top image {top} without any data allocated
+
+ And the following VM configuration:
+ - base image throttled to {data_size}
+ - top image with a blkdebug configuration so the first write access
+ to it will result in an error
+ - top image is attached to a virtio-scsi device
+ """
+ assert qemu_img_create('-f', imgfmt, base, str(image_size)) == 0
+ assert qemu_io_silent('-c', f'write 0 {data_size}', base) == 0
+ assert qemu_img_create('-f', imgfmt, top, str(image_size)) == 0
+
+ self.vm = iotests.VM()
+ self.vm.add_args('-accel', 'tcg') # Make throttling work properly
+ self.vm.add_object(self.vm.qmp_to_opts({
+ 'qom-type': 'throttle-group',
+ 'id': 'thrgr',
+ 'x-bps-total': str(data_size)
+ }))
+ self.vm.add_blockdev(self.vm.qmp_to_opts({
+ 'driver': imgfmt,
+ 'node-name': 'base',
+ 'file': {
+ 'driver': 'throttle',
+ 'throttle-group': 'thrgr',
+ 'file': {
+ 'driver': 'file',
+ 'filename': base
+ }
+ }
+ }))
+ self.vm.add_blockdev(self.vm.qmp_to_opts({
+ 'driver': imgfmt,
+ 'node-name': 'top',
+ 'file': {
+ 'driver': 'blkdebug',
+ 'node-name': 'top-blkdebug',
+ 'inject-error': [{
+ 'event': 'pwritev',
+ 'immediately': 'true',
+ 'once': 'true'
+ }],
+ 'image': {
+ 'driver': 'file',
+ 'filename': top
+ }
+ },
+ 'backing': 'base'
+ }))
+ self.vm.add_device(self.vm.qmp_to_opts({
+ 'driver': 'virtio-scsi',
+ 'id': 'vscsi'
+ }))
+ self.vm.add_device(self.vm.qmp_to_opts({
+ 'driver': 'scsi-hd',
+ 'bus': 'vscsi.0',
+ 'drive': 'top'
+ }))
+ self.vm.launch()
+
+ def tearDown(self) -> None:
+ self.vm.shutdown()
+ os.remove(top)
+ os.remove(base)
+
+ def test_stream_error_on_reset(self) -> None:
+ # Launch a stream job, which will take at least a second to
+ # complete, because the base image is throttled (so we can
+ # get in between it having started and it having completed)
+ res = self.vm.qmp('block-stream', job_id='stream', device='top')
+ self.assert_qmp(res, 'return', {})
+
+ while True:
+ ev = self.vm.event_wait('JOB_STATUS_CHANGE')
+ if ev['data']['status'] == 'running':
+ # Once the stream job is running, reset the system, which
+ # forces the virtio-scsi device to be reset, thus draining
+ # the stream job, and making it complete. Completing
+ # inside of that drain should not result in a segfault.
+ res = self.vm.qmp('system_reset')
+ self.assert_qmp(res, 'return', {})
+ elif ev['data']['status'] == 'null':
+ # The test is done once the job is gone
+ break
+
+
+if __name__ == '__main__':
+ # Passes with any format with backing file support, but qed and
+ # qcow1 do not seem to exercise the used-to-be problematic code
+ # path, so there is no point in having them in this list
+ iotests.main(supported_fmts=['qcow2', 'vmdk'],
+ supported_protocols=['file'])
diff --git a/tests/qemu-iotests/tests/stream-error-on-reset.out b/tests/qemu-iotests/tests/stream-error-on-reset.out
new file mode 100644
index 0000000..ae1213e
--- /dev/null
+++ b/tests/qemu-iotests/tests/stream-error-on-reset.out
@@ -0,0 +1,5 @@
+.
+----------------------------------------------------------------------
+Ran 1 tests
+
+OK
diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c
index 559d477..ad79bd4 100644
--- a/tests/qtest/device-plug-test.c
+++ b/tests/qtest/device-plug-test.c
@@ -77,6 +77,23 @@ static void test_pci_unplug_request(void)
qtest_quit(qtest);
}
+static void test_pci_unplug_json_request(void)
+{
+ QTestState *qtest = qtest_initf(
+ "-device '{\"driver\": \"virtio-mouse-pci\", \"id\": \"dev0\"}'");
+
+ /*
+ * Request device removal. As the guest is not running, the request won't
+ * be processed. However during system reset, the removal will be
+ * handled, removing the device.
+ */
+ device_del(qtest, "dev0");
+ system_reset(qtest);
+ wait_device_deleted_event(qtest, "dev0");
+
+ qtest_quit(qtest);
+}
+
static void test_ccw_unplug(void)
{
QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0");
@@ -145,6 +162,8 @@ int main(int argc, char **argv)
*/
qtest_add_func("/device-plug/pci-unplug-request",
test_pci_unplug_request);
+ qtest_add_func("/device-plug/pci-unplug-json-request",
+ test_pci_unplug_json_request);
if (!strcmp(arch, "s390x")) {
qtest_add_func("/device-plug/ccw-unplug",