1
The following changes since commit 22dbfdecc3c52228d3489da3fe81da92b21197bf:
1
The following changes since commit e3acc2c1961cbe22ca474cd5da4163b7bbf7cea3:
2
2
3
Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20191010.0' into staging (2019-10-14 15:09:08 +0100)
3
tests/docker/dockerfiles: Bump fedora-i386-cross to fedora 34 (2021-10-05 16:40:39 -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 a1406a9262a087d9ec9627b88da13c4590b61dae:
9
for you to fetch changes up to 3765315d4c84f9c0799744f43a314169baaccc05:
10
10
11
iotests: Test large write request to qcow2 file (2019-10-14 17:12:48 +0200)
11
iotests: Update for pylint 2.11.1 (2021-10-06 10:25:55 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- block: Fix crash with qcow2 partial cluster COW with small cluster
16
- Fix I/O errors because of incorrectly detected max_iov
17
sizes (misaligned write requests with BDRV_REQ_NO_FALLBACK)
17
- Fix not white-listed copy-before-write
18
- qcow2: Fix integer overflow potentially causing corruption with huge
18
- qemu-storage-daemon: Only display FUSE help when FUSE is built-in
19
requests
19
- iotests: update environment and linting configuration
20
- vhdx: Detect truncated image files
21
- tools: Support help options for --object
22
- Various block-related replay improvements
23
- iotests/028: Fix for long $TEST_DIRs
24
20
25
----------------------------------------------------------------
21
----------------------------------------------------------------
26
Alberto Garcia (1):
22
Emanuele Giuseppe Esposito (1):
27
block: Reject misaligned write requests with BDRV_REQ_NO_FALLBACK
23
include/block.h: remove outdated comment
28
24
29
Kevin Wolf (4):
25
John Snow (5):
30
vl: Split off user_creatable_print_help()
26
iotests: add 'qemu' package location to PYTHONPATH in testenv
31
qemu-io: Support help options for --object
27
iotests/linters: check mypy files all at once
32
qemu-img: Support help options for --object
28
iotests/mirror-top-perms: Adjust imports
33
qemu-nbd: Support help options for --object
29
iotests/migrate-bitmaps-test: delint
30
iotests: Update for pylint 2.11.1
34
31
35
Max Reitz (3):
32
Paolo Bonzini (1):
36
iotests/028: Fix for long $TEST_DIRs
33
block: introduce max_hw_iov for use in scsi-generic
37
qcow2: Limit total allocation range to INT_MAX
38
iotests: Test large write request to qcow2 file
39
34
40
Pavel Dovgaluk (6):
35
Philippe Mathieu-Daudé (1):
41
block: implement bdrv_snapshot_goto for blkreplay
36
qemu-storage-daemon: Only display FUSE help when FUSE is built-in
42
replay: disable default snapshot for record/replay
43
replay: update docs for record/replay with block devices
44
replay: don't drain/flush bdrv queue while RR is working
45
replay: finish record/replay before closing the disks
46
replay: add BH oneshot event for block layer
47
37
48
Peter Lieven (1):
38
Vladimir Sementsov-Ogievskiy (5):
49
block/vhdx: add check for truncated image files
39
block: implement bdrv_new_open_driver_opts()
40
block: bdrv_insert_node(): fix and improve error handling
41
block: bdrv_insert_node(): doc and style
42
block: bdrv_insert_node(): don't use bdrv_open()
43
iotests/image-fleecing: declare requirement of copy-before-write
50
44
51
docs/replay.txt | 12 +++-
45
include/block/block.h | 8 ++-
52
include/qom/object_interfaces.h | 12 ++++
46
include/block/block_int.h | 7 +++
53
include/sysemu/replay.h | 4 ++
47
include/sysemu/block-backend.h | 1 +
54
replay/replay-internal.h | 1 +
48
block.c | 79 ++++++++++++++++++++++-----
55
block/blkreplay.c | 8 +++
49
block/block-backend.c | 6 ++
56
block/block-backend.c | 9 ++-
50
block/file-posix.c | 2 +-
57
block/io.c | 39 ++++++++++++-
51
block/io.c | 1 +
58
block/iscsi.c | 5 +-
52
hw/scsi/scsi-generic.c | 2 +-
59
block/nfs.c | 6 +-
53
storage-daemon/qemu-storage-daemon.c | 2 +
60
block/null.c | 4 +-
54
tests/qemu-iotests/iotests.py | 2 -
61
block/nvme.c | 6 +-
55
tests/qemu-iotests/testenv.py | 15 +++--
62
block/qcow2-cluster.c | 5 +-
56
tests/qemu-iotests/testrunner.py | 7 ++-
63
block/rbd.c | 5 +-
57
tests/qemu-iotests/235 | 2 -
64
block/vhdx.c | 120 ++++++++++++++++++++++++++++++++++------
58
tests/qemu-iotests/297 | 52 +++++++-----------
65
block/vxhs.c | 5 +-
59
tests/qemu-iotests/300 | 5 +-
66
cpus.c | 2 -
60
tests/qemu-iotests/pylintrc | 6 +-
67
qemu-img.c | 34 +++++++-----
61
tests/qemu-iotests/tests/image-fleecing | 1 +
68
qemu-io.c | 9 ++-
62
tests/qemu-iotests/tests/migrate-bitmaps-test | 50 +++++++++--------
69
qemu-nbd.c | 9 ++-
63
tests/qemu-iotests/tests/mirror-top-perms | 12 ++--
70
qom/object_interfaces.c | 61 ++++++++++++++++++++
64
19 files changed, 164 insertions(+), 96 deletions(-)
71
replay/replay-events.c | 16 ++++++
72
replay/replay.c | 2 +
73
stubs/replay-user.c | 9 +++
74
vl.c | 63 ++++-----------------
75
stubs/Makefile.objs | 1 +
76
tests/qemu-iotests/028 | 11 +++-
77
tests/qemu-iotests/028.out | 1 -
78
tests/qemu-iotests/268 | 55 ++++++++++++++++++
79
tests/qemu-iotests/268.out | 7 +++
80
tests/qemu-iotests/270 | 83 +++++++++++++++++++++++++++
81
tests/qemu-iotests/270.out | 9 +++
82
tests/qemu-iotests/group | 2 +
83
32 files changed, 504 insertions(+), 111 deletions(-)
84
create mode 100644 stubs/replay-user.c
85
create mode 100755 tests/qemu-iotests/268
86
create mode 100644 tests/qemu-iotests/268.out
87
create mode 100755 tests/qemu-iotests/270
88
create mode 100644 tests/qemu-iotests/270.out
89
65
66
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
There are a couple of errors in bdrv_drained_begin header comment:
4
- block_job_pause does not exist anymore, it has been replaced
5
with job_pause in b15de82867
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
10
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Message-Id: <20210903113800.59970-1-eesposit@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
include/block/block.h | 4 +---
16
1 file changed, 1 insertion(+), 3 deletions(-)
17
18
diff --git a/include/block/block.h b/include/block/block.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/block.h
21
+++ b/include/block/block.h
22
@@ -XXX,XX +XXX,XX @@ bool bdrv_drain_poll(BlockDriverState *bs, bool recursive,
23
* bdrv_drained_begin:
24
*
25
* Begin a quiesced section for exclusive access to the BDS, by disabling
26
- * external request sources including NBD server and device model. Note that
27
- * this doesn't block timers or coroutines from submitting more requests, which
28
- * means block_job_pause is still necessary.
29
+ * external request sources including NBD server, block jobs, and device model.
30
*
31
* This function can be recursive.
32
*/
33
--
34
2.31.1
35
36
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
2
3
When configuring QEMU with --disable-fuse, the qemu-storage-daemon
4
still reports FUSE command line options in its help:
5
6
$ qemu-storage-daemon -h
7
Usage: qemu-storage-daemon [options]
8
QEMU storage daemon
9
10
--export [type=]fuse,id=<id>,node-name=<node-name>,mountpoint=<file>
11
[,growable=on|off][,writable=on|off]
12
export the specified block node over FUSE
13
14
Remove this help message when FUSE is disabled, to avoid:
15
16
$ qemu-storage-daemon --export fuse
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>
25
---
26
storage-daemon/qemu-storage-daemon.c | 2 ++
27
1 file changed, 2 insertions(+)
28
29
diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/storage-daemon/qemu-storage-daemon.c
32
+++ b/storage-daemon/qemu-storage-daemon.c
33
@@ -XXX,XX +XXX,XX @@ static void help(void)
34
" export the specified block node over NBD\n"
35
" (requires --nbd-server)\n"
36
"\n"
37
+#ifdef CONFIG_FUSE
38
" --export [type=]fuse,id=<id>,node-name=<node-name>,mountpoint=<file>\n"
39
" [,growable=on|off][,writable=on|off]\n"
40
" export the specified block node over FUSE\n"
41
"\n"
42
+#endif /* CONFIG_FUSE */
43
" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n"
44
" configure a QMP monitor\n"
45
"\n"
46
--
47
2.31.1
48
49
diff view generated by jsdifflib
1
From: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
This patch enables making snapshots with blkreplay used in
3
Add version of bdrv_new_open_driver() that supports QDict options.
4
block devices.
4
We'll use it in further commit.
5
This function is required to make bdrv_snapshot_goto without
6
calling .bdrv_open which is not implemented.
7
5
8
Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
6
Simply add one more argument to bdrv_new_open_driver() is worse, as
9
Acked-by: Kevin Wolf <kwolf@redhat.com>
7
there are too many invocations of bdrv_new_open_driver() to update
8
then.
9
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Suggested-by: Kevin Wolf <kwolf@redhat.com>
12
Message-Id: <20210920115538.264372-2-vsementsov@virtuozzo.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
14
---
12
block/blkreplay.c | 8 ++++++++
15
include/block/block.h | 4 ++++
13
1 file changed, 8 insertions(+)
16
block.c | 25 +++++++++++++++++++++----
17
2 files changed, 25 insertions(+), 4 deletions(-)
14
18
15
diff --git a/block/blkreplay.c b/block/blkreplay.c
19
diff --git a/include/block/block.h b/include/block/block.h
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/block/blkreplay.c
21
--- a/include/block/block.h
18
+++ b/block/blkreplay.c
22
+++ b/include/block/block.h
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs)
23
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
24
const char *bdref_key, Error **errp);
25
BlockDriverState *bdrv_open(const char *filename, const char *reference,
26
QDict *options, int flags, Error **errp);
27
+BlockDriverState *bdrv_new_open_driver_opts(BlockDriver *drv,
28
+ const char *node_name,
29
+ QDict *options, int flags,
30
+ Error **errp);
31
BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
32
int flags, Error **errp);
33
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
34
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
37
+++ b/block.c
38
@@ -XXX,XX +XXX,XX @@ open_failed:
20
return ret;
39
return ret;
21
}
40
}
22
41
23
+static int blkreplay_snapshot_goto(BlockDriverState *bs,
42
-BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
24
+ const char *snapshot_id)
43
- int flags, Error **errp)
44
+/*
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
{
57
BlockDriverState *bs;
58
int ret;
59
60
bs = bdrv_new();
61
bs->open_flags = flags;
62
- bs->explicit_options = qdict_new();
63
- bs->options = qdict_new();
64
+ bs->options = options ?: qdict_new();
65
+ bs->explicit_options = qdict_clone_shallow(bs->options);
66
bs->opaque = NULL;
67
68
update_options_from_flags(bs->options, flags);
69
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
70
return bs;
71
}
72
73
+/* Create and open a block node. */
74
+BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
75
+ int flags, Error **errp)
25
+{
76
+{
26
+ return bdrv_snapshot_goto(bs->file->bs, snapshot_id, NULL);
77
+ return bdrv_new_open_driver_opts(drv, node_name, NULL, flags, errp);
27
+}
78
+}
28
+
79
+
29
static BlockDriver bdrv_blkreplay = {
80
QemuOptsList bdrv_runtime_opts = {
30
.format_name = "blkreplay",
81
.name = "bdrv_common",
31
.instance_size = 0,
82
.head = QTAILQ_HEAD_INITIALIZER(bdrv_runtime_opts.head),
32
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkreplay = {
33
.bdrv_co_pwrite_zeroes = blkreplay_co_pwrite_zeroes,
34
.bdrv_co_pdiscard = blkreplay_co_pdiscard,
35
.bdrv_co_flush = blkreplay_co_flush,
36
+
37
+ .bdrv_snapshot_goto = blkreplay_snapshot_goto,
38
};
39
40
static void bdrv_blkreplay_init(void)
41
--
83
--
42
2.20.1
84
2.31.1
43
85
44
86
diff view generated by jsdifflib
1
From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
In record/replay mode bdrv queue is controlled by replay mechanism.
3
- use ERRP_GUARD(): function calls error_prepend(), so it must use
4
It does not allow saving or loading the snapshots
4
ERRP_GUARD(), otherwise error_prepend() would not be called when
5
when bdrv queue is not empty. Stopping the VM is not blocked by nonempty
5
passed errp is error_fatal
6
queue, but flushing the queue is still impossible there,
7
because it may cause deadlocks in replay mode.
8
This patch disables bdrv_drain_all and bdrv_flush_all in
9
record/replay mode.
10
6
11
Stopping the machine when the IO requests are not finished is needed
7
- drop error propagation, handle return code instead
12
for the debugging. E.g., breakpoint may be set at the specified step,
13
and forcing the IO requests to finish may break the determinism
14
of the execution.
15
8
16
Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
9
- for symmetry, do error_prepend() for the second failure
17
Acked-by: Kevin Wolf <kwolf@redhat.com>
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Message-Id: <20210920115538.264372-3-vsementsov@virtuozzo.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
14
---
20
block/io.c | 28 ++++++++++++++++++++++++++++
15
block.c | 9 +++++----
21
cpus.c | 2 --
16
1 file changed, 5 insertions(+), 4 deletions(-)
22
2 files changed, 28 insertions(+), 2 deletions(-)
23
17
24
diff --git a/block/io.c b/block/io.c
18
diff --git a/block.c b/block.c
25
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
26
--- a/block/io.c
20
--- a/block.c
27
+++ b/block/io.c
21
+++ b/block.c
28
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void bdrv_delete(BlockDriverState *bs)
29
#include "qapi/error.h"
23
BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
30
#include "qemu/error-report.h"
24
int flags, Error **errp)
31
#include "qemu/main-loop.h"
25
{
32
+#include "sysemu/replay.h"
26
+ ERRP_GUARD();
33
27
+ int ret;
34
#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
28
BlockDriverState *new_node_bs;
35
29
- Error *local_err = NULL;
36
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_begin(void)
30
37
return;
31
new_node_bs = bdrv_open(NULL, NULL, node_options, flags, errp);
32
if (new_node_bs == NULL) {
33
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
38
}
34
}
39
35
40
+ /*
36
bdrv_drained_begin(bs);
41
+ * bdrv queue is managed by record/replay,
37
- bdrv_replace_node(bs, new_node_bs, &local_err);
42
+ * waiting for finishing the I/O requests may
38
+ ret = bdrv_replace_node(bs, new_node_bs, errp);
43
+ * be infinite
39
bdrv_drained_end(bs);
44
+ */
40
45
+ if (replay_events_enabled()) {
41
- if (local_err) {
46
+ return;
42
+ if (ret < 0) {
47
+ }
43
+ error_prepend(errp, "Could not replace node: ");
48
+
44
bdrv_unref(new_node_bs);
49
/* AIO_WAIT_WHILE() with a NULL context can only be called from the main
45
- error_propagate(errp, local_err);
50
* loop AioContext, so make sure we're in the main context. */
46
return NULL;
51
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
52
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all_end(void)
53
BlockDriverState *bs = NULL;
54
int drained_end_counter = 0;
55
56
+ /*
57
+ * bdrv queue is managed by record/replay,
58
+ * waiting for finishing the I/O requests may
59
+ * be endless
60
+ */
61
+ if (replay_events_enabled()) {
62
+ return;
63
+ }
64
+
65
while ((bs = bdrv_next_all_states(bs))) {
66
AioContext *aio_context = bdrv_get_aio_context(bs);
67
68
@@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void)
69
BlockDriverState *bs = NULL;
70
int result = 0;
71
72
+ /*
73
+ * bdrv queue is managed by record/replay,
74
+ * creating new flush request for stopping
75
+ * the VM may break the determinism
76
+ */
77
+ if (replay_events_enabled()) {
78
+ return result;
79
+ }
80
+
81
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
82
AioContext *aio_context = bdrv_get_aio_context(bs);
83
int ret;
84
diff --git a/cpus.c b/cpus.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/cpus.c
87
+++ b/cpus.c
88
@@ -XXX,XX +XXX,XX @@ static int do_vm_stop(RunState state, bool send_stop)
89
}
47
}
90
48
91
bdrv_drain_all();
92
- replay_disable_events();
93
ret = bdrv_flush_all();
94
95
return ret;
96
@@ -XXX,XX +XXX,XX @@ int vm_prepare_start(void)
97
/* We are sending this now, but the CPUs will be resumed shortly later */
98
qapi_event_send_resume();
99
100
- replay_enable_events();
101
cpu_enable_ticks();
102
runstate_set(RUN_STATE_RUNNING);
103
vm_state_notify(1, RUN_STATE_RUNNING);
104
--
49
--
105
2.20.1
50
2.31.1
106
51
107
52
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
- options & flags is common pair for open-like functions, let's use it
4
- add a comment that specifies use of @options
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20210920115538.264372-4-vsementsov@virtuozzo.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block.c | 13 +++++++++++--
11
1 file changed, 11 insertions(+), 2 deletions(-)
12
13
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
16
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ static void bdrv_delete(BlockDriverState *bs)
18
g_free(bs);
19
}
20
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
--
44
2.31.1
45
46
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
The BDRV_REQ_NO_FALLBACK flag means that an operation should only be
3
Use bdrv_new_open_driver_opts() instead of complicated bdrv_open().
4
performed if it can be offloaded or otherwise performed efficiently.
5
4
6
However a misaligned write request requires a RMW so we should return
5
Among other extra things bdrv_open() also check for white-listed
7
an error and let the caller decide how to proceed.
6
formats, which we don't want for internal node creation: currently
7
backup doesn't work when copy-before-write filter is not white-listed.
8
As well block-stream doesn't work when copy-on-read is not
9
white-listed.
8
10
9
This hits an assertion since commit c8bb23cbdb if the required
11
Fixes: 751cec7a261adaf1145dc7adf6de7c9c084e5a0b
10
alignment is larger than the cluster size:
12
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2004812
11
13
Reported-by: Yanan Fu
12
qemu-img create -f qcow2 -o cluster_size=2k img.qcow2 4G
14
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
qemu-io -c "open -o driver=qcow2,file.align=4k blkdebug::img.qcow2" \
15
Message-Id: <20210920115538.264372-5-vsementsov@virtuozzo.com>
14
-c 'write 0 512'
15
qemu-io: block/io.c:1127: bdrv_driver_pwritev: Assertion `!(flags & BDRV_REQ_NO_FALLBACK)' failed.
16
Aborted
17
18
The reason is that when writing to an unallocated cluster we try to
19
skip the copy-on-write part and zeroize it using BDRV_REQ_NO_FALLBACK
20
instead, resulting in a write request that is too small (2KB cluster
21
size vs 4KB required alignment).
22
23
Signed-off-by: Alberto Garcia <berto@igalia.com>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
---
17
---
26
block/io.c | 7 +++++
18
block.c | 34 ++++++++++++++++++++++++++++------
27
tests/qemu-iotests/268 | 55 ++++++++++++++++++++++++++++++++++++++
19
1 file changed, 28 insertions(+), 6 deletions(-)
28
tests/qemu-iotests/268.out | 7 +++++
29
tests/qemu-iotests/group | 1 +
30
4 files changed, 70 insertions(+)
31
create mode 100755 tests/qemu-iotests/268
32
create mode 100644 tests/qemu-iotests/268.out
33
20
34
diff --git a/block/io.c b/block/io.c
21
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
36
--- a/block/io.c
23
--- a/block.c
37
+++ b/block/io.c
24
+++ b/block.c
38
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
25
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
39
return ret;
26
{
40
}
27
ERRP_GUARD();
41
28
int ret;
42
+ /* If the request is misaligned then we can't make it efficient */
29
- BlockDriverState *new_node_bs;
43
+ if ((flags & BDRV_REQ_NO_FALLBACK) &&
30
+ BlockDriverState *new_node_bs = NULL;
44
+ !QEMU_IS_ALIGNED(offset | bytes, align))
31
+ const char *drvname, *node_name;
45
+ {
32
+ BlockDriver *drv;
46
+ return -ENOTSUP;
33
+
34
+ drvname = qdict_get_try_str(options, "driver");
35
+ if (!drvname) {
36
+ error_setg(errp, "driver is not specified");
37
+ goto fail;
47
+ }
38
+ }
48
+
39
+
49
bdrv_inc_in_flight(bs);
40
+ drv = bdrv_find_format(drvname);
50
/*
41
+ if (!drv) {
51
* Align write if necessary by performing a read-modify-write cycle.
42
+ error_setg(errp, "Unknown driver: '%s'", drvname);
52
diff --git a/tests/qemu-iotests/268 b/tests/qemu-iotests/268
43
+ goto fail;
53
new file mode 100755
44
+ }
54
index XXXXXXX..XXXXXXX
45
55
--- /dev/null
46
- new_node_bs = bdrv_open(NULL, NULL, options, flags, errp);
56
+++ b/tests/qemu-iotests/268
47
- if (new_node_bs == NULL) {
57
@@ -XXX,XX +XXX,XX @@
48
+ node_name = qdict_get_try_str(options, "node-name");
58
+#!/usr/bin/env bash
59
+#
60
+# Test write request with required alignment larger than the cluster size
61
+#
62
+# Copyright (C) 2019 Igalia, S.L.
63
+# Author: Alberto Garcia <berto@igalia.com>
64
+#
65
+# This program is free software; you can redistribute it and/or modify
66
+# it under the terms of the GNU General Public License as published by
67
+# the Free Software Foundation; either version 2 of the License, or
68
+# (at your option) any later version.
69
+#
70
+# This program is distributed in the hope that it will be useful,
71
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
72
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73
+# GNU General Public License for more details.
74
+#
75
+# You should have received a copy of the GNU General Public License
76
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
77
+#
78
+
49
+
79
+# creator
50
+ new_node_bs = bdrv_new_open_driver_opts(drv, node_name, options, flags,
80
+owner=berto@igalia.com
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
}
58
59
bdrv_drained_begin(bs);
60
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
61
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
}
68
69
return new_node_bs;
81
+
70
+
82
+seq=`basename $0`
71
+fail:
83
+echo "QA output created by $seq"
72
+ qobject_unref(options);
84
+
73
+ bdrv_unref(new_node_bs);
85
+status=1    # failure is the default!
74
+ return NULL;
86
+
75
}
87
+_cleanup()
76
88
+{
77
/*
89
+ _cleanup_test_img
90
+}
91
+trap "_cleanup; exit \$status" 0 1 2 3 15
92
+
93
+# get standard environment, filters and checks
94
+. ./common.rc
95
+. ./common.filter
96
+
97
+_supported_fmt qcow2
98
+_supported_proto file
99
+
100
+echo
101
+echo "== Required alignment larger than cluster size =="
102
+
103
+CLUSTER_SIZE=2k _make_test_img 1M
104
+# Since commit c8bb23cbdb writing to an unallocated cluster fills the
105
+# empty COW areas with bdrv_write_zeroes(flags=BDRV_REQ_NO_FALLBACK)
106
+$QEMU_IO -c "open -o driver=$IMGFMT,file.align=4k blkdebug::$TEST_IMG" \
107
+ -c "write 0 512" | _filter_qemu_io
108
+
109
+# success, all done
110
+echo "*** done"
111
+rm -f $seq.full
112
+status=0
113
diff --git a/tests/qemu-iotests/268.out b/tests/qemu-iotests/268.out
114
new file mode 100644
115
index XXXXXXX..XXXXXXX
116
--- /dev/null
117
+++ b/tests/qemu-iotests/268.out
118
@@ -XXX,XX +XXX,XX @@
119
+QA output created by 268
120
+
121
+== Required alignment larger than cluster size ==
122
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
123
+wrote 512/512 bytes at offset 0
124
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
125
+*** done
126
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
127
index XXXXXXX..XXXXXXX 100644
128
--- a/tests/qemu-iotests/group
129
+++ b/tests/qemu-iotests/group
130
@@ -XXX,XX +XXX,XX @@
131
265 rw auto quick
132
266 rw quick
133
267 rw auto quick snapshot
134
+268 rw auto quick
135
--
78
--
136
2.20.1
79
2.31.1
137
80
138
81
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Now test fails if copy-before-write is not white-listed.
4
Let's skip test instead.
5
6
Fixes: c0605985696a19ef034fa25d04f53f3b3b383896
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20210920115538.264372-6-vsementsov@virtuozzo.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
tests/qemu-iotests/tests/image-fleecing | 1 +
12
1 file changed, 1 insertion(+)
13
14
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/tests/image-fleecing
17
+++ b/tests/qemu-iotests/tests/image-fleecing
18
@@ -XXX,XX +XXX,XX @@ from iotests import log, qemu_img, qemu_io, qemu_io_silent
19
iotests.script_initialize(
20
supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk', 'vhdx', 'raw'],
21
supported_platforms=['linux'],
22
+ required_fmts=['copy-before-write'],
23
)
24
25
patterns = [('0x5d', '0', '64k'),
26
--
27
2.31.1
28
29
diff view generated by jsdifflib
1
From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Replay is capable of recording normal BH events, but sometimes
3
Linux limits the size of iovecs to 1024 (UIO_MAXIOV in the kernel
4
there are single use callbacks scheduled with aio_bh_schedule_oneshot
4
sources, IOV_MAX in POSIX). Because of this, on some host adapters
5
function. This patch enables recording and replaying such callbacks.
5
requests with many iovecs are rejected with -EINVAL by the
6
Block layer uses these events for calling the completion function.
6
io_submit() or readv()/writev() system calls.
7
Replaying these calls makes the execution deterministic.
8
7
9
Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
8
In fact, the same limit applies to SG_IO as well. To fix both the
10
Acked-by: Kevin Wolf <kwolf@redhat.com>
9
EINVAL and the possible performance issues from using fewer iovecs
10
than allowed by Linux (some HBAs have max_segments as low as 128),
11
introduce a separate entry in BlockLimits to hold the max_segments
12
value from sysfs. This new limit is used only for SG_IO and clamped
13
to bs->bl.max_iov anyway, just like max_hw_transfer is clamped to
14
bs->bl.max_transfer.
15
16
Reported-by: Halil Pasic <pasic@linux.ibm.com>
17
Cc: Hanna Reitz <hreitz@redhat.com>
18
Cc: Kevin Wolf <kwolf@redhat.com>
19
Cc: qemu-block@nongnu.org
20
Cc: qemu-stable@nongnu.org
21
Fixes: 18473467d5 ("file-posix: try BLKSECTGET on block devices too, do not round to power of 2", 2021-06-25)
22
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
23
Message-Id: <20210923130436.1187591-1-pbonzini@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
25
---
13
include/sysemu/replay.h | 4 ++++
26
include/block/block_int.h | 7 +++++++
14
replay/replay-internal.h | 1 +
27
include/sysemu/block-backend.h | 1 +
15
block/block-backend.c | 9 ++++++---
28
block/block-backend.c | 6 ++++++
16
block/io.c | 4 ++--
29
block/file-posix.c | 2 +-
17
block/iscsi.c | 5 +++--
30
block/io.c | 1 +
18
block/nfs.c | 6 ++++--
31
hw/scsi/scsi-generic.c | 2 +-
19
block/null.c | 4 +++-
32
6 files changed, 17 insertions(+), 2 deletions(-)
20
block/nvme.c | 6 ++++--
21
block/rbd.c | 5 +++--
22
block/vxhs.c | 5 +++--
23
replay/replay-events.c | 16 ++++++++++++++++
24
stubs/replay-user.c | 9 +++++++++
25
stubs/Makefile.objs | 1 +
26
13 files changed, 59 insertions(+), 16 deletions(-)
27
create mode 100644 stubs/replay-user.c
28
33
29
diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
34
diff --git a/include/block/block_int.h b/include/block/block_int.h
30
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
31
--- a/include/sysemu/replay.h
36
--- a/include/block/block_int.h
32
+++ b/include/sysemu/replay.h
37
+++ b/include/block/block_int.h
33
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@ typedef struct BlockLimits {
34
#include "qapi/qapi-types-misc.h"
39
*/
35
#include "qapi/qapi-types-run-state.h"
40
uint64_t max_hw_transfer;
36
#include "qapi/qapi-types-ui.h"
41
37
+#include "block/aio.h"
42
+ /* Maximal number of scatter/gather elements allowed by the hardware.
38
43
+ * Applies whenever transfers to the device bypass the kernel I/O
39
/* replay clock kinds */
44
+ * scheduler, for example with SG_IO. If larger than max_iov
40
enum ReplayClockKind {
45
+ * or if zero, blk_get_max_hw_iov will fall back to max_iov.
41
@@ -XXX,XX +XXX,XX @@ void replay_enable_events(void);
46
+ */
42
bool replay_events_enabled(void);
47
+ int max_hw_iov;
43
/*! Adds bottom half event to the queue */
48
+
44
void replay_bh_schedule_event(QEMUBH *bh);
49
/* memory alignment, in bytes so that no bounce buffer is needed */
45
+/* Adds oneshot bottom half event to the queue */
50
size_t min_mem_alignment;
46
+void replay_bh_schedule_oneshot_event(AioContext *ctx,
51
47
+ QEMUBHFunc *cb, void *opaque);
52
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
48
/*! Adds input event to the queue */
49
void replay_input_event(QemuConsole *src, InputEvent *evt);
50
/*! Adds input sync event to the queue */
51
diff --git a/replay/replay-internal.h b/replay/replay-internal.h
52
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
53
--- a/replay/replay-internal.h
54
--- a/include/sysemu/block-backend.h
54
+++ b/replay/replay-internal.h
55
+++ b/include/sysemu/block-backend.h
55
@@ -XXX,XX +XXX,XX @@ enum ReplayEvents {
56
@@ -XXX,XX +XXX,XX @@ uint32_t blk_get_request_alignment(BlockBackend *blk);
56
57
uint32_t blk_get_max_transfer(BlockBackend *blk);
57
enum ReplayAsyncEventKind {
58
uint64_t blk_get_max_hw_transfer(BlockBackend *blk);
58
REPLAY_ASYNC_EVENT_BH,
59
int blk_get_max_iov(BlockBackend *blk);
59
+ REPLAY_ASYNC_EVENT_BH_ONESHOT,
60
+int blk_get_max_hw_iov(BlockBackend *blk);
60
REPLAY_ASYNC_EVENT_INPUT,
61
void blk_set_guest_block_size(BlockBackend *blk, int align);
61
REPLAY_ASYNC_EVENT_INPUT_SYNC,
62
void *blk_try_blockalign(BlockBackend *blk, size_t size);
62
REPLAY_ASYNC_EVENT_CHAR_READ,
63
void *blk_blockalign(BlockBackend *blk, size_t size);
63
diff --git a/block/block-backend.c b/block/block-backend.c
64
diff --git a/block/block-backend.c b/block/block-backend.c
64
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
65
--- a/block/block-backend.c
66
--- a/block/block-backend.c
66
+++ b/block/block-backend.c
67
+++ b/block/block-backend.c
67
@@ -XXX,XX +XXX,XX @@
68
@@ -XXX,XX +XXX,XX @@ uint32_t blk_get_max_transfer(BlockBackend *blk)
68
#include "hw/qdev-core.h"
69
return ROUND_DOWN(max, blk_get_request_alignment(blk));
69
#include "sysemu/blockdev.h"
70
#include "sysemu/runstate.h"
71
+#include "sysemu/sysemu.h"
72
+#include "sysemu/replay.h"
73
#include "qapi/error.h"
74
#include "qapi/qapi-events-block.h"
75
#include "qemu/id.h"
76
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
77
acb->blk = blk;
78
acb->ret = ret;
79
80
- aio_bh_schedule_oneshot(blk_get_aio_context(blk), error_callback_bh, acb);
81
+ replay_bh_schedule_oneshot_event(blk_get_aio_context(blk),
82
+ error_callback_bh, acb);
83
return &acb->common;
84
}
70
}
85
71
86
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
72
+int blk_get_max_hw_iov(BlockBackend *blk)
87
73
+{
88
acb->has_returned = true;
74
+ return MIN_NON_ZERO(blk->root->bs->bl.max_hw_iov,
89
if (acb->rwco.ret != NOT_DONE) {
75
+ blk->root->bs->bl.max_iov);
90
- aio_bh_schedule_oneshot(blk_get_aio_context(blk),
76
+}
91
- blk_aio_complete_bh, acb);
77
+
92
+ replay_bh_schedule_oneshot_event(blk_get_aio_context(blk),
78
int blk_get_max_iov(BlockBackend *blk)
93
+ blk_aio_complete_bh, acb);
79
{
80
return blk->root->bs->bl.max_iov;
81
diff --git a/block/file-posix.c b/block/file-posix.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/block/file-posix.c
84
+++ b/block/file-posix.c
85
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
86
87
ret = hdev_get_max_segments(s->fd, &st);
88
if (ret > 0) {
89
- bs->bl.max_iov = ret;
90
+ bs->bl.max_hw_iov = ret;
91
}
94
}
92
}
95
93
}
96
return &acb->common;
97
diff --git a/block/io.c b/block/io.c
94
diff --git a/block/io.c b/block/io.c
98
index XXXXXXX..XXXXXXX 100644
95
index XXXXXXX..XXXXXXX 100644
99
--- a/block/io.c
96
--- a/block/io.c
100
+++ b/block/io.c
97
+++ b/block/io.c
101
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
98
@@ -XXX,XX +XXX,XX @@ static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
102
if (bs) {
99
dst->min_mem_alignment = MAX(dst->min_mem_alignment,
103
bdrv_inc_in_flight(bs);
100
src->min_mem_alignment);
104
}
101
dst->max_iov = MIN_NON_ZERO(dst->max_iov, src->max_iov);
105
- aio_bh_schedule_oneshot(bdrv_get_aio_context(bs),
102
+ dst->max_hw_iov = MIN_NON_ZERO(dst->max_hw_iov, src->max_hw_iov);
106
- bdrv_co_drain_bh_cb, &data);
103
}
107
+ replay_bh_schedule_oneshot_event(bdrv_get_aio_context(bs),
104
108
+ bdrv_co_drain_bh_cb, &data);
105
typedef struct BdrvRefreshLimitsState {
109
106
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
110
qemu_coroutine_yield();
111
/* If we are resumed from some other event (such as an aio completion or a
112
diff --git a/block/iscsi.c b/block/iscsi.c
113
index XXXXXXX..XXXXXXX 100644
107
index XXXXXXX..XXXXXXX 100644
114
--- a/block/iscsi.c
108
--- a/hw/scsi/scsi-generic.c
115
+++ b/block/iscsi.c
109
+++ b/hw/scsi/scsi-generic.c
116
@@ -XXX,XX +XXX,XX @@
110
@@ -XXX,XX +XXX,XX @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len)
117
#include "qemu/module.h"
111
page = r->req.cmd.buf[2];
118
#include "qemu/option.h"
112
if (page == 0xb0) {
119
#include "qemu/uuid.h"
113
uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk);
120
+#include "sysemu/replay.h"
114
- uint32_t max_iov = blk_get_max_iov(s->conf.blk);
121
#include "qapi/error.h"
115
+ uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk);
122
#include "qapi/qapi-commands-misc.h"
116
123
#include "qapi/qmp/qdict.h"
117
assert(max_transfer);
124
@@ -XXX,XX +XXX,XX @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
118
max_transfer = MIN_NON_ZERO(max_transfer, max_iov * qemu_real_host_page_size)
125
}
126
127
if (iTask->co) {
128
- aio_bh_schedule_oneshot(iTask->iscsilun->aio_context,
129
- iscsi_co_generic_bh_cb, iTask);
130
+ replay_bh_schedule_oneshot_event(iTask->iscsilun->aio_context,
131
+ iscsi_co_generic_bh_cb, iTask);
132
} else {
133
iTask->complete = 1;
134
}
135
diff --git a/block/nfs.c b/block/nfs.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/block/nfs.c
138
+++ b/block/nfs.c
139
@@ -XXX,XX +XXX,XX @@
140
#include "qemu/option.h"
141
#include "qemu/uri.h"
142
#include "qemu/cutils.h"
143
+#include "sysemu/sysemu.h"
144
+#include "sysemu/replay.h"
145
#include "qapi/qapi-visit-block-core.h"
146
#include "qapi/qmp/qdict.h"
147
#include "qapi/qmp/qstring.h"
148
@@ -XXX,XX +XXX,XX @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
149
if (task->ret < 0) {
150
error_report("NFS Error: %s", nfs_get_error(nfs));
151
}
152
- aio_bh_schedule_oneshot(task->client->aio_context,
153
- nfs_co_generic_bh_cb, task);
154
+ replay_bh_schedule_oneshot_event(task->client->aio_context,
155
+ nfs_co_generic_bh_cb, task);
156
}
157
158
static int coroutine_fn nfs_co_preadv(BlockDriverState *bs, uint64_t offset,
159
diff --git a/block/null.c b/block/null.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/null.c
162
+++ b/block/null.c
163
@@ -XXX,XX +XXX,XX @@
164
#include "qemu/module.h"
165
#include "qemu/option.h"
166
#include "block/block_int.h"
167
+#include "sysemu/replay.h"
168
169
#define NULL_OPT_LATENCY "latency-ns"
170
#define NULL_OPT_ZEROES "read-zeroes"
171
@@ -XXX,XX +XXX,XX @@ static inline BlockAIOCB *null_aio_common(BlockDriverState *bs,
172
timer_mod_ns(&acb->timer,
173
qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + s->latency_ns);
174
} else {
175
- aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), null_bh_cb, acb);
176
+ replay_bh_schedule_oneshot_event(bdrv_get_aio_context(bs),
177
+ null_bh_cb, acb);
178
}
179
return &acb->common;
180
}
181
diff --git a/block/nvme.c b/block/nvme.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/block/nvme.c
184
+++ b/block/nvme.c
185
@@ -XXX,XX +XXX,XX @@
186
#include "qemu/option.h"
187
#include "qemu/vfio-helpers.h"
188
#include "block/block_int.h"
189
+#include "sysemu/replay.h"
190
#include "trace.h"
191
192
#include "block/nvme.h"
193
@@ -XXX,XX +XXX,XX @@ static bool nvme_process_completion(BDRVNVMeState *s, NVMeQueuePair *q)
194
smp_mb_release();
195
*q->cq.doorbell = cpu_to_le32(q->cq.head);
196
if (!qemu_co_queue_empty(&q->free_req_queue)) {
197
- aio_bh_schedule_oneshot(s->aio_context, nvme_free_req_queue_cb, q);
198
+ replay_bh_schedule_oneshot_event(s->aio_context,
199
+ nvme_free_req_queue_cb, q);
200
}
201
}
202
q->busy = false;
203
@@ -XXX,XX +XXX,XX @@ static void nvme_rw_cb(void *opaque, int ret)
204
/* The rw coroutine hasn't yielded, don't try to enter. */
205
return;
206
}
207
- aio_bh_schedule_oneshot(data->ctx, nvme_rw_cb_bh, data);
208
+ replay_bh_schedule_oneshot_event(data->ctx, nvme_rw_cb_bh, data);
209
}
210
211
static coroutine_fn int nvme_co_prw_aligned(BlockDriverState *bs,
212
diff --git a/block/rbd.c b/block/rbd.c
213
index XXXXXXX..XXXXXXX 100644
214
--- a/block/rbd.c
215
+++ b/block/rbd.c
216
@@ -XXX,XX +XXX,XX @@
217
#include "block/qdict.h"
218
#include "crypto/secret.h"
219
#include "qemu/cutils.h"
220
+#include "sysemu/replay.h"
221
#include "qapi/qmp/qstring.h"
222
#include "qapi/qmp/qdict.h"
223
#include "qapi/qmp/qjson.h"
224
@@ -XXX,XX +XXX,XX @@ static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb)
225
rcb->ret = rbd_aio_get_return_value(c);
226
rbd_aio_release(c);
227
228
- aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
229
- rbd_finish_bh, rcb);
230
+ replay_bh_schedule_oneshot_event(bdrv_get_aio_context(acb->common.bs),
231
+ rbd_finish_bh, rcb);
232
}
233
234
static int rbd_aio_discard_wrapper(rbd_image_t image,
235
diff --git a/block/vxhs.c b/block/vxhs.c
236
index XXXXXXX..XXXXXXX 100644
237
--- a/block/vxhs.c
238
+++ b/block/vxhs.c
239
@@ -XXX,XX +XXX,XX @@
240
#include "qapi/error.h"
241
#include "qemu/uuid.h"
242
#include "crypto/tlscredsx509.h"
243
+#include "sysemu/replay.h"
244
245
#define VXHS_OPT_FILENAME "filename"
246
#define VXHS_OPT_VDISK_ID "vdisk-id"
247
@@ -XXX,XX +XXX,XX @@ static void vxhs_iio_callback(void *ctx, uint32_t opcode, uint32_t error)
248
trace_vxhs_iio_callback(error);
249
}
250
251
- aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
252
- vxhs_complete_aio_bh, acb);
253
+ replay_bh_schedule_oneshot_event(bdrv_get_aio_context(acb->common.bs),
254
+ vxhs_complete_aio_bh, acb);
255
break;
256
257
default:
258
diff --git a/replay/replay-events.c b/replay/replay-events.c
259
index XXXXXXX..XXXXXXX 100644
260
--- a/replay/replay-events.c
261
+++ b/replay/replay-events.c
262
@@ -XXX,XX +XXX,XX @@ static void replay_run_event(Event *event)
263
case REPLAY_ASYNC_EVENT_BH:
264
aio_bh_call(event->opaque);
265
break;
266
+ case REPLAY_ASYNC_EVENT_BH_ONESHOT:
267
+ ((QEMUBHFunc *)event->opaque)(event->opaque2);
268
+ break;
269
case REPLAY_ASYNC_EVENT_INPUT:
270
qemu_input_event_send_impl(NULL, (InputEvent *)event->opaque);
271
qapi_free_InputEvent((InputEvent *)event->opaque);
272
@@ -XXX,XX +XXX,XX @@ void replay_bh_schedule_event(QEMUBH *bh)
273
}
274
}
275
276
+void replay_bh_schedule_oneshot_event(AioContext *ctx,
277
+ QEMUBHFunc *cb, void *opaque)
278
+{
279
+ if (events_enabled) {
280
+ uint64_t id = replay_get_current_icount();
281
+ replay_add_event(REPLAY_ASYNC_EVENT_BH_ONESHOT, cb, opaque, id);
282
+ } else {
283
+ aio_bh_schedule_oneshot(ctx, cb, opaque);
284
+ }
285
+}
286
+
287
void replay_add_input_event(struct InputEvent *event)
288
{
289
replay_add_event(REPLAY_ASYNC_EVENT_INPUT, event, NULL, 0);
290
@@ -XXX,XX +XXX,XX @@ static void replay_save_event(Event *event, int checkpoint)
291
/* save event-specific data */
292
switch (event->event_kind) {
293
case REPLAY_ASYNC_EVENT_BH:
294
+ case REPLAY_ASYNC_EVENT_BH_ONESHOT:
295
replay_put_qword(event->id);
296
break;
297
case REPLAY_ASYNC_EVENT_INPUT:
298
@@ -XXX,XX +XXX,XX @@ static Event *replay_read_event(int checkpoint)
299
/* Events that has not to be in the queue */
300
switch (replay_state.read_event_kind) {
301
case REPLAY_ASYNC_EVENT_BH:
302
+ case REPLAY_ASYNC_EVENT_BH_ONESHOT:
303
if (replay_state.read_event_id == -1) {
304
replay_state.read_event_id = replay_get_qword();
305
}
306
diff --git a/stubs/replay-user.c b/stubs/replay-user.c
307
new file mode 100644
308
index XXXXXXX..XXXXXXX
309
--- /dev/null
310
+++ b/stubs/replay-user.c
311
@@ -XXX,XX +XXX,XX @@
312
+#include "qemu/osdep.h"
313
+#include "sysemu/replay.h"
314
+#include "sysemu/sysemu.h"
315
+
316
+void replay_bh_schedule_oneshot_event(AioContext *ctx,
317
+ QEMUBHFunc *cb, void *opaque)
318
+{
319
+ aio_bh_schedule_oneshot(ctx, cb, opaque);
320
+}
321
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
322
index XXXXXXX..XXXXXXX 100644
323
--- a/stubs/Makefile.objs
324
+++ b/stubs/Makefile.objs
325
@@ -XXX,XX +XXX,XX @@ stub-obj-y += monitor.o
326
stub-obj-y += notify-event.o
327
stub-obj-y += qtest.o
328
stub-obj-y += replay.o
329
+stub-obj-y += replay-user.o
330
stub-obj-y += runstate-check.o
331
stub-obj-y += set-fd-handler.o
332
stub-obj-y += sysbus.o
333
--
119
--
334
2.20.1
120
2.31.1
335
121
336
122
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
For long test image paths, the order of the "Formatting" line and the
3
We can drop the sys.path hacking in various places by doing
4
"(qemu)" prompt after a drive_backup HMP command may be reversed. In
4
this. Additionally, by doing it in one place right up top, we can print
5
fact, the interaction between the prompt and the line may lead to the
5
interesting warnings in case the environment does not look correct. (See
6
"Formatting" to being greppable at all after "read"-ing it (if the
6
next commit.)
7
prompt injects an IFS character into the "Formatting" string).
8
7
9
So just wait until we get a prompt. At that point, the block job must
8
If we ever decide to change how the environment is crafted, all of the
10
have been started, so "info block-jobs" will only return "No active
9
"help me find my python packages" goop is all in one place, right in one
11
jobs" once it is done.
10
function.
12
11
13
Reported-by: Thomas Huth <thuth@redhat.com>
12
Signed-off-by: John Snow <jsnow@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Reviewed-by: John Snow <jsnow@redhat.com>
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
16
Message-Id: <20210923180715.4168522-2-jsnow@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
---
18
tests/qemu-iotests/028 | 11 ++++++++---
19
tests/qemu-iotests/iotests.py | 2 --
19
tests/qemu-iotests/028.out | 1 -
20
tests/qemu-iotests/testenv.py | 15 +++++++++------
20
2 files changed, 8 insertions(+), 4 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(-)
21
26
22
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
27
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
28
index XXXXXXX..XXXXXXX 100644
29
--- a/tests/qemu-iotests/iotests.py
30
+++ b/tests/qemu-iotests/iotests.py
31
@@ -XXX,XX +XXX,XX @@
32
33
from contextlib import contextmanager
34
35
-# pylint: disable=import-error, wrong-import-position
36
-sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
37
from qemu.machine import qtest
38
from qemu.qmp import QMPMessage
39
40
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
41
index XXXXXXX..XXXXXXX 100644
42
--- a/tests/qemu-iotests/testenv.py
43
+++ b/tests/qemu-iotests/testenv.py
44
@@ -XXX,XX +XXX,XX @@ def init_directories(self) -> None:
45
SAMPLE_IMG_DIR
46
OUTPUT_DIR
47
"""
48
- self.pythonpath = os.getenv('PYTHONPATH')
49
- if self.pythonpath:
50
- self.pythonpath = self.source_iotests + os.pathsep + \
51
- self.pythonpath
52
- else:
53
- self.pythonpath = self.source_iotests
54
+
55
+ # Path where qemu goodies live in this source tree.
56
+ qemu_srctree_path = Path(__file__, '../../../python').resolve()
57
+
58
+ self.pythonpath = os.pathsep.join(filter(None, (
59
+ self.source_iotests,
60
+ str(qemu_srctree_path),
61
+ os.getenv('PYTHONPATH'),
62
+ )))
63
64
self.test_dir = os.getenv('TEST_DIR',
65
os.path.join(os.getcwd(), 'scratch'))
66
diff --git a/tests/qemu-iotests/235 b/tests/qemu-iotests/235
23
index XXXXXXX..XXXXXXX 100755
67
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/028
68
--- a/tests/qemu-iotests/235
25
+++ b/tests/qemu-iotests/028
69
+++ b/tests/qemu-iotests/235
26
@@ -XXX,XX +XXX,XX @@ fi
70
@@ -XXX,XX +XXX,XX @@ import os
27
# Silence output since it contains the disk image path and QEMU's readline
71
import iotests
28
# character echoing makes it very hard to filter the output. Plus, there
72
from iotests import qemu_img_create, qemu_io, file_path, log
29
# is no telling how many times the command will repeat before succeeding.
73
30
-_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)" >/dev/null
74
-sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
31
-_send_qemu_cmd $h "" "Formatting" | _filter_img_create
75
-
32
-qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs" >/dev/null
76
from qemu.machine import QEMUMachine
33
+# (Note that creating the image results in a "Formatting..." message over
77
34
+# stdout, which is the same channel the monitor uses. We cannot reliably
78
iotests.script_initialize(supported_fmts=['qcow2'])
35
+# wait for it because the monitor output may interact with it in such a
79
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
36
+# way that _timed_wait_for cannot read it. However, once the block job is
80
index XXXXXXX..XXXXXXX 100755
37
+# done, we know that the "Formatting..." message must have appeared
81
--- a/tests/qemu-iotests/297
38
+# already, so the output is still deterministic.)
82
+++ b/tests/qemu-iotests/297
39
+silent=y _send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)"
83
@@ -XXX,XX +XXX,XX @@ def run_linters():
40
+silent=y qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
84
# Todo notes are fine, but fixme's or xxx's should probably just be
41
_send_qemu_cmd $h "info block-jobs" "No active jobs"
85
# fixed (in tests, at least)
42
_send_qemu_cmd $h 'quit' ""
86
env = os.environ.copy()
43
87
- qemu_module_path = os.path.join(os.path.dirname(__file__),
44
diff --git a/tests/qemu-iotests/028.out b/tests/qemu-iotests/028.out
88
- '..', '..', 'python')
45
index XXXXXXX..XXXXXXX 100644
89
- try:
46
--- a/tests/qemu-iotests/028.out
90
- env['PYTHONPATH'] += os.pathsep + qemu_module_path
47
+++ b/tests/qemu-iotests/028.out
91
- except KeyError:
48
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
92
- env['PYTHONPATH'] = qemu_module_path
49
93
subprocess.run(('pylint-3', '--score=n', '--notes=FIXME,XXX', *files),
50
block-backup
94
env=env, check=False)
51
95
52
-Formatting 'TEST_DIR/t.IMGFMT.copy', fmt=IMGFMT size=4294968832 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT
96
diff --git a/tests/qemu-iotests/300 b/tests/qemu-iotests/300
53
(qemu) info block-jobs
97
index XXXXXXX..XXXXXXX 100755
54
No active jobs
98
--- a/tests/qemu-iotests/300
55
=== IO: pattern 195
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
+
106
import iotests
107
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')
56
--
135
--
57
2.20.1
136
2.31.1
58
137
59
138
diff view generated by jsdifflib
1
From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
1
From: John Snow <jsnow@redhat.com>
2
2
3
After recent updates block devices cannot be closed on qemu exit.
3
We can circumvent the '__main__' redefinition problem by passing
4
This happens due to the block request polling when replay is not finished.
4
--scripts-are-modules. Take mypy out of the loop per-filename and check
5
Therefore now we stop execution recording before closing the block devices.
5
everything in one go: it's quite a bit faster.
6
6
7
Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
7
Signed-off-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Message-Id: <20210923180715.4168522-4-jsnow@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
14
---
10
replay/replay.c | 2 ++
15
tests/qemu-iotests/297 | 46 +++++++++++++++++++-----------------------
11
vl.c | 1 +
16
1 file changed, 21 insertions(+), 25 deletions(-)
12
2 files changed, 3 insertions(+)
13
17
14
diff --git a/replay/replay.c b/replay/replay.c
18
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100755
16
--- a/replay/replay.c
20
--- a/tests/qemu-iotests/297
17
+++ b/replay/replay.c
21
+++ b/tests/qemu-iotests/297
18
@@ -XXX,XX +XXX,XX @@ void replay_finish(void)
22
@@ -XXX,XX +XXX,XX @@ def run_linters():
19
g_free(replay_snapshot);
23
print('=== mypy ===')
20
replay_snapshot = NULL;
24
sys.stdout.flush()
21
25
22
+ replay_mode = REPLAY_MODE_NONE;
26
- # We have to call mypy separately for each file. Otherwise, it
27
- # will interpret all given files as belonging together (i.e., they
28
- # may not both define the same classes, etc.; most notably, they
29
- # must not both define the __main__ module).
30
env['MYPYPATH'] = env['PYTHONPATH']
31
- for filename in files:
32
- p = subprocess.run(('mypy',
33
- '--warn-unused-configs',
34
- '--disallow-subclassing-any',
35
- '--disallow-any-generics',
36
- '--disallow-incomplete-defs',
37
- '--disallow-untyped-decorators',
38
- '--no-implicit-optional',
39
- '--warn-redundant-casts',
40
- '--warn-unused-ignores',
41
- '--no-implicit-reexport',
42
- '--namespace-packages',
43
- filename),
44
- env=env,
45
- check=False,
46
- stdout=subprocess.PIPE,
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)
23
+
70
+
24
replay_finish_events();
71
+ if p.returncode != 0:
25
}
72
+ print(p.stdout)
26
73
27
diff --git a/vl.c b/vl.c
74
28
index XXXXXXX..XXXXXXX 100644
75
for linter in ('pylint-3', 'mypy'):
29
--- a/vl.c
30
+++ b/vl.c
31
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
32
33
/* No more vcpu or device emulation activity beyond this point */
34
vm_shutdown();
35
+ replay_finish();
36
37
job_cancel_sync_all();
38
bdrv_close_all();
39
--
76
--
40
2.20.1
77
2.31.1
41
78
42
79
diff view generated by jsdifflib
1
From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
1
From: John Snow <jsnow@redhat.com>
2
2
3
This patch updates the description of the command lines for using
3
We need to import subpackages from the qemu namespace package; importing
4
record/replay with attached block devices.
4
the namespace package alone doesn't bring the subpackages with it --
5
unless someone else (like iotests.py) imports them too.
5
6
6
Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
7
Adjust the imports.
8
9
Signed-off-by: John Snow <jsnow@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Message-Id: <20210923180715.4168522-5-jsnow@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
16
---
9
docs/replay.txt | 12 +++++++++---
17
tests/qemu-iotests/tests/mirror-top-perms | 7 ++++---
10
1 file changed, 9 insertions(+), 3 deletions(-)
18
1 file changed, 4 insertions(+), 3 deletions(-)
11
19
12
diff --git a/docs/replay.txt b/docs/replay.txt
20
diff --git a/tests/qemu-iotests/tests/mirror-top-perms b/tests/qemu-iotests/tests/mirror-top-perms
13
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100755
14
--- a/docs/replay.txt
22
--- a/tests/qemu-iotests/tests/mirror-top-perms
15
+++ b/docs/replay.txt
23
+++ b/tests/qemu-iotests/tests/mirror-top-perms
16
@@ -XXX,XX +XXX,XX @@ Usage of the record/replay:
24
@@ -XXX,XX +XXX,XX @@
17
* First, record the execution with the following command line:
25
18
qemu-system-i386 \
26
import os
19
-icount shift=7,rr=record,rrfile=replay.bin \
27
20
- -drive file=disk.qcow2,if=none,id=img-direct \
28
-import qemu
21
+ -drive file=disk.qcow2,if=none,snapshot,id=img-direct \
29
+from qemu import qmp
22
-drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay \
30
+from qemu.machine import machine
23
-device ide-hd,drive=img-blkreplay \
31
24
-netdev user,id=net1 -device rtl8139,netdev=net1 \
32
import iotests
25
@@ -XXX,XX +XXX,XX @@ Usage of the record/replay:
33
from iotests import qemu_img
26
* After recording, you can replay it by using another command line:
34
@@ -XXX,XX +XXX,XX @@ class TestMirrorTopPerms(iotests.QMPTestCase):
27
qemu-system-i386 \
35
def tearDown(self):
28
-icount shift=7,rr=replay,rrfile=replay.bin \
36
try:
29
- -drive file=disk.qcow2,if=none,id=img-direct \
37
self.vm.shutdown()
30
+ -drive file=disk.qcow2,if=none,snapshot,id=img-direct \
38
- except qemu.machine.machine.AbnormalShutdown:
31
-drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay \
39
+ except machine.AbnormalShutdown:
32
-device ide-hd,drive=img-blkreplay \
40
pass
33
-netdev user,id=net1 -device rtl8139,netdev=net1 \
41
34
@@ -XXX,XX +XXX,XX @@ Block devices record/replay module intercepts calls of
42
if self.vm_b is not None:
35
bdrv coroutine functions at the top of block drivers stack.
43
@@ -XXX,XX +XXX,XX @@ class TestMirrorTopPerms(iotests.QMPTestCase):
36
To record and replay block operations the drive must be configured
44
self.vm_b.launch()
37
as following:
45
print('ERROR: VM B launched successfully, this should not have '
38
- -drive file=disk.qcow2,if=none,id=img-direct
46
'happened')
39
+ -drive file=disk.qcow2,if=none,snapshot,id=img-direct
47
- except qemu.qmp.QMPConnectError:
40
-drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay
48
+ except qmp.QMPConnectError:
41
-device ide-hd,drive=img-blkreplay
49
assert 'Is another process using the image' in self.vm_b.get_log()
42
50
43
@@ -XXX,XX +XXX,XX @@ This snapshot is created at start of recording and restored at start
51
result = self.vm.qmp('block-job-cancel',
44
of replaying. It also can be loaded while replaying to roll back
45
the execution.
46
47
+'snapshot' flag of the disk image must be removed to save the snapshots
48
+in the overlay (or original image) instead of using the temporary overlay.
49
+ -drive file=disk.ovl,if=none,id=img-direct
50
+ -drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay
51
+ -device ide-hd,drive=img-blkreplay
52
+
53
Use QEMU monitor to create additional snapshots. 'savevm <name>' command
54
created the snapshot and 'loadvm <name>' restores it. To prevent corruption
55
of the original disk image, use overlay files linked to the original images.
56
--
52
--
57
2.20.1
53
2.31.1
58
54
59
55
diff view generated by jsdifflib
1
From: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
1
From: John Snow <jsnow@redhat.com>
2
2
3
This patch disables setting '-snapshot' option on by default
3
Mostly uninteresting stuff. Move the test injections under a function
4
in record/replay mode. This is needed for creating vmstates in record
4
named main() so that the variables used during that process aren't in
5
and replay modes.
5
the global scope.
6
6
7
Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
7
Signed-off-by: John Snow <jsnow@redhat.com>
8
Acked-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Message-Id: <20210923180715.4168522-6-jsnow@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
14
---
11
vl.c | 10 ++++++++--
15
tests/qemu-iotests/tests/migrate-bitmaps-test | 50 +++++++++++--------
12
1 file changed, 8 insertions(+), 2 deletions(-)
16
1 file changed, 28 insertions(+), 22 deletions(-)
13
17
14
diff --git a/vl.c b/vl.c
18
diff --git a/tests/qemu-iotests/tests/migrate-bitmaps-test b/tests/qemu-iotests/tests/migrate-bitmaps-test
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100755
16
--- a/vl.c
20
--- a/tests/qemu-iotests/tests/migrate-bitmaps-test
17
+++ b/vl.c
21
+++ b/tests/qemu-iotests/tests/migrate-bitmaps-test
18
@@ -XXX,XX +XXX,XX @@ static void configure_blockdev(BlockdevOptionsQueue *bdo_queue,
22
@@ -XXX,XX +XXX,XX @@
19
qapi_free_BlockdevOptions(bdo->bdo);
23
# along with this program. If not, see <http://www.gnu.org/licenses/>.
20
g_free(bdo);
24
#
21
}
25
22
- if (snapshot || replay_mode != REPLAY_MODE_NONE) {
26
-import os
23
+ if (snapshot) {
27
import itertools
24
qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot,
28
import operator
25
NULL, NULL);
29
+import os
26
}
30
import re
27
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
31
+
28
drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS);
32
import iotests
29
break;
33
from iotests import qemu_img, qemu_img_create, Timeout
30
case QEMU_OPTION_snapshot:
34
31
- snapshot = 1;
35
@@ -XXX,XX +XXX,XX @@ def inject_test_case(klass, suffix, method, *args, **kwargs):
32
+ {
36
setattr(klass, 'test_' + method + suffix, lambda self: mc(self))
33
+ Error *blocker = NULL;
37
34
+ snapshot = 1;
38
35
+ error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED,
39
-for cmb in list(itertools.product((True, False), repeat=5)):
36
+ "-snapshot");
40
- name = ('_' if cmb[0] else '_not_') + 'persistent_'
37
+ replay_add_blocker(blocker);
41
- name += ('_' if cmb[1] else '_not_') + 'migbitmap_'
38
+ }
42
- name += '_online' if cmb[2] else '_offline'
39
break;
43
- name += '_shared' if cmb[3] else '_nonshared'
40
case QEMU_OPTION_numa:
44
- if cmb[4]:
41
opts = qemu_opts_parse_noisily(qemu_find_opts("numa"),
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
+
89
+
90
if __name__ == '__main__':
91
- iotests.main(supported_fmts=['qcow2'],
92
- supported_protocols=['file'])
93
+ main()
42
--
94
--
43
2.20.1
95
2.31.1
44
96
45
97
diff view generated by jsdifflib
1
From: Peter Lieven <pl@kamp.de>
1
From: John Snow <jsnow@redhat.com>
2
2
3
qemu is currently not able to detect truncated vhdx image files.
3
1. Ignore the new f-strings warning, we're not interested in doing a
4
Add a basic check if all allocated blocks are reachable at open and
4
full conversion at this time.
5
report all errors during bdrv_co_check.
6
5
7
Signed-off-by: Peter Lieven <pl@kamp.de>
6
2. Just mute the unbalanced-tuple-unpacking warning, it's not a real
7
error in this case and muting the dozens of callsites is just not
8
worth it.
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>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
17
---
10
block/vhdx.c | 120 +++++++++++++++++++++++++++++++++++++++++++--------
18
tests/qemu-iotests/testrunner.py | 7 ++++---
11
1 file changed, 103 insertions(+), 17 deletions(-)
19
tests/qemu-iotests/pylintrc | 6 +++++-
20
2 files changed, 9 insertions(+), 4 deletions(-)
12
21
13
diff --git a/block/vhdx.c b/block/vhdx.c
22
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
14
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
15
--- a/block/vhdx.c
24
--- a/tests/qemu-iotests/testrunner.py
16
+++ b/block/vhdx.c
25
+++ b/tests/qemu-iotests/testrunner.py
17
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ def do_run_test(self, test: str) -> TestResult:
18
#include "qemu/option.h"
27
diff=file_diff(str(f_reference), str(f_bad)))
19
#include "qemu/crc32c.h"
28
20
#include "qemu/bswap.h"
29
if f_notrun.exists():
21
+#include "qemu/error-report.h"
30
- return TestResult(status='not run',
22
#include "vhdx.h"
31
- description=f_notrun.read_text().strip())
23
#include "migration/blocker.h"
32
+ return TestResult(
24
#include "qemu/uuid.h"
33
+ status='not run',
25
@@ -XXX,XX +XXX,XX @@ static int vhdx_region_check(BDRVVHDXState *s, uint64_t start, uint64_t length)
34
+ description=f_notrun.read_text(encoding='utf-8').strip())
26
end = start + length;
35
27
QLIST_FOREACH(r, &s->regions, entries) {
36
casenotrun = ''
28
if (!((start >= r->end) || (end <= r->start))) {
37
if f_casenotrun.exists():
29
+ error_report("VHDX region %" PRIu64 "-%" PRIu64 " overlaps with "
38
- casenotrun = f_casenotrun.read_text()
30
+ "region %" PRIu64 "-%." PRIu64, start, end, r->start,
39
+ casenotrun = f_casenotrun.read_text(encoding='utf-8')
31
+ r->end);
40
32
ret = -EINVAL;
41
diff = file_diff(str(f_reference), str(f_bad))
33
goto exit;
42
if diff:
34
}
43
diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc
35
@@ -XXX,XX +XXX,XX @@ static void vhdx_calc_bat_entries(BDRVVHDXState *s)
44
index XXXXXXX..XXXXXXX 100644
36
45
--- a/tests/qemu-iotests/pylintrc
37
}
46
+++ b/tests/qemu-iotests/pylintrc
38
47
@@ -XXX,XX +XXX,XX @@ disable=invalid-name,
39
+static int vhdx_check_bat_entries(BlockDriverState *bs, int *errcnt)
48
too-many-public-methods,
40
+{
49
# pylint warns about Optional[] etc. as unsubscriptable in 3.9
41
+ BDRVVHDXState *s = bs->opaque;
50
unsubscriptable-object,
42
+ int64_t image_file_size = bdrv_getlength(bs->file->bs);
51
+ # pylint's static analysis causes false positivies for file_path();
43
+ uint64_t payblocks = s->chunk_ratio;
52
+ # If we really care to make it statically knowable, we'll use mypy.
44
+ uint64_t i;
53
+ unbalanced-tuple-unpacking,
45
+ int ret = 0;
54
# Sometimes we need to disable a newly introduced pylint warning.
46
+
55
# Doing so should not produce a warning in older versions of pylint.
47
+ if (image_file_size < 0) {
56
bad-option-value,
48
+ error_report("Could not determinate VHDX image file size.");
57
# These are temporary, and should be removed:
49
+ return image_file_size;
58
missing-docstring,
50
+ }
59
too-many-return-statements,
51
+
60
- too-many-statements
52
+ for (i = 0; i < s->bat_entries; i++) {
61
+ too-many-statements,
53
+ if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) ==
62
+ consider-using-f-string,
54
+ PAYLOAD_BLOCK_FULLY_PRESENT) {
63
55
+ uint64_t offset = s->bat[i] & VHDX_BAT_FILE_OFF_MASK;
64
[FORMAT]
56
+ /*
57
+ * Allow that the last block exists only partially. The VHDX spec
58
+ * states that the image file can only grow in blocksize increments,
59
+ * but QEMU created images with partial last blocks in the past.
60
+ */
61
+ uint32_t block_length = MIN(s->block_size,
62
+ bs->total_sectors * BDRV_SECTOR_SIZE - i * s->block_size);
63
+ /*
64
+ * Check for BAT entry overflow.
65
+ */
66
+ if (offset > INT64_MAX - s->block_size) {
67
+ error_report("VHDX BAT entry %" PRIu64 " offset overflow.", i);
68
+ ret = -EINVAL;
69
+ if (!errcnt) {
70
+ break;
71
+ }
72
+ (*errcnt)++;
73
+ }
74
+ /*
75
+ * Check if fully allocated BAT entries do not reside after
76
+ * end of the image file.
77
+ */
78
+ if (offset >= image_file_size) {
79
+ error_report("VHDX BAT entry %" PRIu64 " start offset %" PRIu64
80
+ " points after end of file (%" PRIi64 "). Image"
81
+ " has probably been truncated.",
82
+ i, offset, image_file_size);
83
+ ret = -EINVAL;
84
+ if (!errcnt) {
85
+ break;
86
+ }
87
+ (*errcnt)++;
88
+ } else if (offset + block_length > image_file_size) {
89
+ error_report("VHDX BAT entry %" PRIu64 " end offset %" PRIu64
90
+ " points after end of file (%" PRIi64 "). Image"
91
+ " has probably been truncated.",
92
+ i, offset + block_length - 1, image_file_size);
93
+ ret = -EINVAL;
94
+ if (!errcnt) {
95
+ break;
96
+ }
97
+ (*errcnt)++;
98
+ }
99
+
100
+ /*
101
+ * verify populated BAT field file offsets against
102
+ * region table and log entries
103
+ */
104
+ if (payblocks--) {
105
+ /* payload bat entries */
106
+ int ret2;
107
+ ret2 = vhdx_region_check(s, offset, s->block_size);
108
+ if (ret2 < 0) {
109
+ ret = -EINVAL;
110
+ if (!errcnt) {
111
+ break;
112
+ }
113
+ (*errcnt)++;
114
+ }
115
+ } else {
116
+ payblocks = s->chunk_ratio;
117
+ /*
118
+ * Once differencing files are supported, verify sector bitmap
119
+ * blocks here
120
+ */
121
+ }
122
+ }
123
+ }
124
+
125
+ return ret;
126
+}
127
+
128
static void vhdx_close(BlockDriverState *bs)
129
{
130
BDRVVHDXState *s = bs->opaque;
131
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
132
goto fail;
133
}
134
135
- uint64_t payblocks = s->chunk_ratio;
136
- /* endian convert, and verify populated BAT field file offsets against
137
- * region table and log entries */
138
+ /* endian convert populated BAT field entires */
139
for (i = 0; i < s->bat_entries; i++) {
140
s->bat[i] = le64_to_cpu(s->bat[i]);
141
- if (payblocks--) {
142
- /* payload bat entries */
143
- if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) ==
144
- PAYLOAD_BLOCK_FULLY_PRESENT) {
145
- ret = vhdx_region_check(s, s->bat[i] & VHDX_BAT_FILE_OFF_MASK,
146
- s->block_size);
147
- if (ret < 0) {
148
- goto fail;
149
- }
150
- }
151
- } else {
152
- payblocks = s->chunk_ratio;
153
- /* Once differencing files are supported, verify sector bitmap
154
- * blocks here */
155
+ }
156
+
157
+ if (!(flags & BDRV_O_CHECK)) {
158
+ ret = vhdx_check_bat_entries(bs, NULL);
159
+ if (ret < 0) {
160
+ goto fail;
161
}
162
}
163
164
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_check(BlockDriverState *bs,
165
if (s->log_replayed_on_open) {
166
result->corruptions_fixed++;
167
}
168
+
169
+ vhdx_check_bat_entries(bs, &result->corruptions);
170
+
171
return 0;
172
}
173
65
174
--
66
--
175
2.20.1
67
2.31.1
176
68
177
69
diff view generated by jsdifflib