1
The following changes since commit e3acc2c1961cbe22ca474cd5da4163b7bbf7cea3:
1
The following changes since commit 2e3408b3cc7de4e87a9adafc8c19bfce3abec947:
2
2
3
tests/docker/dockerfiles: Bump fedora-i386-cross to fedora 34 (2021-10-05 16:40:39 -0700)
3
Merge tag 'misc-pull-request' of gitlab.com:marcandre.lureau/qemu into staging (2022-05-03 09:13:17 -0700)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 3765315d4c84f9c0799744f43a314169baaccc05:
9
for you to fetch changes up to c1fe694357a328c807ae3cc6961c19e923448fcc:
10
10
11
iotests: Update for pylint 2.11.1 (2021-10-06 10:25:55 +0200)
11
coroutine-win32: use QEMU_DEFINE_STATIC_CO_TLS() (2022-05-04 15:55:23 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches
15
15
16
- Fix I/O errors because of incorrectly detected max_iov
16
- Fix and re-enable GLOBAL_STATE_CODE assertions
17
- Fix not white-listed copy-before-write
17
- vhost-user: Fixes for VHOST_USER_ADD/REM_MEM_REG
18
- qemu-storage-daemon: Only display FUSE help when FUSE is built-in
18
- vmdk: Fix reopening bs->file
19
- iotests: update environment and linting configuration
19
- coroutine: use QEMU_DEFINE_STATIC_CO_TLS()
20
- docs/qemu-img: Fix list of formats which implement check
20
21
21
----------------------------------------------------------------
22
----------------------------------------------------------------
22
Emanuele Giuseppe Esposito (1):
23
Denis V. Lunev (1):
23
include/block.h: remove outdated comment
24
qemu-img: properly list formats which have consistency check implemented
24
25
25
John Snow (5):
26
Hanna Reitz (6):
26
iotests: add 'qemu' package location to PYTHONPATH in testenv
27
block: Classify bdrv_get_flags() as I/O function
27
iotests/linters: check mypy files all at once
28
qcow2: Do not reopen data_file in invalidate_cache
28
iotests/mirror-top-perms: Adjust imports
29
Revert "main-loop: Disable GLOBAL_STATE_CODE() assertions"
29
iotests/migrate-bitmaps-test: delint
30
iotests: Add regression test for issue 945
30
iotests: Update for pylint 2.11.1
31
block/vmdk: Fix reopening bs->file
32
iotests/reopen-file: Test reopening file child
31
33
32
Paolo Bonzini (1):
34
Kevin Wolf (3):
33
block: introduce max_hw_iov for use in scsi-generic
35
docs/vhost-user: Clarifications for VHOST_USER_ADD/REM_MEM_REG
36
libvhost-user: Fix extra vu_add/rem_mem_reg reply
37
vhost-user: Don't pass file descriptor for VHOST_USER_REM_MEM_REG
34
38
35
Philippe Mathieu-Daudé (1):
39
Stefan Hajnoczi (3):
36
qemu-storage-daemon: Only display FUSE help when FUSE is built-in
40
coroutine-ucontext: use QEMU_DEFINE_STATIC_CO_TLS()
41
coroutine: use QEMU_DEFINE_STATIC_CO_TLS()
42
coroutine-win32: use QEMU_DEFINE_STATIC_CO_TLS()
37
43
38
Vladimir Sementsov-Ogievskiy (5):
44
docs/interop/vhost-user.rst | 17 ++++
39
block: implement bdrv_new_open_driver_opts()
45
docs/tools/qemu-img.rst | 4 +-
40
block: bdrv_insert_node(): fix and improve error handling
46
include/block/block-global-state.h | 1 -
41
block: bdrv_insert_node(): doc and style
47
include/block/block-io.h | 1 +
42
block: bdrv_insert_node(): don't use bdrv_open()
48
include/qemu/main-loop.h | 3 +-
43
iotests/image-fleecing: declare requirement of copy-before-write
49
block.c | 2 +-
44
50
block/qcow2.c | 104 ++++++++++++---------
45
include/block/block.h | 8 ++-
51
block/vmdk.c | 56 ++++++++++-
46
include/block/block_int.h | 7 +++
52
hw/virtio/vhost-user.c | 2 +-
47
include/sysemu/block-backend.h | 1 +
53
subprojects/libvhost-user/libvhost-user.c | 17 ++--
48
block.c | 79 ++++++++++++++++++++++-----
54
util/coroutine-ucontext.c | 38 +++++---
49
block/block-backend.c | 6 ++
55
util/coroutine-win32.c | 18 +++-
50
block/file-posix.c | 2 +-
56
util/qemu-coroutine.c | 41 ++++----
51
block/io.c | 1 +
57
tests/qemu-iotests/tests/export-incoming-iothread | 81 ++++++++++++++++
52
hw/scsi/scsi-generic.c | 2 +-
58
.../tests/export-incoming-iothread.out | 5 +
53
storage-daemon/qemu-storage-daemon.c | 2 +
59
tests/qemu-iotests/tests/reopen-file | 89 ++++++++++++++++++
54
tests/qemu-iotests/iotests.py | 2 -
60
tests/qemu-iotests/tests/reopen-file.out | 5 +
55
tests/qemu-iotests/testenv.py | 15 +++--
61
17 files changed, 388 insertions(+), 96 deletions(-)
56
tests/qemu-iotests/testrunner.py | 7 ++-
62
create mode 100755 tests/qemu-iotests/tests/export-incoming-iothread
57
tests/qemu-iotests/235 | 2 -
63
create mode 100644 tests/qemu-iotests/tests/export-incoming-iothread.out
58
tests/qemu-iotests/297 | 52 +++++++-----------
64
create mode 100755 tests/qemu-iotests/tests/reopen-file
59
tests/qemu-iotests/300 | 5 +-
65
create mode 100644 tests/qemu-iotests/tests/reopen-file.out
60
tests/qemu-iotests/pylintrc | 6 +-
61
tests/qemu-iotests/tests/image-fleecing | 1 +
62
tests/qemu-iotests/tests/migrate-bitmaps-test | 50 +++++++++--------
63
tests/qemu-iotests/tests/mirror-top-perms | 12 ++--
64
19 files changed, 164 insertions(+), 96 deletions(-)
65
66
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: "Denis V. Lunev" <den@openvz.org>
2
2
3
We need to import subpackages from the qemu namespace package; importing
3
Simple grep for the .bdrv_co_check callback presence gives the following
4
the namespace package alone doesn't bring the subpackages with it --
4
list of block drivers
5
unless someone else (like iotests.py) imports them too.
5
* QED
6
* VDI
7
* VHDX
8
* VMDK
9
* Parallels
10
which have this callback. The presense of the callback means that
11
consistency check is supported.
6
12
7
Adjust the imports.
13
The patch updates documentation accordingly.
8
14
9
Signed-off-by: John Snow <jsnow@redhat.com>
15
Signed-off-by: Denis V. Lunev <den@openvz.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
CC: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
17
CC: Hanna Reitz <hreitz@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Message-Id: <20220407083932.531965-1-den@openvz.org>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
19
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Message-Id: <20210923180715.4168522-5-jsnow@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
21
---
17
tests/qemu-iotests/tests/mirror-top-perms | 7 ++++---
22
docs/tools/qemu-img.rst | 4 ++--
18
1 file changed, 4 insertions(+), 3 deletions(-)
23
1 file changed, 2 insertions(+), 2 deletions(-)
19
24
20
diff --git a/tests/qemu-iotests/tests/mirror-top-perms b/tests/qemu-iotests/tests/mirror-top-perms
25
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
21
index XXXXXXX..XXXXXXX 100755
26
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qemu-iotests/tests/mirror-top-perms
27
--- a/docs/tools/qemu-img.rst
23
+++ b/tests/qemu-iotests/tests/mirror-top-perms
28
+++ b/docs/tools/qemu-img.rst
24
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ Command description:
25
30
``-r all`` fixes all kinds of errors, with a higher risk of choosing the
26
import os
31
wrong fix or hiding corruption that has already occurred.
27
32
28
-import qemu
33
- Only the formats ``qcow2``, ``qed`` and ``vdi`` support
29
+from qemu import qmp
34
- consistency checks.
30
+from qemu.machine import machine
35
+ Only the formats ``qcow2``, ``qed``, ``parallels``, ``vhdx``, ``vmdk`` and
31
36
+ ``vdi`` support consistency checks.
32
import iotests
37
33
from iotests import qemu_img
38
In case the image does not have any inconsistencies, check exits with ``0``.
34
@@ -XXX,XX +XXX,XX @@ class TestMirrorTopPerms(iotests.QMPTestCase):
39
Other exit codes indicate the kind of inconsistency found or if another error
35
def tearDown(self):
36
try:
37
self.vm.shutdown()
38
- except qemu.machine.machine.AbnormalShutdown:
39
+ except machine.AbnormalShutdown:
40
pass
41
42
if self.vm_b is not None:
43
@@ -XXX,XX +XXX,XX @@ class TestMirrorTopPerms(iotests.QMPTestCase):
44
self.vm_b.launch()
45
print('ERROR: VM B launched successfully, this should not have '
46
'happened')
47
- except qemu.qmp.QMPConnectError:
48
+ except qmp.QMPConnectError:
49
assert 'Is another process using the image' in self.vm_b.get_log()
50
51
result = self.vm.qmp('block-job-cancel',
52
--
40
--
53
2.31.1
41
2.35.1
54
55
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
The specification for VHOST_USER_ADD/REM_MEM_REG messages is unclear
2
in several points, which has led to clients having incompatible
3
implementations. This changes the specification to be more explicit
4
about them:
2
5
3
There are a couple of errors in bdrv_drained_begin header comment:
6
* VHOST_USER_ADD_MEM_REG is not specified as receiving a file
4
- block_job_pause does not exist anymore, it has been replaced
7
descriptor, though it obviously does need to do so. All
5
with job_pause in b15de82867
8
implementations agree on this one, fix the specification.
6
- job_pause is automatically invoked as a .drained_begin callback
7
(child_job_drained_begin) by the child_job BdrvChildClass struct
8
in blockjob.c. So no additional pause should be required.
9
9
10
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
* VHOST_USER_REM_MEM_REG is not specified as receiving a file
11
Message-Id: <20210903113800.59970-1-eesposit@redhat.com>
11
descriptor either, and it also has no reason to do so. rust-vmm does
12
not send file descriptors for removing a memory region (in agreement
13
with the specification), libvhost-user and QEMU do (which is a bug),
14
though libvhost-user doesn't actually make any use of it.
15
16
Change the specification so that for compatibility QEMU's behaviour
17
becomes legal, even if discouraged, but rust-vmm's behaviour becomes
18
the explicitly recommended mode of operation.
19
20
* VHOST_USER_ADD_MEM_REG doesn't have a documented return value, which
21
is the desired behaviour in the non-postcopy case. It also implemented
22
like this in QEMU and rust-vmm, though libvhost-user is buggy and
23
sometimes sends an unexpected reply. This will be fixed in a separate
24
patch.
25
26
However, in postcopy mode it does reply like VHOST_USER_SET_MEM_TABLE.
27
This behaviour is shared between libvhost-user and QEMU; rust-vmm
28
doesn't implement postcopy mode yet. Mention it explicitly in the
29
spec.
30
31
* The specification doesn't mention how VHOST_USER_REM_MEM_REG
32
identifies the memory region to be removed. Change it to describe the
33
existing behaviour of libvhost-user (guest address, user address and
34
size must match).
35
36
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
37
Message-Id: <20220407133657.155281-2-kwolf@redhat.com>
38
Reviewed-by: Raphael Norwitz <raphael.norwitz@nutanix.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
39
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
40
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
41
---
15
include/block/block.h | 4 +---
42
docs/interop/vhost-user.rst | 17 +++++++++++++++++
16
1 file changed, 1 insertion(+), 3 deletions(-)
43
1 file changed, 17 insertions(+)
17
44
18
diff --git a/include/block/block.h b/include/block/block.h
45
diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
19
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/block.h
47
--- a/docs/interop/vhost-user.rst
21
+++ b/include/block/block.h
48
+++ b/docs/interop/vhost-user.rst
22
@@ -XXX,XX +XXX,XX @@ bool bdrv_drain_poll(BlockDriverState *bs, bool recursive,
49
@@ -XXX,XX +XXX,XX @@ replies. Here is a list of the ones that do:
23
* bdrv_drained_begin:
50
There are several messages that the master sends with file descriptors passed
24
*
51
in the ancillary data:
25
* Begin a quiesced section for exclusive access to the BDS, by disabling
52
26
- * external request sources including NBD server and device model. Note that
53
+* ``VHOST_USER_ADD_MEM_REG``
27
- * this doesn't block timers or coroutines from submitting more requests, which
54
* ``VHOST_USER_SET_MEM_TABLE``
28
- * means block_job_pause is still necessary.
55
* ``VHOST_USER_SET_LOG_BASE`` (if ``VHOST_USER_PROTOCOL_F_LOG_SHMFD``)
29
+ * external request sources including NBD server, block jobs, and device model.
56
* ``VHOST_USER_SET_LOG_FD``
30
*
57
@@ -XXX,XX +XXX,XX @@ Master message types
31
* This function can be recursive.
58
``VHOST_USER_REM_MEM_REG`` message, this message is used to set and
32
*/
59
update the memory tables of the slave device.
60
61
+ Exactly one file descriptor from which the memory is mapped is
62
+ passed in the ancillary data.
63
+
64
+ In postcopy mode (see ``VHOST_USER_POSTCOPY_LISTEN``), the slave
65
+ replies with the bases of the memory mapped region to the master.
66
+ For further details on postcopy, see ``VHOST_USER_SET_MEM_TABLE``.
67
+ They apply to ``VHOST_USER_ADD_MEM_REG`` accordingly.
68
+
69
``VHOST_USER_REM_MEM_REG``
70
:id: 38
71
:equivalent ioctl: N/A
72
@@ -XXX,XX +XXX,XX @@ Master message types
73
``VHOST_USER_ADD_MEM_REG`` message, this message is used to set and
74
update the memory tables of the slave device.
75
76
+ The memory region to be removed is identified by its guest address,
77
+ user address and size. The mmap offset is ignored.
78
+
79
+ No file descriptors SHOULD be passed in the ancillary data. For
80
+ compatibility with existing incorrect implementations, the slave MAY
81
+ accept messages with one file descriptor. If a file descriptor is
82
+ passed, the slave MUST close it without using it otherwise.
83
+
84
``VHOST_USER_SET_STATUS``
85
:id: 39
86
:equivalent ioctl: VHOST_VDPA_SET_STATUS
33
--
87
--
34
2.31.1
88
2.35.1
35
36
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Outside of postcopy mode, neither VHOST_USER_ADD_MEM_REG nor
2
VHOST_USER_REM_MEM_REG are supposed to send a reply unless explicitly
3
requested with the need_reply flag. Their current implementation always
4
sends a reply, even if it isn't requested. This confuses the master
5
because it will interpret the reply as a reply for the next message for
6
which it actually expects a reply.
2
7
3
Use bdrv_new_open_driver_opts() instead of complicated bdrv_open().
8
need_reply is already handled correctly by vu_dispatch(), so just don't
9
send a reply in the non-postcopy part of the message handler for these
10
two commands.
4
11
5
Among other extra things bdrv_open() also check for white-listed
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
formats, which we don't want for internal node creation: currently
13
Message-Id: <20220407133657.155281-3-kwolf@redhat.com>
7
backup doesn't work when copy-before-write filter is not white-listed.
14
Reviewed-by: Raphael Norwitz <raphael.norwitz@nutanix.com>
8
As well block-stream doesn't work when copy-on-read is not
15
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
white-listed.
10
11
Fixes: 751cec7a261adaf1145dc7adf6de7c9c084e5a0b
12
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2004812
13
Reported-by: Yanan Fu
14
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Message-Id: <20210920115538.264372-5-vsementsov@virtuozzo.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
17
---
18
block.c | 34 ++++++++++++++++++++++++++++------
18
subprojects/libvhost-user/libvhost-user.c | 9 +++------
19
1 file changed, 28 insertions(+), 6 deletions(-)
19
1 file changed, 3 insertions(+), 6 deletions(-)
20
20
21
diff --git a/block.c b/block.c
21
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
22
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block.c
23
--- a/subprojects/libvhost-user/libvhost-user.c
24
+++ b/block.c
24
+++ b/subprojects/libvhost-user/libvhost-user.c
25
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
25
@@ -XXX,XX +XXX,XX @@ vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
26
{
26
27
ERRP_GUARD();
27
DPRINT("Successfully added new region\n");
28
int ret;
28
dev->nregions++;
29
- BlockDriverState *new_node_bs;
29
- vmsg_set_reply_u64(vmsg, 0);
30
+ BlockDriverState *new_node_bs = NULL;
30
- return true;
31
+ const char *drvname, *node_name;
31
+ return false;
32
+ BlockDriver *drv;
33
+
34
+ drvname = qdict_get_try_str(options, "driver");
35
+ if (!drvname) {
36
+ error_setg(errp, "driver is not specified");
37
+ goto fail;
38
+ }
39
+
40
+ drv = bdrv_find_format(drvname);
41
+ if (!drv) {
42
+ error_setg(errp, "Unknown driver: '%s'", drvname);
43
+ goto fail;
44
+ }
45
46
- new_node_bs = bdrv_open(NULL, NULL, options, flags, errp);
47
- if (new_node_bs == NULL) {
48
+ node_name = qdict_get_try_str(options, "node-name");
49
+
50
+ new_node_bs = bdrv_new_open_driver_opts(drv, node_name, options, flags,
51
+ errp);
52
+ options = NULL; /* bdrv_new_open_driver() eats options */
53
+ if (!new_node_bs) {
54
error_prepend(errp, "Could not create node: ");
55
- return NULL;
56
+ goto fail;
57
}
32
}
58
33
}
59
bdrv_drained_begin(bs);
34
60
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
35
@@ -XXX,XX +XXX,XX @@ vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
61
36
}
62
if (ret < 0) {
63
error_prepend(errp, "Could not replace node: ");
64
- bdrv_unref(new_node_bs);
65
- return NULL;
66
+ goto fail;
67
}
37
}
68
38
69
return new_node_bs;
39
- if (found) {
70
+
40
- vmsg_set_reply_u64(vmsg, 0);
71
+fail:
41
- } else {
72
+ qobject_unref(options);
42
+ if (!found) {
73
+ bdrv_unref(new_node_bs);
43
vu_panic(dev, "Specified region not found\n");
74
+ return NULL;
44
}
45
46
close(vmsg->fds[0]);
47
48
- return true;
49
+ return false;
75
}
50
}
76
51
77
/*
52
static bool
78
--
53
--
79
2.31.1
54
2.35.1
80
81
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
The spec clarifies now that QEMU should not send a file descriptor in a
2
request to remove a memory region. Change it accordingly.
2
3
3
- use ERRP_GUARD(): function calls error_prepend(), so it must use
4
For libvhost-user, this is a bug fix that makes it compatible with
4
ERRP_GUARD(), otherwise error_prepend() would not be called when
5
rust-vmm's implementation that doesn't send a file descriptor. Keep
5
passed errp is error_fatal
6
accepting, but ignoring a file descriptor for compatibility with older
7
QEMU versions.
6
8
7
- drop error propagation, handle return code instead
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
10
Message-Id: <20220407133657.155281-4-kwolf@redhat.com>
9
- for symmetry, do error_prepend() for the second failure
11
Reviewed-by: Raphael Norwitz <raphael.norwitz@nutanix.com>
10
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Message-Id: <20210920115538.264372-3-vsementsov@virtuozzo.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
14
---
15
block.c | 9 +++++----
15
hw/virtio/vhost-user.c | 2 +-
16
1 file changed, 5 insertions(+), 4 deletions(-)
16
subprojects/libvhost-user/libvhost-user.c | 8 ++++----
17
2 files changed, 5 insertions(+), 5 deletions(-)
17
18
18
diff --git a/block.c b/block.c
19
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
21
--- a/hw/virtio/vhost-user.c
21
+++ b/block.c
22
+++ b/hw/virtio/vhost-user.c
22
@@ -XXX,XX +XXX,XX @@ static void bdrv_delete(BlockDriverState *bs)
23
@@ -XXX,XX +XXX,XX @@ static int send_remove_regions(struct vhost_dev *dev,
23
BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
24
vhost_user_fill_msg_region(&region_buffer, shadow_reg, 0);
24
int flags, Error **errp)
25
msg->payload.mem_reg.region = region_buffer;
25
{
26
26
+ ERRP_GUARD();
27
- ret = vhost_user_write(dev, msg, &fd, 1);
27
+ int ret;
28
+ ret = vhost_user_write(dev, msg, NULL, 0);
28
BlockDriverState *new_node_bs;
29
if (ret < 0) {
29
- Error *local_err = NULL;
30
return ret;
30
31
}
31
new_node_bs = bdrv_open(NULL, NULL, node_options, flags, errp);
32
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
32
if (new_node_bs == NULL) {
33
index XXXXXXX..XXXXXXX 100644
33
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
34
--- a/subprojects/libvhost-user/libvhost-user.c
35
+++ b/subprojects/libvhost-user/libvhost-user.c
36
@@ -XXX,XX +XXX,XX @@ vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
37
int i;
38
bool found = false;
39
40
- if (vmsg->fd_num != 1) {
41
+ if (vmsg->fd_num > 1) {
42
vmsg_close_fds(vmsg);
43
- vu_panic(dev, "VHOST_USER_REM_MEM_REG received %d fds - only 1 fd "
44
+ vu_panic(dev, "VHOST_USER_REM_MEM_REG received %d fds - at most 1 fd "
45
"should be sent for this message type", vmsg->fd_num);
46
return false;
34
}
47
}
35
48
36
bdrv_drained_begin(bs);
49
if (vmsg->size < VHOST_USER_MEM_REG_SIZE) {
37
- bdrv_replace_node(bs, new_node_bs, &local_err);
50
- close(vmsg->fds[0]);
38
+ ret = bdrv_replace_node(bs, new_node_bs, errp);
51
+ vmsg_close_fds(vmsg);
39
bdrv_drained_end(bs);
52
vu_panic(dev, "VHOST_USER_REM_MEM_REG requires a message size of at "
40
53
"least %d bytes and only %d bytes were received",
41
- if (local_err) {
54
VHOST_USER_MEM_REG_SIZE, vmsg->size);
42
+ if (ret < 0) {
55
@@ -XXX,XX +XXX,XX @@ vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
43
+ error_prepend(errp, "Could not replace node: ");
56
vu_panic(dev, "Specified region not found\n");
44
bdrv_unref(new_node_bs);
45
- error_propagate(errp, local_err);
46
return NULL;
47
}
57
}
48
58
59
- close(vmsg->fds[0]);
60
+ vmsg_close_fds(vmsg);
61
62
return false;
63
}
49
--
64
--
50
2.31.1
65
2.35.1
51
52
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
- options & flags is common pair for open-like functions, let's use it
3
This function is safe to call in an I/O context, and qcow2_do_open()
4
- add a comment that specifies use of @options
4
does so (invoked in an I/O context by qcow2_co_invalidate_cache()).
5
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
Message-Id: <20210920115538.264372-4-vsementsov@virtuozzo.com>
7
Message-Id: <20220427114057.36651-2-hreitz@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
---
10
block.c | 13 +++++++++++--
11
include/block/block-global-state.h | 1 -
11
1 file changed, 11 insertions(+), 2 deletions(-)
12
include/block/block-io.h | 1 +
13
block.c | 2 +-
14
3 files changed, 2 insertions(+), 2 deletions(-)
12
15
16
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-global-state.h
19
+++ b/include/block/block-global-state.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_next_cleanup(BdrvNextIterator *it);
21
BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs);
22
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
23
void *opaque, bool read_only);
24
-int bdrv_get_flags(BlockDriverState *bs);
25
char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
26
char *bdrv_dirname(BlockDriverState *bs, Error **errp);
27
28
diff --git a/include/block/block-io.h b/include/block/block-io.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/block/block-io.h
31
+++ b/include/block/block-io.h
32
@@ -XXX,XX +XXX,XX @@ int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
33
bool bdrv_is_read_only(BlockDriverState *bs);
34
bool bdrv_is_writable(BlockDriverState *bs);
35
bool bdrv_is_sg(BlockDriverState *bs);
36
+int bdrv_get_flags(BlockDriverState *bs);
37
bool bdrv_is_inserted(BlockDriverState *bs);
38
void bdrv_lock_medium(BlockDriverState *bs, bool locked);
39
void bdrv_eject(BlockDriverState *bs, bool eject_flag);
13
diff --git a/block.c b/block.c
40
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
42
--- a/block.c
16
+++ b/block.c
43
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ static void bdrv_delete(BlockDriverState *bs)
44
@@ -XXX,XX +XXX,XX @@ const char *bdrv_get_device_or_node_name(const BlockDriverState *bs)
18
g_free(bs);
45
46
int bdrv_get_flags(BlockDriverState *bs)
47
{
48
- GLOBAL_STATE_CODE();
49
+ IO_CODE();
50
return bs->open_flags;
19
}
51
}
20
52
21
-BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
22
+
23
+/*
24
+ * Replace @bs by newly created block node.
25
+ *
26
+ * @options is a QDict of options to pass to the block drivers, or NULL for an
27
+ * empty set of options. The reference to the QDict belongs to the block layer
28
+ * after the call (even on failure), so if the caller intends to reuse the
29
+ * dictionary, it needs to use qobject_ref() before calling bdrv_open.
30
+ */
31
+BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
32
int flags, Error **errp)
33
{
34
ERRP_GUARD();
35
int ret;
36
BlockDriverState *new_node_bs;
37
38
- new_node_bs = bdrv_open(NULL, NULL, node_options, flags, errp);
39
+ new_node_bs = bdrv_open(NULL, NULL, options, flags, errp);
40
if (new_node_bs == NULL) {
41
error_prepend(errp, "Could not create node: ");
42
return NULL;
43
--
53
--
44
2.31.1
54
2.35.1
45
46
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
Linux limits the size of iovecs to 1024 (UIO_MAXIOV in the kernel
3
qcow2_co_invalidate_cache() closes and opens the qcow2 file, by calling
4
sources, IOV_MAX in POSIX). Because of this, on some host adapters
4
qcow2_close() and qcow2_do_open(). These two functions must thus be
5
requests with many iovecs are rejected with -EINVAL by the
5
usable from both a global-state and an I/O context.
6
io_submit() or readv()/writev() system calls.
6
7
7
As they are, they are not safe to call in an I/O context, because they
8
In fact, the same limit applies to SG_IO as well. To fix both the
8
use bdrv_unref_child() and bdrv_open_child() to close/open the data_file
9
EINVAL and the possible performance issues from using fewer iovecs
9
child, respectively, both of which are global-state functions. When
10
than allowed by Linux (some HBAs have max_segments as low as 128),
10
used from qcow2_co_invalidate_cache(), we do not need to close/open the
11
introduce a separate entry in BlockLimits to hold the max_segments
11
data_file child, though (we do not do this for bs->file or bs->backing
12
value from sysfs. This new limit is used only for SG_IO and clamped
12
either), and so we should skip it in the qcow2_co_invalidate_cache()
13
to bs->bl.max_iov anyway, just like max_hw_transfer is clamped to
13
path.
14
bs->bl.max_transfer.
14
15
15
To do so, add a parameter to qcow2_do_open() and qcow2_close() to make
16
Reported-by: Halil Pasic <pasic@linux.ibm.com>
16
them skip handling s->data_file, and have qcow2_co_invalidate_cache()
17
Cc: Hanna Reitz <hreitz@redhat.com>
17
exempt it from the memset() on the BDRVQcow2State.
18
Cc: Kevin Wolf <kwolf@redhat.com>
18
19
Cc: qemu-block@nongnu.org
19
(Note that the QED driver similarly closes/opens the QED image by
20
Cc: qemu-stable@nongnu.org
20
invoking bdrv_qed_close()+bdrv_qed_do_open(), but both functions seem
21
Fixes: 18473467d5 ("file-posix: try BLKSECTGET on block devices too, do not round to power of 2", 2021-06-25)
21
safe to use in an I/O context.)
22
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
22
23
Message-Id: <20210923130436.1187591-1-pbonzini@redhat.com>
23
Fixes: https://gitlab.com/qemu-project/qemu/-/issues/945
24
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
25
Message-Id: <20220427114057.36651-3-hreitz@redhat.com>
26
Reviewed-by: Eric Blake <eblake@redhat.com>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
---
28
---
26
include/block/block_int.h | 7 +++++++
29
block/qcow2.c | 104 ++++++++++++++++++++++++++++++--------------------
27
include/sysemu/block-backend.h | 1 +
30
1 file changed, 62 insertions(+), 42 deletions(-)
28
block/block-backend.c | 6 ++++++
31
29
block/file-posix.c | 2 +-
32
diff --git a/block/qcow2.c b/block/qcow2.c
30
block/io.c | 1 +
31
hw/scsi/scsi-generic.c | 2 +-
32
6 files changed, 17 insertions(+), 2 deletions(-)
33
34
diff --git a/include/block/block_int.h b/include/block/block_int.h
35
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
36
--- a/include/block/block_int.h
34
--- a/block/qcow2.c
37
+++ b/include/block/block_int.h
35
+++ b/block/qcow2.c
38
@@ -XXX,XX +XXX,XX @@ typedef struct BlockLimits {
36
@@ -XXX,XX +XXX,XX @@ static int validate_compression_type(BDRVQcow2State *s, Error **errp)
39
*/
37
40
uint64_t max_hw_transfer;
38
/* Called with s->lock held. */
41
39
static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
42
+ /* Maximal number of scatter/gather elements allowed by the hardware.
40
- int flags, Error **errp)
43
+ * Applies whenever transfers to the device bypass the kernel I/O
41
+ int flags, bool open_data_file,
44
+ * scheduler, for example with SG_IO. If larger than max_iov
42
+ Error **errp)
45
+ * or if zero, blk_get_max_hw_iov will fall back to max_iov.
43
{
46
+ */
44
ERRP_GUARD();
47
+ int max_hw_iov;
45
BDRVQcow2State *s = bs->opaque;
48
+
46
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
49
/* memory alignment, in bytes so that no bounce buffer is needed */
47
goto fail;
50
size_t min_mem_alignment;
48
}
51
49
52
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
50
- /* Open external data file */
53
index XXXXXXX..XXXXXXX 100644
51
- s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
54
--- a/include/sysemu/block-backend.h
52
- &child_of_bds, BDRV_CHILD_DATA,
55
+++ b/include/sysemu/block-backend.h
53
- true, errp);
56
@@ -XXX,XX +XXX,XX @@ uint32_t blk_get_request_alignment(BlockBackend *blk);
54
- if (*errp) {
57
uint32_t blk_get_max_transfer(BlockBackend *blk);
55
- ret = -EINVAL;
58
uint64_t blk_get_max_hw_transfer(BlockBackend *blk);
56
- goto fail;
59
int blk_get_max_iov(BlockBackend *blk);
57
- }
60
+int blk_get_max_hw_iov(BlockBackend *blk);
58
+ if (open_data_file) {
61
void blk_set_guest_block_size(BlockBackend *blk, int align);
59
+ /* Open external data file */
62
void *blk_try_blockalign(BlockBackend *blk, size_t size);
60
+ s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
63
void *blk_blockalign(BlockBackend *blk, size_t size);
61
+ &child_of_bds, BDRV_CHILD_DATA,
64
diff --git a/block/block-backend.c b/block/block-backend.c
62
+ true, errp);
65
index XXXXXXX..XXXXXXX 100644
63
+ if (*errp) {
66
--- a/block/block-backend.c
64
+ ret = -EINVAL;
67
+++ b/block/block-backend.c
65
+ goto fail;
68
@@ -XXX,XX +XXX,XX @@ uint32_t blk_get_max_transfer(BlockBackend *blk)
66
+ }
69
return ROUND_DOWN(max, blk_get_request_alignment(blk));
67
68
- if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
69
- if (!s->data_file && s->image_data_file) {
70
- s->data_file = bdrv_open_child(s->image_data_file, options,
71
- "data-file", bs, &child_of_bds,
72
- BDRV_CHILD_DATA, false, errp);
73
+ if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
74
+ if (!s->data_file && s->image_data_file) {
75
+ s->data_file = bdrv_open_child(s->image_data_file, options,
76
+ "data-file", bs, &child_of_bds,
77
+ BDRV_CHILD_DATA, false, errp);
78
+ if (!s->data_file) {
79
+ ret = -EINVAL;
80
+ goto fail;
81
+ }
82
+ }
83
if (!s->data_file) {
84
+ error_setg(errp, "'data-file' is required for this image");
85
ret = -EINVAL;
86
goto fail;
87
}
88
- }
89
- if (!s->data_file) {
90
- error_setg(errp, "'data-file' is required for this image");
91
- ret = -EINVAL;
92
- goto fail;
93
- }
94
95
- /* No data here */
96
- bs->file->role &= ~BDRV_CHILD_DATA;
97
+ /* No data here */
98
+ bs->file->role &= ~BDRV_CHILD_DATA;
99
100
- /* Must succeed because we have given up permissions if anything */
101
- bdrv_child_refresh_perms(bs, bs->file, &error_abort);
102
- } else {
103
- if (s->data_file) {
104
- error_setg(errp, "'data-file' can only be set for images with an "
105
- "external data file");
106
- ret = -EINVAL;
107
- goto fail;
108
- }
109
+ /* Must succeed because we have given up permissions if anything */
110
+ bdrv_child_refresh_perms(bs, bs->file, &error_abort);
111
+ } else {
112
+ if (s->data_file) {
113
+ error_setg(errp, "'data-file' can only be set for images with "
114
+ "an external data file");
115
+ ret = -EINVAL;
116
+ goto fail;
117
+ }
118
119
- s->data_file = bs->file;
120
+ s->data_file = bs->file;
121
122
- if (data_file_is_raw(bs)) {
123
- error_setg(errp, "data-file-raw requires a data file");
124
- ret = -EINVAL;
125
- goto fail;
126
+ if (data_file_is_raw(bs)) {
127
+ error_setg(errp, "data-file-raw requires a data file");
128
+ ret = -EINVAL;
129
+ goto fail;
130
+ }
131
}
132
}
133
134
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
135
136
fail:
137
g_free(s->image_data_file);
138
- if (has_data_file(bs)) {
139
+ if (open_data_file && has_data_file(bs)) {
140
bdrv_unref_child(bs, s->data_file);
141
s->data_file = NULL;
142
}
143
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qcow2_open_entry(void *opaque)
144
BDRVQcow2State *s = qoc->bs->opaque;
145
146
qemu_co_mutex_lock(&s->lock);
147
- qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, qoc->errp);
148
+ qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, true,
149
+ qoc->errp);
150
qemu_co_mutex_unlock(&s->lock);
70
}
151
}
71
152
72
+int blk_get_max_hw_iov(BlockBackend *blk)
153
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
154
return result;
155
}
156
157
-static void qcow2_close(BlockDriverState *bs)
158
+static void qcow2_do_close(BlockDriverState *bs, bool close_data_file)
159
{
160
BDRVQcow2State *s = bs->opaque;
161
qemu_vfree(s->l1_table);
162
@@ -XXX,XX +XXX,XX @@ static void qcow2_close(BlockDriverState *bs)
163
g_free(s->image_backing_file);
164
g_free(s->image_backing_format);
165
166
- if (has_data_file(bs)) {
167
+ if (close_data_file && has_data_file(bs)) {
168
bdrv_unref_child(bs, s->data_file);
169
s->data_file = NULL;
170
}
171
@@ -XXX,XX +XXX,XX @@ static void qcow2_close(BlockDriverState *bs)
172
qcow2_free_snapshots(bs);
173
}
174
175
+static void qcow2_close(BlockDriverState *bs)
73
+{
176
+{
74
+ return MIN_NON_ZERO(blk->root->bs->bl.max_hw_iov,
177
+ qcow2_do_close(bs, true);
75
+ blk->root->bs->bl.max_iov);
76
+}
178
+}
77
+
179
+
78
int blk_get_max_iov(BlockBackend *blk)
180
static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
181
Error **errp)
79
{
182
{
80
return blk->root->bs->bl.max_iov;
183
ERRP_GUARD();
81
diff --git a/block/file-posix.c b/block/file-posix.c
184
BDRVQcow2State *s = bs->opaque;
82
index XXXXXXX..XXXXXXX 100644
185
+ BdrvChild *data_file;
83
--- a/block/file-posix.c
186
int flags = s->flags;
84
+++ b/block/file-posix.c
187
QCryptoBlock *crypto = NULL;
85
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
188
QDict *options;
86
189
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
87
ret = hdev_get_max_segments(s->fd, &st);
190
crypto = s->crypto;
88
if (ret > 0) {
191
s->crypto = NULL;
89
- bs->bl.max_iov = ret;
192
90
+ bs->bl.max_hw_iov = ret;
193
- qcow2_close(bs);
91
}
194
+ /*
92
}
195
+ * Do not reopen s->data_file (i.e., have qcow2_do_close() not close it,
93
}
196
+ * and then prevent qcow2_do_open() from opening it), because this function
94
diff --git a/block/io.c b/block/io.c
197
+ * runs in the I/O path and as such we must not invoke global-state
95
index XXXXXXX..XXXXXXX 100644
198
+ * functions like bdrv_unref_child() and bdrv_open_child().
96
--- a/block/io.c
199
+ */
97
+++ b/block/io.c
200
98
@@ -XXX,XX +XXX,XX @@ static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
201
+ qcow2_do_close(bs, false);
99
dst->min_mem_alignment = MAX(dst->min_mem_alignment,
202
+
100
src->min_mem_alignment);
203
+ data_file = s->data_file;
101
dst->max_iov = MIN_NON_ZERO(dst->max_iov, src->max_iov);
204
memset(s, 0, sizeof(BDRVQcow2State));
102
+ dst->max_hw_iov = MIN_NON_ZERO(dst->max_hw_iov, src->max_hw_iov);
205
+ s->data_file = data_file;
103
}
206
+
104
207
options = qdict_clone_shallow(bs->options);
105
typedef struct BdrvRefreshLimitsState {
208
106
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
209
flags &= ~BDRV_O_INACTIVE;
107
index XXXXXXX..XXXXXXX 100644
210
qemu_co_mutex_lock(&s->lock);
108
--- a/hw/scsi/scsi-generic.c
211
- ret = qcow2_do_open(bs, options, flags, errp);
109
+++ b/hw/scsi/scsi-generic.c
212
+ ret = qcow2_do_open(bs, options, flags, false, errp);
110
@@ -XXX,XX +XXX,XX @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len)
213
qemu_co_mutex_unlock(&s->lock);
111
page = r->req.cmd.buf[2];
214
qobject_unref(options);
112
if (page == 0xb0) {
215
if (ret < 0) {
113
uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk);
114
- uint32_t max_iov = blk_get_max_iov(s->conf.blk);
115
+ uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk);
116
117
assert(max_transfer);
118
max_transfer = MIN_NON_ZERO(max_transfer, max_iov * qemu_real_host_page_size)
119
--
216
--
120
2.31.1
217
2.35.1
121
122
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
1. Ignore the new f-strings warning, we're not interested in doing a
3
This reverts commit b1c073490553f80594b903ceedfc7c1aef6b1b19. (We
4
full conversion at this time.
4
wanted to do so once the 7.1 tree opens, which has happened. The issue
5
reported in https://gitlab.com/qemu-project/qemu/-/issues/945 should be
6
fixed by the preceding patches.)
5
7
6
2. Just mute the unbalanced-tuple-unpacking warning, it's not a real
8
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
error in this case and muting the dozens of callsites is just not
9
Message-Id: <20220427114057.36651-4-hreitz@redhat.com>
8
worth it.
10
Reviewed-by: Eric Blake <eblake@redhat.com>
9
10
3. Add encodings to read_text().
11
12
Signed-off-by: John Snow <jsnow@redhat.com>
13
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Message-Id: <20210923180715.4168522-7-jsnow@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
12
---
18
tests/qemu-iotests/testrunner.py | 7 ++++---
13
include/qemu/main-loop.h | 3 +--
19
tests/qemu-iotests/pylintrc | 6 +++++-
14
1 file changed, 1 insertion(+), 2 deletions(-)
20
2 files changed, 9 insertions(+), 4 deletions(-)
21
15
22
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
16
diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/tests/qemu-iotests/testrunner.py
18
--- a/include/qemu/main-loop.h
25
+++ b/tests/qemu-iotests/testrunner.py
19
+++ b/include/qemu/main-loop.h
26
@@ -XXX,XX +XXX,XX @@ def do_run_test(self, test: str) -> TestResult:
20
@@ -XXX,XX +XXX,XX @@ bool qemu_in_main_thread(void);
27
diff=file_diff(str(f_reference), str(f_bad)))
21
#else
28
22
#define GLOBAL_STATE_CODE() \
29
if f_notrun.exists():
23
do { \
30
- return TestResult(status='not run',
24
- /* FIXME: Re-enable after 7.0 release */ \
31
- description=f_notrun.read_text().strip())
25
- /* assert(qemu_in_main_thread()); */ \
32
+ return TestResult(
26
+ assert(qemu_in_main_thread()); \
33
+ status='not run',
27
} while (0)
34
+ description=f_notrun.read_text(encoding='utf-8').strip())
28
#endif /* CONFIG_COCOA */
35
36
casenotrun = ''
37
if f_casenotrun.exists():
38
- casenotrun = f_casenotrun.read_text()
39
+ casenotrun = f_casenotrun.read_text(encoding='utf-8')
40
41
diff = file_diff(str(f_reference), str(f_bad))
42
if diff:
43
diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc
44
index XXXXXXX..XXXXXXX 100644
45
--- a/tests/qemu-iotests/pylintrc
46
+++ b/tests/qemu-iotests/pylintrc
47
@@ -XXX,XX +XXX,XX @@ disable=invalid-name,
48
too-many-public-methods,
49
# pylint warns about Optional[] etc. as unsubscriptable in 3.9
50
unsubscriptable-object,
51
+ # pylint's static analysis causes false positivies for file_path();
52
+ # If we really care to make it statically knowable, we'll use mypy.
53
+ unbalanced-tuple-unpacking,
54
# Sometimes we need to disable a newly introduced pylint warning.
55
# Doing so should not produce a warning in older versions of pylint.
56
bad-option-value,
57
# These are temporary, and should be removed:
58
missing-docstring,
59
too-many-return-statements,
60
- too-many-statements
61
+ too-many-statements,
62
+ consider-using-f-string,
63
64
[FORMAT]
65
29
66
--
30
--
67
2.31.1
31
2.35.1
68
69
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
We can circumvent the '__main__' redefinition problem by passing
3
Create a VM with a BDS in an iothread, add -incoming defer to the
4
--scripts-are-modules. Take mypy out of the loop per-filename and check
4
command line, and then export this BDS via NBD. Doing so should not
5
everything in one go: it's quite a bit faster.
5
fail an assertion.
6
6
7
Signed-off-by: John Snow <jsnow@redhat.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-Id: <20220427114057.36651-5-hreitz@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Tested-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Message-Id: <20210923180715.4168522-4-jsnow@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
12
---
15
tests/qemu-iotests/297 | 46 +++++++++++++++++++-----------------------
13
.../tests/export-incoming-iothread | 81 +++++++++++++++++++
16
1 file changed, 21 insertions(+), 25 deletions(-)
14
.../tests/export-incoming-iothread.out | 5 ++
15
2 files changed, 86 insertions(+)
16
create mode 100755 tests/qemu-iotests/tests/export-incoming-iothread
17
create mode 100644 tests/qemu-iotests/tests/export-incoming-iothread.out
17
18
18
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
19
diff --git a/tests/qemu-iotests/tests/export-incoming-iothread b/tests/qemu-iotests/tests/export-incoming-iothread
19
index XXXXXXX..XXXXXXX 100755
20
new file mode 100755
20
--- a/tests/qemu-iotests/297
21
index XXXXXXX..XXXXXXX
21
+++ b/tests/qemu-iotests/297
22
--- /dev/null
22
@@ -XXX,XX +XXX,XX @@ def run_linters():
23
+++ b/tests/qemu-iotests/tests/export-incoming-iothread
23
print('=== mypy ===')
24
@@ -XXX,XX +XXX,XX @@
24
sys.stdout.flush()
25
+#!/usr/bin/env python3
25
26
+# group: rw quick migration
26
- # We have to call mypy separately for each file. Otherwise, it
27
+#
27
- # will interpret all given files as belonging together (i.e., they
28
+# Regression test for issue 945:
28
- # may not both define the same classes, etc.; most notably, they
29
+# https://gitlab.com/qemu-project/qemu/-/issues/945
29
- # must not both define the __main__ module).
30
+# Test adding an export on top of an iothread-ed block device while in
30
env['MYPYPATH'] = env['PYTHONPATH']
31
+# -incoming defer.
31
- for filename in files:
32
+#
32
- p = subprocess.run(('mypy',
33
+# Copyright (C) 2022 Red Hat, Inc.
33
- '--warn-unused-configs',
34
+#
34
- '--disallow-subclassing-any',
35
+# This program is free software; you can redistribute it and/or modify
35
- '--disallow-any-generics',
36
+# it under the terms of the GNU General Public License as published by
36
- '--disallow-incomplete-defs',
37
+# the Free Software Foundation; either version 2 of the License, or
37
- '--disallow-untyped-decorators',
38
+# (at your option) any later version.
38
- '--no-implicit-optional',
39
+#
39
- '--warn-redundant-casts',
40
+# This program is distributed in the hope that it will be useful,
40
- '--warn-unused-ignores',
41
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
41
- '--no-implicit-reexport',
42
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42
- '--namespace-packages',
43
+# GNU General Public License for more details.
43
- filename),
44
+#
44
- env=env,
45
+# You should have received a copy of the GNU General Public License
45
- check=False,
46
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
46
- stdout=subprocess.PIPE,
47
+#
47
- stderr=subprocess.STDOUT,
48
- universal_newlines=True)
49
-
50
- if p.returncode != 0:
51
- print(p.stdout)
52
+ p = subprocess.run(('mypy',
53
+ '--warn-unused-configs',
54
+ '--disallow-subclassing-any',
55
+ '--disallow-any-generics',
56
+ '--disallow-incomplete-defs',
57
+ '--disallow-untyped-decorators',
58
+ '--no-implicit-optional',
59
+ '--warn-redundant-casts',
60
+ '--warn-unused-ignores',
61
+ '--no-implicit-reexport',
62
+ '--namespace-packages',
63
+ '--scripts-are-modules',
64
+ *files),
65
+ env=env,
66
+ check=False,
67
+ stdout=subprocess.PIPE,
68
+ stderr=subprocess.STDOUT,
69
+ universal_newlines=True)
70
+
48
+
71
+ if p.returncode != 0:
49
+import os
72
+ print(p.stdout)
50
+import iotests
73
51
+from iotests import qemu_img_create
74
52
+
75
for linter in ('pylint-3', 'mypy'):
53
+
54
+image_size = 1 * 1024 * 1024
55
+test_img = os.path.join(iotests.test_dir, 'test.img')
56
+node_name = 'node0'
57
+iothread_id = 'iothr0'
58
+
59
+nbd_sock = os.path.join(iotests.sock_dir, 'nbd.sock')
60
+
61
+
62
+class TestExportIncomingIothread(iotests.QMPTestCase):
63
+ def setUp(self) -> None:
64
+ qemu_img_create('-f', iotests.imgfmt, test_img, str(image_size))
65
+
66
+ self.vm = iotests.VM()
67
+ self.vm.add_object(f'iothread,id={iothread_id}')
68
+ self.vm.add_blockdev((
69
+ f'driver={iotests.imgfmt}',
70
+ f'node-name={node_name}',
71
+ 'file.driver=file',
72
+ f'file.filename={test_img}'
73
+ ))
74
+ self.vm.add_incoming('defer')
75
+ self.vm.launch()
76
+
77
+ def tearDown(self):
78
+ self.vm.shutdown()
79
+ os.remove(test_img)
80
+
81
+ def test_export_add(self):
82
+ result = self.vm.qmp('nbd-server-start', {
83
+ 'addr': {
84
+ 'type': 'unix',
85
+ 'data': {
86
+ 'path': nbd_sock
87
+ }
88
+ }
89
+ })
90
+ self.assert_qmp(result, 'return', {})
91
+
92
+ # Regression test for issue 945: This should not fail an assertion
93
+ result = self.vm.qmp('block-export-add', {
94
+ 'type': 'nbd',
95
+ 'id': 'exp0',
96
+ 'node-name': node_name,
97
+ 'iothread': iothread_id
98
+ })
99
+ self.assert_qmp(result, 'return', {})
100
+
101
+
102
+if __name__ == '__main__':
103
+ iotests.main(supported_fmts=['generic'],
104
+ unsupported_fmts=['luks'], # Would need a secret
105
+ supported_protocols=['file'])
106
diff --git a/tests/qemu-iotests/tests/export-incoming-iothread.out b/tests/qemu-iotests/tests/export-incoming-iothread.out
107
new file mode 100644
108
index XXXXXXX..XXXXXXX
109
--- /dev/null
110
+++ b/tests/qemu-iotests/tests/export-incoming-iothread.out
111
@@ -XXX,XX +XXX,XX @@
112
+.
113
+----------------------------------------------------------------------
114
+Ran 1 tests
115
+
116
+OK
76
--
117
--
77
2.31.1
118
2.35.1
78
79
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
Add version of bdrv_new_open_driver() that supports QDict options.
3
VMDK disk data is stored in extents, which may or may not be separate
4
We'll use it in further commit.
4
from bs->file. VmdkExtent.file points to where they are stored. Each
5
that is stored in bs->file will simply reuse the exact pointer value of
6
bs->file.
5
7
6
Simply add one more argument to bdrv_new_open_driver() is worse, as
8
(That is why vmdk_free_extents() will unref VmdkExtent.file (e->file)
7
there are too many invocations of bdrv_new_open_driver() to update
9
only if e->file != bs->file.)
8
then.
9
10
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reopen operations can change bs->file (they will replace the whole
11
Suggested-by: Kevin Wolf <kwolf@redhat.com>
12
BdrvChild object, not just the BDS stored in that BdrvChild), and then
12
Message-Id: <20210920115538.264372-2-vsementsov@virtuozzo.com>
13
we will need to change all .file pointers of all such VmdkExtents to
14
point to the new BdrvChild.
15
16
In vmdk_reopen_prepare(), we have to check which VmdkExtents are
17
affected, and in vmdk_reopen_commit(), we can modify them. We have to
18
split this because:
19
- The new BdrvChild is created only after prepare, so we can change
20
VmdkExtent.file only in commit
21
- In commit, there no longer is any (valid) reference to the old
22
BdrvChild object, so there would be nothing to compare VmdkExtent.file
23
against to see whether it was equal to bs->file before reopening
24
(There is BDRVReopenState.old_file_bs, but the old bs->file
25
BdrvChild's .bs pointer will be NULL-ed when the new BdrvChild is
26
created, and so we cannot compare VmdkExtent.file->bs against
27
BDRVReopenState.old_file_bs)
28
29
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
30
Message-Id: <20220314162719.65384-2-hreitz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
32
---
15
include/block/block.h | 4 ++++
33
block/vmdk.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++-
16
block.c | 25 +++++++++++++++++++++----
34
1 file changed, 55 insertions(+), 1 deletion(-)
17
2 files changed, 25 insertions(+), 4 deletions(-)
18
35
19
diff --git a/include/block/block.h b/include/block/block.h
36
diff --git a/block/vmdk.c b/block/vmdk.c
20
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/block.h
38
--- a/block/vmdk.c
22
+++ b/include/block/block.h
39
+++ b/block/vmdk.c
23
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
40
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVVmdkState {
24
const char *bdref_key, Error **errp);
41
char *create_type;
25
BlockDriverState *bdrv_open(const char *filename, const char *reference,
42
} BDRVVmdkState;
26
QDict *options, int flags, Error **errp);
43
27
+BlockDriverState *bdrv_new_open_driver_opts(BlockDriver *drv,
44
+typedef struct BDRVVmdkReopenState {
28
+ const char *node_name,
45
+ bool *extents_using_bs_file;
29
+ QDict *options, int flags,
46
+} BDRVVmdkReopenState;
30
+ Error **errp);
47
+
31
BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
48
typedef struct VmdkMetaData {
32
int flags, Error **errp);
49
unsigned int l1_index;
33
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
50
unsigned int l2_index;
34
diff --git a/block.c b/block.c
51
@@ -XXX,XX +XXX,XX @@ static int vmdk_is_cid_valid(BlockDriverState *bs)
35
index XXXXXXX..XXXXXXX 100644
52
return 1;
36
--- a/block.c
37
+++ b/block.c
38
@@ -XXX,XX +XXX,XX @@ open_failed:
39
return ret;
40
}
53
}
41
54
42
-BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
55
-/* We have nothing to do for VMDK reopen, stubs just return success */
43
- int flags, Error **errp)
56
static int vmdk_reopen_prepare(BDRVReopenState *state,
44
+/*
57
BlockReopenQueue *queue, Error **errp)
45
+ * Create and open a block node.
46
+ *
47
+ * @options is a QDict of options to pass to the block drivers, or NULL for an
48
+ * empty set of options. The reference to the QDict belongs to the block layer
49
+ * after the call (even on failure), so if the caller intends to reuse the
50
+ * dictionary, it needs to use qobject_ref() before calling bdrv_open.
51
+ */
52
+BlockDriverState *bdrv_new_open_driver_opts(BlockDriver *drv,
53
+ const char *node_name,
54
+ QDict *options, int flags,
55
+ Error **errp)
56
{
58
{
57
BlockDriverState *bs;
59
+ BDRVVmdkState *s;
58
int ret;
60
+ BDRVVmdkReopenState *rs;
59
61
+ int i;
60
bs = bdrv_new();
62
+
61
bs->open_flags = flags;
63
assert(state != NULL);
62
- bs->explicit_options = qdict_new();
64
assert(state->bs != NULL);
63
- bs->options = qdict_new();
65
+ assert(state->opaque == NULL);
64
+ bs->options = options ?: qdict_new();
66
+
65
+ bs->explicit_options = qdict_clone_shallow(bs->options);
67
+ s = state->bs->opaque;
66
bs->opaque = NULL;
68
+
67
69
+ rs = g_new0(BDRVVmdkReopenState, 1);
68
update_options_from_flags(bs->options, flags);
70
+ state->opaque = rs;
69
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
71
+
70
return bs;
72
+ /*
73
+ * Check whether there are any extents stored in bs->file; if bs->file
74
+ * changes, we will need to update their .file pointers to follow suit
75
+ */
76
+ rs->extents_using_bs_file = g_new(bool, s->num_extents);
77
+ for (i = 0; i < s->num_extents; i++) {
78
+ rs->extents_using_bs_file[i] = s->extents[i].file == state->bs->file;
79
+ }
80
+
81
return 0;
71
}
82
}
72
83
73
+/* Create and open a block node. */
84
+static void vmdk_reopen_clean(BDRVReopenState *state)
74
+BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
75
+ int flags, Error **errp)
76
+{
85
+{
77
+ return bdrv_new_open_driver_opts(drv, node_name, NULL, flags, errp);
86
+ BDRVVmdkReopenState *rs = state->opaque;
87
+
88
+ g_free(rs->extents_using_bs_file);
89
+ g_free(rs);
90
+ state->opaque = NULL;
78
+}
91
+}
79
+
92
+
80
QemuOptsList bdrv_runtime_opts = {
93
+static void vmdk_reopen_commit(BDRVReopenState *state)
81
.name = "bdrv_common",
94
+{
82
.head = QTAILQ_HEAD_INITIALIZER(bdrv_runtime_opts.head),
95
+ BDRVVmdkState *s = state->bs->opaque;
96
+ BDRVVmdkReopenState *rs = state->opaque;
97
+ int i;
98
+
99
+ for (i = 0; i < s->num_extents; i++) {
100
+ if (rs->extents_using_bs_file[i]) {
101
+ s->extents[i].file = state->bs->file;
102
+ }
103
+ }
104
+
105
+ vmdk_reopen_clean(state);
106
+}
107
+
108
+static void vmdk_reopen_abort(BDRVReopenState *state)
109
+{
110
+ vmdk_reopen_clean(state);
111
+}
112
+
113
static int vmdk_parent_open(BlockDriverState *bs)
114
{
115
char *p_name;
116
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
117
.bdrv_open = vmdk_open,
118
.bdrv_co_check = vmdk_co_check,
119
.bdrv_reopen_prepare = vmdk_reopen_prepare,
120
+ .bdrv_reopen_commit = vmdk_reopen_commit,
121
+ .bdrv_reopen_abort = vmdk_reopen_abort,
122
.bdrv_child_perm = bdrv_default_perms,
123
.bdrv_co_preadv = vmdk_co_preadv,
124
.bdrv_co_pwritev = vmdk_co_pwritev,
83
--
125
--
84
2.31.1
126
2.35.1
85
86
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
Mostly uninteresting stuff. Move the test injections under a function
3
This should work for all format drivers that support reopening, so test
4
named main() so that the variables used during that process aren't in
4
it.
5
the global scope.
6
5
7
Signed-off-by: John Snow <jsnow@redhat.com>
6
(This serves as a regression test for HEAD^: This test used to fail for
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
VMDK before HEAD^.)
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20220314162719.65384-3-hreitz@redhat.com>
12
Message-Id: <20210923180715.4168522-6-jsnow@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
12
---
15
tests/qemu-iotests/tests/migrate-bitmaps-test | 50 +++++++++++--------
13
tests/qemu-iotests/tests/reopen-file | 89 ++++++++++++++++++++++++
16
1 file changed, 28 insertions(+), 22 deletions(-)
14
tests/qemu-iotests/tests/reopen-file.out | 5 ++
15
2 files changed, 94 insertions(+)
16
create mode 100755 tests/qemu-iotests/tests/reopen-file
17
create mode 100644 tests/qemu-iotests/tests/reopen-file.out
17
18
18
diff --git a/tests/qemu-iotests/tests/migrate-bitmaps-test b/tests/qemu-iotests/tests/migrate-bitmaps-test
19
diff --git a/tests/qemu-iotests/tests/reopen-file b/tests/qemu-iotests/tests/reopen-file
19
index XXXXXXX..XXXXXXX 100755
20
new file mode 100755
20
--- a/tests/qemu-iotests/tests/migrate-bitmaps-test
21
index XXXXXXX..XXXXXXX
21
+++ b/tests/qemu-iotests/tests/migrate-bitmaps-test
22
--- /dev/null
23
+++ b/tests/qemu-iotests/tests/reopen-file
22
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@
23
# along with this program. If not, see <http://www.gnu.org/licenses/>.
25
+#!/usr/bin/env python3
24
#
26
+# group: rw quick
25
27
+#
26
-import os
28
+# Test reopening a format driver's file child
27
import itertools
29
+#
28
import operator
30
+# Copyright (C) 2022 Red Hat, Inc.
31
+#
32
+# This program is free software; you can redistribute it and/or modify
33
+# it under the terms of the GNU General Public License as published by
34
+# the Free Software Foundation; either version 2 of the License, or
35
+# (at your option) any later version.
36
+#
37
+# This program is distributed in the hope that it will be useful,
38
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
39
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40
+# GNU General Public License for more details.
41
+#
42
+# You should have received a copy of the GNU General Public License
43
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
44
+#
45
+
29
+import os
46
+import os
30
import re
47
+import iotests
31
+
48
+from iotests import imgfmt, qemu_img_create, QMPTestCase
32
import iotests
33
from iotests import qemu_img, qemu_img_create, Timeout
34
35
@@ -XXX,XX +XXX,XX @@ def inject_test_case(klass, suffix, method, *args, **kwargs):
36
setattr(klass, 'test_' + method + suffix, lambda self: mc(self))
37
38
39
-for cmb in list(itertools.product((True, False), repeat=5)):
40
- name = ('_' if cmb[0] else '_not_') + 'persistent_'
41
- name += ('_' if cmb[1] else '_not_') + 'migbitmap_'
42
- name += '_online' if cmb[2] else '_offline'
43
- name += '_shared' if cmb[3] else '_nonshared'
44
- if cmb[4]:
45
- name += '__pre_shutdown'
46
-
47
- inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration',
48
- *list(cmb))
49
-
50
-for cmb in list(itertools.product((True, False), repeat=2)):
51
- name = ('_' if cmb[0] else '_not_') + 'persistent_'
52
- name += ('_' if cmb[1] else '_not_') + 'migbitmap'
53
-
54
- inject_test_case(TestDirtyBitmapMigration, name,
55
- 'do_test_migration_resume_source', *list(cmb))
56
-
57
-
58
class TestDirtyBitmapBackingMigration(iotests.QMPTestCase):
59
def setUp(self):
60
qemu_img_create('-f', iotests.imgfmt, base_a, size)
61
@@ -XXX,XX +XXX,XX @@ class TestDirtyBitmapBackingMigration(iotests.QMPTestCase):
62
self.assert_qmp(result, 'return', {})
63
64
65
+def main() -> None:
66
+ for cmb in list(itertools.product((True, False), repeat=5)):
67
+ name = ('_' if cmb[0] else '_not_') + 'persistent_'
68
+ name += ('_' if cmb[1] else '_not_') + 'migbitmap_'
69
+ name += '_online' if cmb[2] else '_offline'
70
+ name += '_shared' if cmb[3] else '_nonshared'
71
+ if cmb[4]:
72
+ name += '__pre_shutdown'
73
+
74
+ inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration',
75
+ *list(cmb))
76
+
77
+ for cmb in list(itertools.product((True, False), repeat=2)):
78
+ name = ('_' if cmb[0] else '_not_') + 'persistent_'
79
+ name += ('_' if cmb[1] else '_not_') + 'migbitmap'
80
+
81
+ inject_test_case(TestDirtyBitmapMigration, name,
82
+ 'do_test_migration_resume_source', *list(cmb))
83
+
84
+ iotests.main(
85
+ supported_fmts=['qcow2'],
86
+ supported_protocols=['file']
87
+ )
88
+
49
+
89
+
50
+
90
if __name__ == '__main__':
51
+image_size = 1 * 1024 * 1024
91
- iotests.main(supported_fmts=['qcow2'],
52
+test_img = os.path.join(iotests.test_dir, 'test.img')
92
- supported_protocols=['file'])
53
+
93
+ main()
54
+
55
+class TestReopenFile(QMPTestCase):
56
+ def setUp(self) -> None:
57
+ res = qemu_img_create('-f', imgfmt, test_img, str(image_size))
58
+ assert res.returncode == 0
59
+
60
+ # Add format driver node ('format') on top of the file ('file'), then
61
+ # add another raw node ('raw') on top of 'file' so for the reopen we
62
+ # can just switch from 'file' to 'raw'
63
+ self.vm = iotests.VM()
64
+ self.vm.add_blockdev(self.vm.qmp_to_opts({
65
+ 'driver': imgfmt,
66
+ 'node-name': 'format',
67
+ 'file': {
68
+ 'driver': 'file',
69
+ 'node-name': 'file',
70
+ 'filename': test_img
71
+ }
72
+ }))
73
+ self.vm.add_blockdev(self.vm.qmp_to_opts({
74
+ 'driver': 'raw',
75
+ 'node-name': 'raw',
76
+ 'file': 'file'
77
+ }))
78
+ self.vm.launch()
79
+
80
+ def tearDown(self) -> None:
81
+ self.vm.shutdown()
82
+ os.remove(test_img)
83
+
84
+ # Check if there was any qemu-io run that failed
85
+ if 'Pattern verification failed' in self.vm.get_log():
86
+ print('ERROR: Pattern verification failed:')
87
+ print(self.vm.get_log())
88
+ self.fail('qemu-io pattern verification failed')
89
+
90
+ def test_reopen_file(self) -> None:
91
+ result = self.vm.qmp('blockdev-reopen', options=[{
92
+ 'driver': imgfmt,
93
+ 'node-name': 'format',
94
+ 'file': 'raw'
95
+ }])
96
+ self.assert_qmp(result, 'return', {})
97
+
98
+ # Do some I/O to the image to see whether it still works
99
+ # (Pattern verification will be checked by tearDown())
100
+ result = self.vm.qmp('human-monitor-command',
101
+ command_line='qemu-io format "write -P 42 0 64k"')
102
+ self.assert_qmp(result, 'return', '')
103
+
104
+ result = self.vm.qmp('human-monitor-command',
105
+ command_line='qemu-io format "read -P 42 0 64k"')
106
+ self.assert_qmp(result, 'return', '')
107
+
108
+
109
+if __name__ == '__main__':
110
+ # Must support creating images and reopen
111
+ iotests.main(supported_fmts=['qcow', 'qcow2', 'qed', 'raw', 'vdi', 'vhdx',
112
+ 'vmdk', 'vpc'],
113
+ supported_protocols=['file'])
114
diff --git a/tests/qemu-iotests/tests/reopen-file.out b/tests/qemu-iotests/tests/reopen-file.out
115
new file mode 100644
116
index XXXXXXX..XXXXXXX
117
--- /dev/null
118
+++ b/tests/qemu-iotests/tests/reopen-file.out
119
@@ -XXX,XX +XXX,XX @@
120
+.
121
+----------------------------------------------------------------------
122
+Ran 1 tests
123
+
124
+OK
94
--
125
--
95
2.31.1
126
2.35.1
96
97
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
Now test fails if copy-before-write is not white-listed.
3
Thread-Local Storage variables cannot be used directly from coroutine
4
Let's skip test instead.
4
code because the compiler may optimize TLS variable accesses across
5
qemu_coroutine_yield() calls. When the coroutine is re-entered from
6
another thread the TLS variables from the old thread must no longer be
7
used.
5
8
6
Fixes: c0605985696a19ef034fa25d04f53f3b3b383896
9
Use QEMU_DEFINE_STATIC_CO_TLS() for the current and leader variables.
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
8
Message-Id: <20210920115538.264372-6-vsementsov@virtuozzo.com>
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-Id: <20220307153853.602859-2-stefanha@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
15
---
11
tests/qemu-iotests/tests/image-fleecing | 1 +
16
util/coroutine-ucontext.c | 38 ++++++++++++++++++++++++--------------
12
1 file changed, 1 insertion(+)
17
1 file changed, 24 insertions(+), 14 deletions(-)
13
18
14
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
19
diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c
15
index XXXXXXX..XXXXXXX 100755
20
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/tests/image-fleecing
21
--- a/util/coroutine-ucontext.c
17
+++ b/tests/qemu-iotests/tests/image-fleecing
22
+++ b/util/coroutine-ucontext.c
18
@@ -XXX,XX +XXX,XX @@ from iotests import log, qemu_img, qemu_io, qemu_io_silent
23
@@ -XXX,XX +XXX,XX @@
19
iotests.script_initialize(
24
#include "qemu/osdep.h"
20
supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk', 'vhdx', 'raw'],
25
#include <ucontext.h>
21
supported_platforms=['linux'],
26
#include "qemu/coroutine_int.h"
22
+ required_fmts=['copy-before-write'],
27
+#include "qemu/coroutine-tls.h"
23
)
28
24
29
#ifdef CONFIG_VALGRIND_H
25
patterns = [('0x5d', '0', '64k'),
30
#include <valgrind/valgrind.h>
31
@@ -XXX,XX +XXX,XX @@ typedef struct {
32
/**
33
* Per-thread coroutine bookkeeping
34
*/
35
-static __thread CoroutineUContext leader;
36
-static __thread Coroutine *current;
37
+QEMU_DEFINE_STATIC_CO_TLS(Coroutine *, current);
38
+QEMU_DEFINE_STATIC_CO_TLS(CoroutineUContext, leader);
39
40
/*
41
* va_args to makecontext() must be type 'int', so passing
42
@@ -XXX,XX +XXX,XX @@ static inline __attribute__((always_inline))
43
void finish_switch_fiber(void *fake_stack_save)
44
{
45
#ifdef CONFIG_ASAN
46
+ CoroutineUContext *leaderp = get_ptr_leader();
47
const void *bottom_old;
48
size_t size_old;
49
50
__sanitizer_finish_switch_fiber(fake_stack_save, &bottom_old, &size_old);
51
52
- if (!leader.stack) {
53
- leader.stack = (void *)bottom_old;
54
- leader.stack_size = size_old;
55
+ if (!leaderp->stack) {
56
+ leaderp->stack = (void *)bottom_old;
57
+ leaderp->stack_size = size_old;
58
}
59
#endif
60
#ifdef CONFIG_TSAN
61
@@ -XXX,XX +XXX,XX @@ static void coroutine_trampoline(int i0, int i1)
62
63
/* Initialize longjmp environment and switch back the caller */
64
if (!sigsetjmp(self->env, 0)) {
65
- start_switch_fiber_asan(COROUTINE_YIELD, &fake_stack_save, leader.stack,
66
- leader.stack_size);
67
+ CoroutineUContext *leaderp = get_ptr_leader();
68
+
69
+ start_switch_fiber_asan(COROUTINE_YIELD, &fake_stack_save,
70
+ leaderp->stack, leaderp->stack_size);
71
start_switch_fiber_tsan(&fake_stack_save, self, true); /* true=caller */
72
siglongjmp(*(sigjmp_buf *)co->entry_arg, 1);
73
}
74
@@ -XXX,XX +XXX,XX @@ qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
75
int ret;
76
void *fake_stack_save = NULL;
77
78
- current = to_;
79
+ set_current(to_);
80
81
ret = sigsetjmp(from->env, 0);
82
if (ret == 0) {
83
@@ -XXX,XX +XXX,XX @@ qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
84
85
Coroutine *qemu_coroutine_self(void)
86
{
87
- if (!current) {
88
- current = &leader.base;
89
+ Coroutine *self = get_current();
90
+ CoroutineUContext *leaderp = get_ptr_leader();
91
+
92
+ if (!self) {
93
+ self = &leaderp->base;
94
+ set_current(self);
95
}
96
#ifdef CONFIG_TSAN
97
- if (!leader.tsan_co_fiber) {
98
- leader.tsan_co_fiber = __tsan_get_current_fiber();
99
+ if (!leaderp->tsan_co_fiber) {
100
+ leaderp->tsan_co_fiber = __tsan_get_current_fiber();
101
}
102
#endif
103
- return current;
104
+ return self;
105
}
106
107
bool qemu_in_coroutine(void)
108
{
109
- return current && current->caller;
110
+ Coroutine *self = get_current();
111
+
112
+ return self && self->caller;
113
}
26
--
114
--
27
2.31.1
115
2.35.1
28
116
29
117
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
When configuring QEMU with --disable-fuse, the qemu-storage-daemon
3
Thread-Local Storage variables cannot be used directly from coroutine
4
still reports FUSE command line options in its help:
4
code because the compiler may optimize TLS variable accesses across
5
qemu_coroutine_yield() calls. When the coroutine is re-entered from
6
another thread the TLS variables from the old thread must no longer be
7
used.
5
8
6
$ qemu-storage-daemon -h
9
Use QEMU_DEFINE_STATIC_CO_TLS() for the current and leader variables.
7
Usage: qemu-storage-daemon [options]
10
The alloc_pool QSLIST needs a typedef so the return value of
8
QEMU storage daemon
11
get_ptr_alloc_pool() can be stored in a local variable.
9
12
10
--export [type=]fuse,id=<id>,node-name=<node-name>,mountpoint=<file>
13
One example of why this code is necessary: a coroutine that yields
11
[,growable=on|off][,writable=on|off]
14
before calling qemu_coroutine_create() to create another coroutine is
12
export the specified block node over FUSE
15
affected by the TLS issue.
13
16
14
Remove this help message when FUSE is disabled, to avoid:
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
18
Message-Id: <20220307153853.602859-3-stefanha@redhat.com>
16
$ qemu-storage-daemon --export fuse
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
qemu-storage-daemon: --export fuse: Invalid parameter 'fuse'
18
19
Reported-by: Qing Wang <qinwang@redhat.com>
20
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Message-Id: <20210816180442.2000642-1-philmd@redhat.com>
22
Reviewed-by: Eric Blake <eblake@redhat.com>
23
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
---
21
---
26
storage-daemon/qemu-storage-daemon.c | 2 ++
22
util/qemu-coroutine.c | 41 ++++++++++++++++++++++++-----------------
27
1 file changed, 2 insertions(+)
23
1 file changed, 24 insertions(+), 17 deletions(-)
28
24
29
diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c
25
diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c
30
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
31
--- a/storage-daemon/qemu-storage-daemon.c
27
--- a/util/qemu-coroutine.c
32
+++ b/storage-daemon/qemu-storage-daemon.c
28
+++ b/util/qemu-coroutine.c
33
@@ -XXX,XX +XXX,XX @@ static void help(void)
29
@@ -XXX,XX +XXX,XX @@
34
" export the specified block node over NBD\n"
30
#include "qemu/atomic.h"
35
" (requires --nbd-server)\n"
31
#include "qemu/coroutine.h"
36
"\n"
32
#include "qemu/coroutine_int.h"
37
+#ifdef CONFIG_FUSE
33
+#include "qemu/coroutine-tls.h"
38
" --export [type=]fuse,id=<id>,node-name=<node-name>,mountpoint=<file>\n"
34
#include "block/aio.h"
39
" [,growable=on|off][,writable=on|off]\n"
35
40
" export the specified block node over FUSE\n"
36
/** Initial batch size is 64, and is increased on demand */
41
"\n"
37
@@ -XXX,XX +XXX,XX @@ enum {
42
+#endif /* CONFIG_FUSE */
38
static QSLIST_HEAD(, Coroutine) release_pool = QSLIST_HEAD_INITIALIZER(pool);
43
" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n"
39
static unsigned int pool_batch_size = POOL_INITIAL_BATCH_SIZE;
44
" configure a QMP monitor\n"
40
static unsigned int release_pool_size;
45
"\n"
41
-static __thread QSLIST_HEAD(, Coroutine) alloc_pool = QSLIST_HEAD_INITIALIZER(pool);
42
-static __thread unsigned int alloc_pool_size;
43
-static __thread Notifier coroutine_pool_cleanup_notifier;
44
+
45
+typedef QSLIST_HEAD(, Coroutine) CoroutineQSList;
46
+QEMU_DEFINE_STATIC_CO_TLS(CoroutineQSList, alloc_pool);
47
+QEMU_DEFINE_STATIC_CO_TLS(unsigned int, alloc_pool_size);
48
+QEMU_DEFINE_STATIC_CO_TLS(Notifier, coroutine_pool_cleanup_notifier);
49
50
static void coroutine_pool_cleanup(Notifier *n, void *value)
51
{
52
Coroutine *co;
53
Coroutine *tmp;
54
+ CoroutineQSList *alloc_pool = get_ptr_alloc_pool();
55
56
- QSLIST_FOREACH_SAFE(co, &alloc_pool, pool_next, tmp) {
57
- QSLIST_REMOVE_HEAD(&alloc_pool, pool_next);
58
+ QSLIST_FOREACH_SAFE(co, alloc_pool, pool_next, tmp) {
59
+ QSLIST_REMOVE_HEAD(alloc_pool, pool_next);
60
qemu_coroutine_delete(co);
61
}
62
}
63
@@ -XXX,XX +XXX,XX @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque)
64
Coroutine *co = NULL;
65
66
if (CONFIG_COROUTINE_POOL) {
67
- co = QSLIST_FIRST(&alloc_pool);
68
+ CoroutineQSList *alloc_pool = get_ptr_alloc_pool();
69
+
70
+ co = QSLIST_FIRST(alloc_pool);
71
if (!co) {
72
if (release_pool_size > qatomic_read(&pool_batch_size)) {
73
/* Slow path; a good place to register the destructor, too. */
74
- if (!coroutine_pool_cleanup_notifier.notify) {
75
- coroutine_pool_cleanup_notifier.notify = coroutine_pool_cleanup;
76
- qemu_thread_atexit_add(&coroutine_pool_cleanup_notifier);
77
+ Notifier *notifier = get_ptr_coroutine_pool_cleanup_notifier();
78
+ if (!notifier->notify) {
79
+ notifier->notify = coroutine_pool_cleanup;
80
+ qemu_thread_atexit_add(notifier);
81
}
82
83
/* This is not exact; there could be a little skew between
84
* release_pool_size and the actual size of release_pool. But
85
* it is just a heuristic, it does not need to be perfect.
86
*/
87
- alloc_pool_size = qatomic_xchg(&release_pool_size, 0);
88
- QSLIST_MOVE_ATOMIC(&alloc_pool, &release_pool);
89
- co = QSLIST_FIRST(&alloc_pool);
90
+ set_alloc_pool_size(qatomic_xchg(&release_pool_size, 0));
91
+ QSLIST_MOVE_ATOMIC(alloc_pool, &release_pool);
92
+ co = QSLIST_FIRST(alloc_pool);
93
}
94
}
95
if (co) {
96
- QSLIST_REMOVE_HEAD(&alloc_pool, pool_next);
97
- alloc_pool_size--;
98
+ QSLIST_REMOVE_HEAD(alloc_pool, pool_next);
99
+ set_alloc_pool_size(get_alloc_pool_size() - 1);
100
}
101
}
102
103
@@ -XXX,XX +XXX,XX @@ static void coroutine_delete(Coroutine *co)
104
qatomic_inc(&release_pool_size);
105
return;
106
}
107
- if (alloc_pool_size < qatomic_read(&pool_batch_size)) {
108
- QSLIST_INSERT_HEAD(&alloc_pool, co, pool_next);
109
- alloc_pool_size++;
110
+ if (get_alloc_pool_size() < qatomic_read(&pool_batch_size)) {
111
+ QSLIST_INSERT_HEAD(get_ptr_alloc_pool(), co, pool_next);
112
+ set_alloc_pool_size(get_alloc_pool_size() + 1);
113
return;
114
}
115
}
46
--
116
--
47
2.31.1
117
2.35.1
48
118
49
119
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
We can drop the sys.path hacking in various places by doing
3
Thread-Local Storage variables cannot be used directly from coroutine
4
this. Additionally, by doing it in one place right up top, we can print
4
code because the compiler may optimize TLS variable accesses across
5
interesting warnings in case the environment does not look correct. (See
5
qemu_coroutine_yield() calls. When the coroutine is re-entered from
6
next commit.)
6
another thread the TLS variables from the old thread must no longer be
7
used.
7
8
8
If we ever decide to change how the environment is crafted, all of the
9
Use QEMU_DEFINE_STATIC_CO_TLS() for the current and leader variables.
9
"help me find my python packages" goop is all in one place, right in one
10
function.
11
10
12
Signed-off-by: John Snow <jsnow@redhat.com>
11
I think coroutine-win32.c could get away with __thread because the
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
variables are only used in situations where either the stale value is
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
correct (current) or outside coroutine context (loading leader when
15
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
current is NULL). Due to the difficulty of being sure that this is
16
Message-Id: <20210923180715.4168522-2-jsnow@redhat.com>
15
really safe in all scenarios it seems worth converting it anyway.
16
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
18
Message-Id: <20220307153853.602859-4-stefanha@redhat.com>
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
21
---
19
tests/qemu-iotests/iotests.py | 2 --
22
util/coroutine-win32.c | 18 +++++++++++++-----
20
tests/qemu-iotests/testenv.py | 15 +++++++++------
23
1 file changed, 13 insertions(+), 5 deletions(-)
21
tests/qemu-iotests/235 | 2 --
22
tests/qemu-iotests/297 | 6 ------
23
tests/qemu-iotests/300 | 5 ++---
24
tests/qemu-iotests/tests/mirror-top-perms | 7 +++----
25
6 files changed, 14 insertions(+), 23 deletions(-)
26
24
27
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
25
diff --git a/util/coroutine-win32.c b/util/coroutine-win32.c
28
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
29
--- a/tests/qemu-iotests/iotests.py
27
--- a/util/coroutine-win32.c
30
+++ b/tests/qemu-iotests/iotests.py
28
+++ b/util/coroutine-win32.c
31
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@
32
30
33
from contextlib import contextmanager
31
#include "qemu/osdep.h"
34
32
#include "qemu/coroutine_int.h"
35
-# pylint: disable=import-error, wrong-import-position
33
+#include "qemu/coroutine-tls.h"
36
-sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
34
37
from qemu.machine import qtest
35
typedef struct
38
from qemu.qmp import QMPMessage
36
{
39
37
@@ -XXX,XX +XXX,XX @@ typedef struct
40
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
38
CoroutineAction action;
41
index XXXXXXX..XXXXXXX 100644
39
} CoroutineWin32;
42
--- a/tests/qemu-iotests/testenv.py
40
43
+++ b/tests/qemu-iotests/testenv.py
41
-static __thread CoroutineWin32 leader;
44
@@ -XXX,XX +XXX,XX @@ def init_directories(self) -> None:
42
-static __thread Coroutine *current;
45
SAMPLE_IMG_DIR
43
+QEMU_DEFINE_STATIC_CO_TLS(CoroutineWin32, leader);
46
OUTPUT_DIR
44
+QEMU_DEFINE_STATIC_CO_TLS(Coroutine *, current);
47
"""
45
48
- self.pythonpath = os.getenv('PYTHONPATH')
46
/* This function is marked noinline to prevent GCC from inlining it
49
- if self.pythonpath:
47
* into coroutine_trampoline(). If we allow it to do that then it
50
- self.pythonpath = self.source_iotests + os.pathsep + \
48
@@ -XXX,XX +XXX,XX @@ qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
51
- self.pythonpath
49
CoroutineWin32 *from = DO_UPCAST(CoroutineWin32, base, from_);
52
- else:
50
CoroutineWin32 *to = DO_UPCAST(CoroutineWin32, base, to_);
53
- self.pythonpath = self.source_iotests
51
52
- current = to_;
53
+ set_current(to_);
54
55
to->action = action;
56
SwitchToFiber(to->fiber);
57
@@ -XXX,XX +XXX,XX @@ void qemu_coroutine_delete(Coroutine *co_)
58
59
Coroutine *qemu_coroutine_self(void)
60
{
61
+ Coroutine *current = get_current();
54
+
62
+
55
+ # Path where qemu goodies live in this source tree.
63
if (!current) {
56
+ qemu_srctree_path = Path(__file__, '../../../python').resolve()
64
- current = &leader.base;
65
- leader.fiber = ConvertThreadToFiber(NULL);
66
+ CoroutineWin32 *leader = get_ptr_leader();
57
+
67
+
58
+ self.pythonpath = os.pathsep.join(filter(None, (
68
+ current = &leader->base;
59
+ self.source_iotests,
69
+ set_current(current);
60
+ str(qemu_srctree_path),
70
+ leader->fiber = ConvertThreadToFiber(NULL);
61
+ os.getenv('PYTHONPATH'),
71
}
62
+ )))
72
return current;
63
73
}
64
self.test_dir = os.getenv('TEST_DIR',
74
65
os.path.join(os.getcwd(), 'scratch'))
75
bool qemu_in_coroutine(void)
66
diff --git a/tests/qemu-iotests/235 b/tests/qemu-iotests/235
76
{
67
index XXXXXXX..XXXXXXX 100755
77
+ Coroutine *current = get_current();
68
--- a/tests/qemu-iotests/235
69
+++ b/tests/qemu-iotests/235
70
@@ -XXX,XX +XXX,XX @@ import os
71
import iotests
72
from iotests import qemu_img_create, qemu_io, file_path, log
73
74
-sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
75
-
76
from qemu.machine import QEMUMachine
77
78
iotests.script_initialize(supported_fmts=['qcow2'])
79
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
80
index XXXXXXX..XXXXXXX 100755
81
--- a/tests/qemu-iotests/297
82
+++ b/tests/qemu-iotests/297
83
@@ -XXX,XX +XXX,XX @@ def run_linters():
84
# Todo notes are fine, but fixme's or xxx's should probably just be
85
# fixed (in tests, at least)
86
env = os.environ.copy()
87
- qemu_module_path = os.path.join(os.path.dirname(__file__),
88
- '..', '..', 'python')
89
- try:
90
- env['PYTHONPATH'] += os.pathsep + qemu_module_path
91
- except KeyError:
92
- env['PYTHONPATH'] = qemu_module_path
93
subprocess.run(('pylint-3', '--score=n', '--notes=FIXME,XXX', *files),
94
env=env, check=False)
95
96
diff --git a/tests/qemu-iotests/300 b/tests/qemu-iotests/300
97
index XXXXXXX..XXXXXXX 100755
98
--- a/tests/qemu-iotests/300
99
+++ b/tests/qemu-iotests/300
100
@@ -XXX,XX +XXX,XX @@ import random
101
import re
102
from typing import Dict, List, Optional
103
104
+from qemu.machine import machine
105
+
78
+
106
import iotests
79
return current && current->caller;
107
80
}
108
-# Import qemu after iotests.py has amended sys.path
109
-# pylint: disable=wrong-import-order
110
-from qemu.machine import machine
111
112
BlockBitmapMapping = List[Dict[str, object]]
113
114
diff --git a/tests/qemu-iotests/tests/mirror-top-perms b/tests/qemu-iotests/tests/mirror-top-perms
115
index XXXXXXX..XXXXXXX 100755
116
--- a/tests/qemu-iotests/tests/mirror-top-perms
117
+++ b/tests/qemu-iotests/tests/mirror-top-perms
118
@@ -XXX,XX +XXX,XX @@
119
#
120
121
import os
122
-import iotests
123
-from iotests import qemu_img
124
125
-# Import qemu after iotests.py has amended sys.path
126
-# pylint: disable=wrong-import-order
127
import qemu
128
129
+import iotests
130
+from iotests import qemu_img
131
+
132
133
image_size = 1 * 1024 * 1024
134
source = os.path.join(iotests.test_dir, 'source.img')
135
--
81
--
136
2.31.1
82
2.35.1
137
83
138
84
diff view generated by jsdifflib