aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/qemu-iotests/tests/iothreads-commit-active85
-rw-r--r--tests/qemu-iotests/tests/iothreads-commit-active.out23
-rw-r--r--tests/qtest/dbus-display-test.c43
-rw-r--r--tests/qtest/libqtest.c5
-rw-r--r--tests/qtest/libqtest.h9
-rw-r--r--tests/qtest/meson.build2
-rw-r--r--tests/unit/test-block-iothread.c7
7 files changed, 169 insertions, 5 deletions
diff --git a/tests/qemu-iotests/tests/iothreads-commit-active b/tests/qemu-iotests/tests/iothreads-commit-active
new file mode 100755
index 0000000000..4010a4871f
--- /dev/null
+++ b/tests/qemu-iotests/tests/iothreads-commit-active
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+# group: rw quick auto
+#
+# Copyright (C) 2023 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/>.
+#
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
+
+import asyncio
+import iotests
+
+iotests.script_initialize(supported_fmts=['qcow2'],
+ supported_platforms=['linux'])
+iotests.verify_virtio_scsi_pci_or_ccw()
+
+with iotests.FilePath('disk0.img') as img_path, \
+ iotests.FilePath('disk0-snap.img') as snap_path, \
+ iotests.FilePath('mirror-src.img') as src_path, \
+ iotests.FilePath('mirror-dst.img') as dst_path, \
+ iotests.VM() as vm:
+
+ img_size = '10M'
+ iotests.qemu_img_create('-f', iotests.imgfmt, img_path, img_size)
+ iotests.qemu_img_create('-f', iotests.imgfmt, '-b', img_path,
+ '-F', iotests.imgfmt, snap_path)
+ iotests.qemu_img_create('-f', iotests.imgfmt, src_path, img_size)
+ iotests.qemu_img_create('-f', iotests.imgfmt, dst_path, img_size)
+
+ iotests.qemu_io_log('-c', 'write 0 64k', img_path)
+ iotests.qemu_io_log('-c', 'write 1M 64k', snap_path)
+ iotests.qemu_io_log('-c', 'write 3M 64k', snap_path)
+
+ iotests.qemu_io_log('-c', f'write 0 {img_size}', src_path)
+
+ iotests.log('Launching VM...')
+ vm.add_object('iothread,id=iothread0')
+ vm.add_object('throttle-group,x-bps-write=1048576,id=tg0')
+ vm.add_blockdev(f'file,node-name=disk0-file,filename={img_path}')
+ vm.add_blockdev('qcow2,node-name=disk0-fmt,file=disk0-file')
+ vm.add_drive(snap_path, 'backing=disk0-fmt,node-name=disk0',
+ interface='none')
+ vm.add_device('virtio-scsi,iothread=iothread0')
+ vm.add_device('scsi-hd,drive=drive0')
+
+ vm.add_blockdev(f'file,filename={src_path},node-name=mirror-src-file')
+ vm.add_blockdev('qcow2,file=mirror-src-file,node-name=mirror-src')
+ vm.add_blockdev(f'file,filename={dst_path},node-name=mirror-dst-file')
+ vm.add_blockdev('qcow2,file=mirror-dst-file,node-name=mirror-dst-fmt')
+ vm.add_blockdev('throttle,throttle-group=tg0,file=mirror-dst-fmt,'
+ 'node-name=mirror-dst')
+ vm.add_device('scsi-hd,drive=mirror-src')
+
+ vm.launch()
+
+ # The background I/O is created on unrelated nodes (so that they won't be
+ # drained together with the other ones), but on the same iothread
+ iotests.log('Creating some background I/O...')
+ iotests.log(vm.qmp('blockdev-mirror', job_id='job0', sync='full',
+ device='mirror-src', target='mirror-dst',
+ auto_dismiss=False))
+
+ iotests.log('Starting active commit...')
+ iotests.log(vm.qmp('block-commit', device='disk0', job_id='job1',
+ auto_dismiss=False))
+
+ # Should succeed and not time out
+ try:
+ vm.run_job('job1', wait=5.0)
+ vm.shutdown()
+ except asyncio.TimeoutError:
+ # VM may be stuck, kill it
+ vm.kill()
+ raise
diff --git a/tests/qemu-iotests/tests/iothreads-commit-active.out b/tests/qemu-iotests/tests/iothreads-commit-active.out
new file mode 100644
index 0000000000..4afd50b8d3
--- /dev/null
+++ b/tests/qemu-iotests/tests/iothreads-commit-active.out
@@ -0,0 +1,23 @@
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+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 3145728
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+wrote 10485760/10485760 bytes at offset 0
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+Launching VM...
+Creating some background I/O...
+{"return": {}}
+Starting active commit...
+{"return": {}}
+{"execute": "job-complete", "arguments": {"id": "job1"}}
+{"return": {}}
+{"data": {"device": "job1", "len": 131072, "offset": 131072, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"device": "job1", "len": 131072, "offset": 131072, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "job-dismiss", "arguments": {"id": "job1"}}
+{"return": {}}
diff --git a/tests/qtest/dbus-display-test.c b/tests/qtest/dbus-display-test.c
index fef025ac6f..21edaa1e32 100644
--- a/tests/qtest/dbus-display-test.c
+++ b/tests/qtest/dbus-display-test.c
@@ -1,4 +1,5 @@
#include "qemu/osdep.h"
+#include "qemu/sockets.h"
#include "qemu/dbus.h"
#include "qemu/sockets.h"
#include <gio/gio.h>
@@ -14,7 +15,11 @@ test_dbus_p2p_from_fd(int fd)
g_autoptr(GSocketConnection) socketc = NULL;
GDBusConnection *conn;
+#ifdef WIN32
+ socket = g_socket_new_from_fd(_get_osfhandle(fd), &err);
+#else
socket = g_socket_new_from_fd(fd, &err);
+#endif
g_assert_no_error(err);
socketc = g_socket_connection_factory_create_connection(socket);
@@ -126,7 +131,10 @@ test_dbus_console_registered(GObject *source_object,
qemu_dbus_display1_console_call_register_listener_finish(
QEMU_DBUS_DISPLAY1_CONSOLE(source_object),
- NULL, res, &err);
+#ifndef WIN32
+ NULL,
+#endif
+ res, &err);
g_assert_no_error(err);
test->listener_conn = g_thread_join(test->thread);
@@ -145,17 +153,25 @@ test_dbus_display_console(void)
g_autoptr(GError) err = NULL;
g_autoptr(GDBusConnection) conn = NULL;
g_autoptr(QemuDBusDisplay1ConsoleProxy) console = NULL;
- g_autoptr(GUnixFDList) fd_list = NULL;
g_autoptr(GMainLoop) loop = NULL;
QTestState *qts = NULL;
- int pair[2], idx;
+ int pair[2];
TestDBusConsoleRegister test;
+#ifdef WIN32
+ WSAPROTOCOL_INFOW info;
+ g_autoptr(GVariant) listener = NULL;
+#else
+ g_autoptr(GUnixFDList) fd_list = NULL;
+ int idx;
+#endif
test_setup(&qts, &conn);
g_assert_cmpint(qemu_socketpair(AF_UNIX, SOCK_STREAM, 0, pair), ==, 0);
+#ifndef WIN32
fd_list = g_unix_fd_list_new();
idx = g_unix_fd_list_append(fd_list, pair[1], NULL);
+#endif
console = QEMU_DBUS_DISPLAY1_CONSOLE_PROXY(
qemu_dbus_display1_console_proxy_new_sync(
@@ -171,12 +187,33 @@ test_dbus_display_console(void)
test.thread = g_thread_new(NULL, test_dbus_p2p_server_setup_thread,
GINT_TO_POINTER(pair[0]));
+#ifdef WIN32
+ if (WSADuplicateSocketW(_get_osfhandle(pair[1]),
+ GetProcessId((HANDLE) qtest_pid(qts)),
+ &info) == SOCKET_ERROR)
+ {
+ g_autofree char *emsg = g_win32_error_message(WSAGetLastError());
+ g_error("WSADuplicateSocket failed: %s", emsg);
+ }
+ close(pair[1]);
+ listener = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+ &info,
+ sizeof(info),
+ 1);
+#endif
+
qemu_dbus_display1_console_call_register_listener(
QEMU_DBUS_DISPLAY1_CONSOLE(console),
+#ifdef WIN32
+ listener,
+#else
g_variant_new_handle(idx),
+#endif
G_DBUS_CALL_FLAGS_NONE,
-1,
+#ifndef WIN32
fd_list,
+#endif
NULL,
test_dbus_console_registered,
&test);
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index de03ef5f60..79152f0ec3 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -142,6 +142,11 @@ static int socket_accept(int sock)
return ret;
}
+pid_t qtest_pid(QTestState *s)
+{
+ return s->qemu_pid;
+}
+
bool qtest_probe_child(QTestState *s)
{
pid_t pid = s->qemu_pid;
diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h
index a12acf7fa9..913acc3d5c 100644
--- a/tests/qtest/libqtest.h
+++ b/tests/qtest/libqtest.h
@@ -985,4 +985,13 @@ void qtest_qom_set_bool(QTestState *s, const char *path, const char *property,
* Returns: Value retrieved from property.
*/
bool qtest_qom_get_bool(QTestState *s, const char *path, const char *property);
+
+/**
+ * qtest_pid:
+ * @s: QTestState instance to operate on.
+ *
+ * Returns: the PID of the QEMU process, or <= 0
+ */
+pid_t qtest_pid(QTestState *s);
+
#endif
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 5fa6833ad7..74630f6672 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -104,7 +104,7 @@ qtests_i386 = \
'numa-test'
]
-if dbus_display and targetos != 'windows'
+if dbus_display
qtests_i386 += ['dbus-display-test']
endif
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
index f081c09729..d727a5fee8 100644
--- a/tests/unit/test-block-iothread.c
+++ b/tests/unit/test-block-iothread.c
@@ -825,6 +825,7 @@ static void test_attach_second_node(void)
BlockDriverState *bs, *filter;
QDict *options;
+ aio_context_acquire(main_ctx);
blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
blk_insert_bs(blk, bs, &error_abort);
@@ -833,7 +834,6 @@ static void test_attach_second_node(void)
qdict_put_str(options, "driver", "raw");
qdict_put_str(options, "file", "base");
- aio_context_acquire(main_ctx);
filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
aio_context_release(main_ctx);
@@ -857,9 +857,11 @@ static void test_attach_preserve_blk_ctx(void)
{
IOThread *iothread = iothread_new();
AioContext *ctx = iothread_get_aio_context(iothread);
+ AioContext *main_ctx = qemu_get_aio_context();
BlockBackend *blk;
BlockDriverState *bs;
+ aio_context_acquire(main_ctx);
blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
@@ -868,6 +870,7 @@ static void test_attach_preserve_blk_ctx(void)
blk_insert_bs(blk, bs, &error_abort);
g_assert(blk_get_aio_context(blk) == ctx);
g_assert(bdrv_get_aio_context(bs) == ctx);
+ aio_context_release(main_ctx);
/* Remove the node again */
aio_context_acquire(ctx);
@@ -877,7 +880,9 @@ static void test_attach_preserve_blk_ctx(void)
g_assert(bdrv_get_aio_context(bs) == qemu_get_aio_context());
/* Re-attach the node */
+ aio_context_acquire(main_ctx);
blk_insert_bs(blk, bs, &error_abort);
+ aio_context_release(main_ctx);
g_assert(blk_get_aio_context(blk) == ctx);
g_assert(bdrv_get_aio_context(bs) == ctx);