1
The following changes since commit f17783e706ab9c7b3a2b69cf48e4f0ba40664f54:
1
The following changes since commit 9ac5df20f51fabcba0d902025df4bd7ea987c158:
2
2
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20191220' into staging (2020-01-03 18:50:33 +0000)
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20200221-1' into staging (2020-02-21 16:18:38 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/XanClic/qemu.git tags/pull-block-2020-01-06
7
https://github.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 503ca1262bab2c11c533a4816d1ff4297d4f58a6:
9
for you to fetch changes up to e5c59355ae9f724777c61c859292ec9db2c8c2ab:
10
10
11
backup-top: Begin drain earlier (2020-01-06 14:26:23 +0100)
11
fuzz: add documentation to docs/devel/ (2020-02-22 08:26:48 +0000)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- Minor fixes and tests from the freeze period (too minor to be included
15
16
in 4.2)
16
This pull request contains a virtio-blk/scsi performance optimization, event
17
- Allow many bash iotests to test qcow2's external data file feature
17
loop scalability improvements, and a qtest-based device fuzzing framework. I
18
- Add compress filter driver
18
am including the fuzzing patches because I have reviewed them and Thomas Huth
19
- Fix Python iotests after 6f6e1698a6
19
is currently away on leave.
20
- Fix for the backup job
21
20
22
----------------------------------------------------------------
21
----------------------------------------------------------------
23
Andrey Shinkevich (3):
24
block: introduce compress filter driver
25
qcow2: Allow writing compressed data of multiple clusters
26
tests/qemu-iotests: add case to write compressed data of multiple
27
clusters
28
22
29
Max Reitz (28):
23
Alexander Bulekov (22):
30
block: Add bdrv_qapi_perm_to_blk_perm()
24
softmmu: move vl.c to softmmu/
31
block: Use bdrv_qapi_perm_to_blk_perm()
25
softmmu: split off vl.c:main() into main.c
32
blkdebug: Allow taking/unsharing permissions
26
module: check module wasn't already initialized
33
iotests: Add @error to wait_until_completed
27
fuzz: add FUZZ_TARGET module type
34
iotests: Add test for failing mirror complete
28
qtest: add qtest_server_send abstraction
35
iotests: s/qocw2/qcow2/
29
libqtest: add a layer of abstraction to send/recv
36
iotests/qcow2.py: Add dump-header-exts
30
libqtest: make bufwrite rely on the TransportOps
37
iotests/qcow2.py: Split feature fields into bits
31
qtest: add in-process incoming command handler
38
iotests: Add _filter_json_filename
32
libqos: rename i2c_send and i2c_recv
39
iotests: Filter refcount_order in 036
33
libqos: split qos-test and libqos makefile vars
40
iotests: Replace IMGOPTS by _unsupported_imgopts
34
libqos: move useful qos-test funcs to qos_external
41
iotests: Drop compat=1.1 in 050
35
fuzz: add fuzzer skeleton
42
iotests: Let _make_test_img parse its parameters
36
exec: keep ram block across fork when using qtest
43
iotests: Add -o and --no-opts to _make_test_img
37
main: keep rcu_atfork callback enabled for qtest
44
iotests: Inject space into -ocompat=0.10 in 051
38
fuzz: support for fork-based fuzzing.
45
iotests: Replace IMGOPTS= by -o
39
fuzz: add support for qos-assisted fuzz targets
46
iotests: Replace IMGOPTS='' by --no-opts
40
fuzz: add target/fuzz makefile rules
47
iotests: Drop IMGOPTS use in 267
41
fuzz: add configure flag --enable-fuzzing
48
iotests: Avoid qemu-img create
42
fuzz: add i440fx fuzz targets
49
iotests: Use _rm_test_img for deleting test images
43
fuzz: add virtio-net fuzz target
50
iotests: Avoid cp/mv of test images
44
fuzz: add virtio-scsi fuzz target
51
iotests: Make 091 work with data_file
45
fuzz: add documentation to docs/devel/
52
iotests: Make 110 work with data_file
53
iotests: Make 137 work with data_file
54
iotests: Make 198 work with data_file
55
iotests: Disable data_file where it cannot be used
56
iotests: Allow check -o data_file
57
backup-top: Begin drain earlier
58
46
59
PanNengyuan (1):
47
Denis Plotnikov (1):
60
throttle-groups: fix memory leak in throttle_group_set_limit:
48
virtio: increase virtqueue size for virtio-scsi and virtio-blk
61
49
62
Philippe Mathieu-Daudé (1):
50
Paolo Bonzini (1):
63
tests/qemu-iotests: Update tests to recent desugarized -accel option
51
rcu_queue: add QSLIST functions
64
52
65
Vladimir Sementsov-Ogievskiy (1):
53
Stefan Hajnoczi (7):
66
qcow2-bitmaps: fix qcow2_can_store_new_dirty_bitmap
54
aio-posix: avoid reacquiring rcu_read_lock() when polling
55
util/async: make bh_aio_poll() O(1)
56
aio-posix: fix use after leaving scope in aio_poll()
57
aio-posix: don't pass ns timeout to epoll_wait()
58
qemu/queue.h: add QLIST_SAFE_REMOVE()
59
aio-posix: make AioHandler deletion O(1)
60
aio-posix: make AioHandler dispatch O(1) with epoll
67
61
68
block.c | 47 +++++----
62
MAINTAINERS | 11 +-
69
block/Makefile.objs | 1 +
63
Makefile | 15 +-
70
block/backup-top.c | 4 +-
64
Makefile.objs | 2 -
71
block/blkdebug.c | 93 ++++++++++++++++-
65
Makefile.target | 19 ++-
72
block/filter-compress.c | 168 +++++++++++++++++++++++++++++++
66
block.c | 5 +-
73
block/qcow2-bitmap.c | 41 ++++----
67
chardev/spice.c | 4 +-
74
block/qcow2.c | 102 ++++++++++++++-----
68
configure | 39 +++++
75
block/throttle-groups.c | 4 +-
69
docs/devel/fuzzing.txt | 116 ++++++++++++++
76
include/block/block.h | 1 +
70
exec.c | 12 +-
77
qapi/block-core.json | 24 ++++-
71
hw/block/virtio-blk.c | 2 +-
78
tests/qemu-iotests/007 | 5 +-
72
hw/core/machine.c | 2 +
79
tests/qemu-iotests/014 | 2 +
73
hw/scsi/virtio-scsi.c | 2 +-
80
tests/qemu-iotests/015 | 5 +-
74
include/block/aio.h | 26 ++-
81
tests/qemu-iotests/019 | 6 +-
75
include/qemu/module.h | 4 +-
82
tests/qemu-iotests/020 | 6 +-
76
include/qemu/queue.h | 32 +++-
83
tests/qemu-iotests/024 | 10 +-
77
include/qemu/rcu_queue.h | 47 ++++++
84
tests/qemu-iotests/026 | 5 +-
78
include/sysemu/qtest.h | 4 +
85
tests/qemu-iotests/028 | 2 +-
79
include/sysemu/sysemu.h | 4 +
86
tests/qemu-iotests/029 | 7 +-
80
qtest.c | 31 +++-
87
tests/qemu-iotests/031 | 9 +-
81
scripts/checkpatch.pl | 2 +-
88
tests/qemu-iotests/031.out | 36 +++----
82
scripts/get_maintainer.pl | 3 +-
89
tests/qemu-iotests/036 | 15 +--
83
softmmu/Makefile.objs | 3 +
90
tests/qemu-iotests/036.out | 66 ++----------
84
softmmu/main.c | 53 +++++++
91
tests/qemu-iotests/039 | 27 ++---
85
vl.c => softmmu/vl.c | 48 +++---
92
tests/qemu-iotests/039.out | 22 ++--
86
tests/Makefile.include | 2 +
93
tests/qemu-iotests/041 | 44 ++++++++
87
tests/qtest/Makefile.include | 72 +++++----
94
tests/qemu-iotests/041.out | 4 +-
88
tests/qtest/fuzz/Makefile.include | 18 +++
95
tests/qemu-iotests/043 | 4 +-
89
tests/qtest/fuzz/fork_fuzz.c | 55 +++++++
96
tests/qemu-iotests/046 | 2 +
90
tests/qtest/fuzz/fork_fuzz.h | 23 +++
97
tests/qemu-iotests/048 | 4 +-
91
tests/qtest/fuzz/fork_fuzz.ld | 37 +++++
98
tests/qemu-iotests/050 | 8 +-
92
tests/qtest/fuzz/fuzz.c | 179 +++++++++++++++++++++
99
tests/qemu-iotests/051 | 7 +-
93
tests/qtest/fuzz/fuzz.h | 95 +++++++++++
100
tests/qemu-iotests/053 | 4 +-
94
tests/qtest/fuzz/i440fx_fuzz.c | 193 ++++++++++++++++++++++
101
tests/qemu-iotests/058 | 7 +-
95
tests/qtest/fuzz/qos_fuzz.c | 234 +++++++++++++++++++++++++++
102
tests/qemu-iotests/059 | 20 ++--
96
tests/qtest/fuzz/qos_fuzz.h | 33 ++++
103
tests/qemu-iotests/060 | 14 +--
97
tests/qtest/fuzz/virtio_net_fuzz.c | 198 +++++++++++++++++++++++
104
tests/qemu-iotests/060.out | 20 ++--
98
tests/qtest/fuzz/virtio_scsi_fuzz.c | 213 +++++++++++++++++++++++++
105
tests/qemu-iotests/061 | 63 ++++++------
99
tests/qtest/libqos/i2c.c | 10 +-
106
tests/qemu-iotests/061.out | 72 ++++++-------
100
tests/qtest/libqos/i2c.h | 4 +-
107
tests/qemu-iotests/062 | 5 +-
101
tests/qtest/libqos/qos_external.c | 168 ++++++++++++++++++++
108
tests/qemu-iotests/063 | 18 ++--
102
tests/qtest/libqos/qos_external.h | 28 ++++
109
tests/qemu-iotests/063.out | 3 +-
103
tests/qtest/libqtest.c | 119 ++++++++++++--
110
tests/qemu-iotests/066 | 7 +-
104
tests/qtest/libqtest.h | 4 +
111
tests/qemu-iotests/067 | 6 +-
105
tests/qtest/pca9552-test.c | 10 +-
112
tests/qemu-iotests/068 | 6 +-
106
tests/qtest/qos-test.c | 132 +---------------
113
tests/qemu-iotests/069 | 2 +-
107
tests/test-aio.c | 3 +-
114
tests/qemu-iotests/071 | 7 +-
108
tests/test-rcu-list.c | 16 ++
115
tests/qemu-iotests/073 | 4 +
109
tests/test-rcu-slist.c | 2 +
116
tests/qemu-iotests/074 | 4 +-
110
util/aio-posix.c | 187 +++++++++++++++-------
117
tests/qemu-iotests/079 | 3 +-
111
util/async.c | 237 ++++++++++++++++------------
118
tests/qemu-iotests/080 | 7 +-
112
util/module.c | 7 +
119
tests/qemu-iotests/081 | 6 +-
113
51 files changed, 2365 insertions(+), 400 deletions(-)
120
tests/qemu-iotests/085 | 18 ++--
114
create mode 100644 docs/devel/fuzzing.txt
121
tests/qemu-iotests/085.out | 8 +-
115
create mode 100644 softmmu/Makefile.objs
122
tests/qemu-iotests/088 | 2 +-
116
create mode 100644 softmmu/main.c
123
tests/qemu-iotests/090 | 2 +
117
rename vl.c => softmmu/vl.c (99%)
124
tests/qemu-iotests/091 | 2 +-
118
create mode 100644 tests/qtest/fuzz/Makefile.include
125
tests/qemu-iotests/091.out | 2 -
119
create mode 100644 tests/qtest/fuzz/fork_fuzz.c
126
tests/qemu-iotests/092 | 2 +-
120
create mode 100644 tests/qtest/fuzz/fork_fuzz.h
127
tests/qemu-iotests/094 | 4 +-
121
create mode 100644 tests/qtest/fuzz/fork_fuzz.ld
128
tests/qemu-iotests/095 | 5 +-
122
create mode 100644 tests/qtest/fuzz/fuzz.c
129
tests/qemu-iotests/098 | 6 +-
123
create mode 100644 tests/qtest/fuzz/fuzz.h
130
tests/qemu-iotests/099 | 10 +-
124
create mode 100644 tests/qtest/fuzz/i440fx_fuzz.c
131
tests/qemu-iotests/103 | 5 +-
125
create mode 100644 tests/qtest/fuzz/qos_fuzz.c
132
tests/qemu-iotests/106 | 2 +-
126
create mode 100644 tests/qtest/fuzz/qos_fuzz.h
133
tests/qemu-iotests/108 | 10 +-
127
create mode 100644 tests/qtest/fuzz/virtio_net_fuzz.c
134
tests/qemu-iotests/109 | 4 +-
128
create mode 100644 tests/qtest/fuzz/virtio_scsi_fuzz.c
135
tests/qemu-iotests/110 | 11 +-
129
create mode 100644 tests/qtest/libqos/qos_external.c
136
tests/qemu-iotests/110.out | 4 +-
130
create mode 100644 tests/qtest/libqos/qos_external.h
137
tests/qemu-iotests/111 | 3 +-
131
create mode 100644 tests/test-rcu-slist.c
138
tests/qemu-iotests/112 | 37 +++----
139
tests/qemu-iotests/114 | 2 +
140
tests/qemu-iotests/115 | 3 +-
141
tests/qemu-iotests/121 | 9 +-
142
tests/qemu-iotests/122 | 6 +-
143
tests/qemu-iotests/123 | 4 +-
144
tests/qemu-iotests/125 | 2 +-
145
tests/qemu-iotests/137 | 17 +++-
146
tests/qemu-iotests/137.out | 6 +-
147
tests/qemu-iotests/138 | 8 +-
148
tests/qemu-iotests/141 | 4 +-
149
tests/qemu-iotests/142 | 2 +-
150
tests/qemu-iotests/144 | 4 +-
151
tests/qemu-iotests/153 | 12 +--
152
tests/qemu-iotests/156 | 10 +-
153
tests/qemu-iotests/159 | 2 +-
154
tests/qemu-iotests/160 | 3 +-
155
tests/qemu-iotests/161 | 4 +-
156
tests/qemu-iotests/170 | 2 +-
157
tests/qemu-iotests/172 | 6 +-
158
tests/qemu-iotests/173 | 3 +-
159
tests/qemu-iotests/174 | 2 +-
160
tests/qemu-iotests/175 | 2 +-
161
tests/qemu-iotests/176 | 7 +-
162
tests/qemu-iotests/178 | 6 +-
163
tests/qemu-iotests/182 | 2 +-
164
tests/qemu-iotests/183 | 2 +-
165
tests/qemu-iotests/185 | 4 +-
166
tests/qemu-iotests/187 | 6 +-
167
tests/qemu-iotests/190 | 4 +-
168
tests/qemu-iotests/191 | 11 +-
169
tests/qemu-iotests/195 | 2 +-
170
tests/qemu-iotests/197 | 6 +-
171
tests/qemu-iotests/198 | 6 +-
172
tests/qemu-iotests/198.out | 4 +-
173
tests/qemu-iotests/200 | 7 +-
174
tests/qemu-iotests/201 | 6 +-
175
tests/qemu-iotests/214 | 46 ++++++++-
176
tests/qemu-iotests/214.out | 14 +++
177
tests/qemu-iotests/215 | 6 +-
178
tests/qemu-iotests/217 | 3 +-
179
tests/qemu-iotests/220 | 5 +-
180
tests/qemu-iotests/225 | 2 +-
181
tests/qemu-iotests/229 | 3 +-
182
tests/qemu-iotests/232 | 4 +-
183
tests/qemu-iotests/235 | 2 +-
184
tests/qemu-iotests/243 | 10 +-
185
tests/qemu-iotests/244 | 15 +--
186
tests/qemu-iotests/247 | 4 +-
187
tests/qemu-iotests/249 | 4 +-
188
tests/qemu-iotests/250 | 5 +-
189
tests/qemu-iotests/252 | 2 +-
190
tests/qemu-iotests/261 | 5 +-
191
tests/qemu-iotests/265 | 2 +-
192
tests/qemu-iotests/267 | 17 ++--
193
tests/qemu-iotests/273 | 3 +
194
tests/qemu-iotests/check | 6 +-
195
tests/qemu-iotests/common.filter | 47 ++++++++-
196
tests/qemu-iotests/common.rc | 63 ++++++++++--
197
tests/qemu-iotests/iotests.py | 18 ++--
198
tests/qemu-iotests/qcow2.py | 23 ++++-
199
131 files changed, 1139 insertions(+), 552 deletions(-)
200
create mode 100644 block/filter-compress.c
201
132
202
--
133
--
203
2.24.1
134
2.24.1
204
135
205
diff view generated by jsdifflib
1
When dropping backup-top, we need to drain the node before freeing the
1
From: Denis Plotnikov <dplotnikov@virtuozzo.com>
2
BlockCopyState. Otherwise, requests may still be in flight and then the
3
assertion in shres_destroy() will fail.
4
2
5
(This becomes visible in intermittent failure of 056.)
3
The goal is to reduce the amount of requests issued by a guest on
4
1M reads/writes. This rises the performance up to 4% on that kind of
5
disk access pattern.
6
6
7
Cc: qemu-stable@nongnu.org
7
The maximum chunk size to be used for the guest disk accessing is
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
limited with seg_max parameter, which represents the max amount of
9
Message-id: 20191219182638.104621-1-mreitz@redhat.com
9
pices in the scatter-geather list in one guest disk request.
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
11
Since seg_max is virqueue_size dependent, increasing the virtqueue
12
size increases seg_max, which, in turn, increases the maximum size
13
of data to be read/write from a guest disk.
14
15
More details in the original problem statment:
16
https://lists.gnu.org/archive/html/qemu-devel/2017-12/msg03721.html
17
18
Suggested-by: Denis V. Lunev <den@openvz.org>
19
Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com>
20
Message-id: 20200214074648.958-1-dplotnikov@virtuozzo.com
21
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
22
---
12
block/backup-top.c | 4 ++--
23
hw/block/virtio-blk.c | 2 +-
13
1 file changed, 2 insertions(+), 2 deletions(-)
24
hw/core/machine.c | 2 ++
25
hw/scsi/virtio-scsi.c | 2 +-
26
3 files changed, 4 insertions(+), 2 deletions(-)
14
27
15
diff --git a/block/backup-top.c b/block/backup-top.c
28
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
16
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
17
--- a/block/backup-top.c
30
--- a/hw/block/virtio-blk.c
18
+++ b/block/backup-top.c
31
+++ b/hw/block/virtio-blk.c
19
@@ -XXX,XX +XXX,XX @@ void bdrv_backup_top_drop(BlockDriverState *bs)
32
@@ -XXX,XX +XXX,XX @@ static Property virtio_blk_properties[] = {
20
BDRVBackupTopState *s = bs->opaque;
33
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
21
AioContext *aio_context = bdrv_get_aio_context(bs);
34
true),
22
35
DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues, 1),
23
- block_copy_state_free(s->bcs);
36
- DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 128),
24
-
37
+ DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 256),
25
aio_context_acquire(aio_context);
38
DEFINE_PROP_BOOL("seg-max-adjust", VirtIOBlock, conf.seg_max_adjust, true),
26
39
DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD,
27
bdrv_drained_begin(bs);
40
IOThread *),
28
41
diff --git a/hw/core/machine.c b/hw/core/machine.c
29
+ block_copy_state_free(s->bcs);
42
index XXXXXXX..XXXXXXX 100644
30
+
43
--- a/hw/core/machine.c
31
s->active = false;
44
+++ b/hw/core/machine.c
32
bdrv_child_refresh_perms(bs, bs->backing, &error_abort);
45
@@ -XXX,XX +XXX,XX @@
33
bdrv_replace_node(bs, backing_bs(bs), &error_abort);
46
#include "hw/mem/nvdimm.h"
47
48
GlobalProperty hw_compat_4_2[] = {
49
+ { "virtio-blk-device", "queue-size", "128"},
50
+ { "virtio-scsi-device", "virtqueue_size", "128"},
51
{ "virtio-blk-device", "x-enable-wce-if-config-wce", "off" },
52
{ "virtio-blk-device", "seg-max-adjust", "off"},
53
{ "virtio-scsi-device", "seg_max_adjust", "off"},
54
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/scsi/virtio-scsi.c
57
+++ b/hw/scsi/virtio-scsi.c
58
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
59
static Property virtio_scsi_properties[] = {
60
DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, 1),
61
DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSI,
62
- parent_obj.conf.virtqueue_size, 128),
63
+ parent_obj.conf.virtqueue_size, 256),
64
DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSI,
65
parent_obj.conf.seg_max_adjust, true),
66
DEFINE_PROP_UINT32("max_sectors", VirtIOSCSI, parent_obj.conf.max_sectors,
34
--
67
--
35
2.24.1
68
2.24.1
36
69
37
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
The first rcu_read_lock/unlock() is expensive. Nested calls are cheap.
2
2
3
Commit 6f6e1698a6 desugarized "-machine accel=" to a list
3
This optimization increases IOPS from 73k to 162k with a Linux guest
4
of "-accel" options. Since now "-machine accel" and "-accel"
4
that has 2 virtio-blk,num-queues=1 and 99 virtio-blk,num-queues=32
5
became incompatible, update the iotests to the new format.
5
devices.
6
6
7
Error reported here:
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
https://gitlab.com/qemu-project/qemu/-/jobs/385801004#L3400
8
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-id: 20200218182708.914552-1-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
util/aio-posix.c | 11 +++++++++++
13
1 file changed, 11 insertions(+)
9
14
10
Reported-by: GitLab CI
15
diff --git a/util/aio-posix.c b/util/aio-posix.c
11
Fixes: 6f6e1698a6 (vl: configure accelerators from -accel options)
16
index XXXXXXX..XXXXXXX 100644
12
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
--- a/util/aio-posix.c
13
Message-id: 20200106130951.29873-1-philmd@redhat.com
18
+++ b/util/aio-posix.c
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
@@ -XXX,XX +XXX,XX @@
15
---
20
16
tests/qemu-iotests/235 | 2 +-
21
#include "qemu/osdep.h"
17
tests/qemu-iotests/check | 6 +++---
22
#include "block/block.h"
18
2 files changed, 4 insertions(+), 4 deletions(-)
23
+#include "qemu/rcu.h"
19
24
#include "qemu/rcu_queue.h"
20
diff --git a/tests/qemu-iotests/235 b/tests/qemu-iotests/235
25
#include "qemu/sockets.h"
21
index XXXXXXX..XXXXXXX 100755
26
#include "qemu/cutils.h"
22
--- a/tests/qemu-iotests/235
27
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers_once(AioContext *ctx, int64_t *timeout)
23
+++ b/tests/qemu-iotests/235
28
bool progress = false;
24
@@ -XXX,XX +XXX,XX @@ qemu_img_create('-f', iotests.imgfmt, '-o', 'preallocation=metadata', disk,
29
AioHandler *node;
25
str(size))
30
26
31
+ /*
27
vm = QEMUMachine(iotests.qemu_prog)
32
+ * Optimization: ->io_poll() handlers often contain RCU read critical
28
-vm.add_args('-machine', 'accel=kvm:tcg')
33
+ * sections and we therefore see many rcu_read_lock() -> rcu_read_unlock()
29
+vm.add_args('-accel', 'kvm', '-accel', 'tcg')
34
+ * -> rcu_read_lock() -> ... sequences with expensive memory
30
if iotests.qemu_default_machine == 's390-ccw-virtio':
35
+ * synchronization primitives. Make the entire polling loop an RCU
31
vm.add_args('-no-shutdown')
36
+ * critical section because nested rcu_read_lock()/rcu_read_unlock() calls
32
vm.add_args('-drive', 'id=src,file=' + disk)
37
+ * are cheap.
33
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
38
+ */
34
index XXXXXXX..XXXXXXX 100755
39
+ RCU_READ_LOCK_GUARD();
35
--- a/tests/qemu-iotests/check
40
+
36
+++ b/tests/qemu-iotests/check
41
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
37
@@ -XXX,XX +XXX,XX @@ export QEMU_PROG="$(type -p "$QEMU_PROG")"
42
if (!node->deleted && node->io_poll &&
38
43
aio_node_check(ctx, node->is_external) &&
39
case "$QEMU_PROG" in
40
*qemu-system-arm|*qemu-system-aarch64)
41
- export QEMU_OPTIONS="-nodefaults -display none -machine virt,accel=qtest"
42
+ export QEMU_OPTIONS="-nodefaults -display none -machine virt -accel qtest"
43
;;
44
*qemu-system-tricore)
45
- export QEMU_OPTIONS="-nodefaults -display none -machine tricore_testboard,accel=qtest"
46
+ export QEMU_OPTIONS="-nodefaults -display none -machine tricore_testboard -accel qtest"
47
;;
48
*)
49
- export QEMU_OPTIONS="-nodefaults -display none -machine accel=qtest"
50
+ export QEMU_OPTIONS="-nodefaults -display none -accel qtest"
51
;;
52
esac
53
54
--
44
--
55
2.24.1
45
2.24.1
56
46
57
diff view generated by jsdifflib
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Add the case to the iotest #214 that checks possibility of writing
3
QSLIST is the only family of lists for which we do not have RCU-friendly accessors,
4
compressed data of more than one cluster size. The test case involves
4
add them.
5
the compress filter driver showing a sample usage of that.
6
5
7
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-id: 20200220103828.24525-1-pbonzini@redhat.com
10
Message-id: 1575288906-551879-4-git-send-email-andrey.shinkevich@virtuozzo.com
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
10
---
13
tests/qemu-iotests/214 | 43 ++++++++++++++++++++++++++++++++++++++
11
include/qemu/queue.h | 15 +++++++++++--
14
tests/qemu-iotests/214.out | 14 +++++++++++++
12
include/qemu/rcu_queue.h | 47 ++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 57 insertions(+)
13
tests/Makefile.include | 2 ++
14
tests/test-rcu-list.c | 16 ++++++++++++++
15
tests/test-rcu-slist.c | 2 ++
16
5 files changed, 80 insertions(+), 2 deletions(-)
17
create mode 100644 tests/test-rcu-slist.c
16
18
17
diff --git a/tests/qemu-iotests/214 b/tests/qemu-iotests/214
19
diff --git a/include/qemu/queue.h b/include/qemu/queue.h
18
index XXXXXXX..XXXXXXX 100755
20
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/214
21
--- a/include/qemu/queue.h
20
+++ b/tests/qemu-iotests/214
22
+++ b/include/qemu/queue.h
21
@@ -XXX,XX +XXX,XX @@ _check_test_img -r all
23
@@ -XXX,XX +XXX,XX @@ struct { \
22
$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
24
(head)->slh_first = (head)->slh_first->field.sle_next; \
23
$QEMU_IO -c "read -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
25
} while (/*CONSTCOND*/0)
24
26
25
+echo
27
-#define QSLIST_REMOVE_AFTER(slistelm, field) do { \
26
+echo "=== Write compressed data of multiple clusters ==="
28
+#define QSLIST_REMOVE_AFTER(slistelm, field) do { \
27
+echo
29
(slistelm)->field.sle_next = \
28
+cluster_size=0x10000
30
- QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \
29
+_make_test_img 2M -o cluster_size=$cluster_size
31
+ QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \
32
+} while (/*CONSTCOND*/0)
30
+
33
+
31
+echo "Write uncompressed data:"
34
+#define QSLIST_REMOVE(head, elm, type, field) do { \
32
+let data_size="8 * $cluster_size"
35
+ if ((head)->slh_first == (elm)) { \
33
+$QEMU_IO -c "write -P 0xaa 0 $data_size" "$TEST_IMG" \
36
+ QSLIST_REMOVE_HEAD((head), field); \
34
+ 2>&1 | _filter_qemu_io | _filter_testdir
37
+ } else { \
35
+sizeA=$($QEMU_IMG info --output=json "$TEST_IMG" |
38
+ struct type *curelm = (head)->slh_first; \
36
+ sed -n '/"actual-size":/ s/[^0-9]//gp')
39
+ while (curelm->field.sle_next != (elm)) \
40
+ curelm = curelm->field.sle_next; \
41
+ curelm->field.sle_next = curelm->field.sle_next->field.sle_next; \
42
+ } \
43
} while (/*CONSTCOND*/0)
44
45
#define QSLIST_FOREACH(var, head, field) \
46
diff --git a/include/qemu/rcu_queue.h b/include/qemu/rcu_queue.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/include/qemu/rcu_queue.h
49
+++ b/include/qemu/rcu_queue.h
50
@@ -XXX,XX +XXX,XX @@ extern "C" {
51
(var) && ((next) = atomic_rcu_read(&(var)->field.tqe_next), 1); \
52
(var) = (next))
53
54
+/*
55
+ * RCU singly-linked list
56
+ */
37
+
57
+
38
+_make_test_img 2M -o cluster_size=$cluster_size
58
+/* Singly-linked list access methods */
39
+echo "Write compressed data:"
59
+#define QSLIST_EMPTY_RCU(head) (atomic_read(&(head)->slh_first) == NULL)
40
+let data_size="3 * $cluster_size + $cluster_size / 2"
60
+#define QSLIST_FIRST_RCU(head) atomic_rcu_read(&(head)->slh_first)
41
+# Set compress on. That will align the written data
61
+#define QSLIST_NEXT_RCU(elm, field) atomic_rcu_read(&(elm)->field.sle_next)
42
+# by the cluster size and will write them compressed.
43
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \
44
+$QEMU_IO -c "write -P 0xbb 0 $data_size" --image-opts \
45
+ "driver=compress,file.driver=$IMGFMT,file.file.driver=file,file.file.filename=$TEST_IMG" \
46
+ 2>&1 | _filter_qemu_io | _filter_testdir
47
+
62
+
48
+let offset="4 * $cluster_size + $cluster_size / 4"
63
+/* Singly-linked list functions */
49
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \
64
+#define QSLIST_INSERT_HEAD_RCU(head, elm, field) do { \
50
+$QEMU_IO -c "write -P 0xcc $offset $data_size" "json:{\
65
+ (elm)->field.sle_next = (head)->slh_first; \
51
+ 'driver': 'compress',
66
+ atomic_rcu_set(&(head)->slh_first, (elm)); \
52
+ 'file': {'driver': '$IMGFMT',
67
+} while (/*CONSTCOND*/0)
53
+ 'file': {'driver': 'file',
54
+ 'filename': '$TEST_IMG'}}}" | \
55
+ _filter_qemu_io | _filter_testdir
56
+
68
+
57
+sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" |
69
+#define QSLIST_INSERT_AFTER_RCU(head, listelm, elm, field) do { \
58
+ sed -n '/"actual-size":/ s/[^0-9]//gp')
70
+ (elm)->field.sle_next = (listelm)->field.sle_next; \
71
+ atomic_rcu_set(&(listelm)->field.sle_next, (elm)); \
72
+} while (/*CONSTCOND*/0)
59
+
73
+
60
+if [ $sizeA -le $sizeB ]
74
+#define QSLIST_REMOVE_HEAD_RCU(head, field) do { \
61
+then
75
+ atomic_set(&(head)->slh_first, (head)->slh_first->field.sle_next); \
62
+ echo "Compression ERROR"
76
+} while (/*CONSTCOND*/0)
63
+fi
64
+
77
+
65
+$QEMU_IMG check --output=json "$TEST_IMG" |
78
+#define QSLIST_REMOVE_RCU(head, elm, type, field) do { \
66
+ sed -n 's/,$//; /"compressed-clusters":/ s/^ *//p'
79
+ if ((head)->slh_first == (elm)) { \
80
+ QSLIST_REMOVE_HEAD_RCU((head), field); \
81
+ } else { \
82
+ struct type *curr = (head)->slh_first; \
83
+ while (curr->field.sle_next != (elm)) { \
84
+ curr = curr->field.sle_next; \
85
+ } \
86
+ atomic_set(&curr->field.sle_next, \
87
+ curr->field.sle_next->field.sle_next); \
88
+ } \
89
+} while (/*CONSTCOND*/0)
67
+
90
+
68
# success, all done
91
+#define QSLIST_FOREACH_RCU(var, head, field) \
69
echo '*** done'
92
+ for ((var) = atomic_rcu_read(&(head)->slh_first); \
70
rm -f $seq.full
93
+ (var); \
71
diff --git a/tests/qemu-iotests/214.out b/tests/qemu-iotests/214.out
94
+ (var) = atomic_rcu_read(&(var)->field.sle_next))
95
+
96
+#define QSLIST_FOREACH_SAFE_RCU(var, head, field, next) \
97
+ for ((var) = atomic_rcu_read(&(head)->slh_first); \
98
+ (var) && ((next) = atomic_rcu_read(&(var)->field.sle_next), 1); \
99
+ (var) = (next))
100
+
101
#ifdef __cplusplus
102
}
103
#endif
104
diff --git a/tests/Makefile.include b/tests/Makefile.include
72
index XXXXXXX..XXXXXXX 100644
105
index XXXXXXX..XXXXXXX 100644
73
--- a/tests/qemu-iotests/214.out
106
--- a/tests/Makefile.include
74
+++ b/tests/qemu-iotests/214.out
107
+++ b/tests/Makefile.include
75
@@ -XXX,XX +XXX,XX @@ read 4194304/4194304 bytes at offset 0
108
@@ -XXX,XX +XXX,XX @@ check-unit-y += tests/rcutorture$(EXESUF)
76
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
109
check-unit-y += tests/test-rcu-list$(EXESUF)
77
read 4194304/4194304 bytes at offset 4194304
110
check-unit-y += tests/test-rcu-simpleq$(EXESUF)
78
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
111
check-unit-y += tests/test-rcu-tailq$(EXESUF)
112
+check-unit-y += tests/test-rcu-slist$(EXESUF)
113
check-unit-y += tests/test-qdist$(EXESUF)
114
check-unit-y += tests/test-qht$(EXESUF)
115
check-unit-y += tests/test-qht-par$(EXESUF)
116
@@ -XXX,XX +XXX,XX @@ tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y)
117
tests/test-rcu-list$(EXESUF): tests/test-rcu-list.o $(test-util-obj-y)
118
tests/test-rcu-simpleq$(EXESUF): tests/test-rcu-simpleq.o $(test-util-obj-y)
119
tests/test-rcu-tailq$(EXESUF): tests/test-rcu-tailq.o $(test-util-obj-y)
120
+tests/test-rcu-slist$(EXESUF): tests/test-rcu-slist.o $(test-util-obj-y)
121
tests/test-qdist$(EXESUF): tests/test-qdist.o $(test-util-obj-y)
122
tests/test-qht$(EXESUF): tests/test-qht.o $(test-util-obj-y)
123
tests/test-qht-par$(EXESUF): tests/test-qht-par.o tests/qht-bench$(EXESUF) $(test-util-obj-y)
124
diff --git a/tests/test-rcu-list.c b/tests/test-rcu-list.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/tests/test-rcu-list.c
127
+++ b/tests/test-rcu-list.c
128
@@ -XXX,XX +XXX,XX @@ struct list_element {
129
QSIMPLEQ_ENTRY(list_element) entry;
130
#elif TEST_LIST_TYPE == 3
131
QTAILQ_ENTRY(list_element) entry;
132
+#elif TEST_LIST_TYPE == 4
133
+ QSLIST_ENTRY(list_element) entry;
134
#else
135
#error Invalid TEST_LIST_TYPE
136
#endif
137
@@ -XXX,XX +XXX,XX @@ static QTAILQ_HEAD(, list_element) Q_list_head;
138
#define TEST_LIST_INSERT_HEAD_RCU QTAILQ_INSERT_HEAD_RCU
139
#define TEST_LIST_FOREACH_RCU QTAILQ_FOREACH_RCU
140
#define TEST_LIST_FOREACH_SAFE_RCU QTAILQ_FOREACH_SAFE_RCU
79
+
141
+
80
+=== Write compressed data of multiple clusters ===
142
+#elif TEST_LIST_TYPE == 4
143
+static QSLIST_HEAD(, list_element) Q_list_head;
81
+
144
+
82
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
145
+#define TEST_NAME "qslist"
83
+Write uncompressed data:
146
+#define TEST_LIST_REMOVE_RCU(el, f) \
84
+wrote 524288/524288 bytes at offset 0
147
+     QSLIST_REMOVE_RCU(&Q_list_head, el, list_element, f)
85
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
148
+
86
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
149
+#define TEST_LIST_INSERT_AFTER_RCU(list_el, el, f) \
87
+Write compressed data:
150
+ QSLIST_INSERT_AFTER_RCU(&Q_list_head, list_el, el, f)
88
+wrote 229376/229376 bytes at offset 0
151
+
89
+224 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
152
+#define TEST_LIST_INSERT_HEAD_RCU QSLIST_INSERT_HEAD_RCU
90
+wrote 229376/229376 bytes at offset 278528
153
+#define TEST_LIST_FOREACH_RCU QSLIST_FOREACH_RCU
91
+224 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
154
+#define TEST_LIST_FOREACH_SAFE_RCU QSLIST_FOREACH_SAFE_RCU
92
+"compressed-clusters": 8
155
#else
93
*** done
156
#error Invalid TEST_LIST_TYPE
157
#endif
158
diff --git a/tests/test-rcu-slist.c b/tests/test-rcu-slist.c
159
new file mode 100644
160
index XXXXXXX..XXXXXXX
161
--- /dev/null
162
+++ b/tests/test-rcu-slist.c
163
@@ -XXX,XX +XXX,XX @@
164
+#define TEST_LIST_TYPE 4
165
+#include "test-rcu-list.c"
94
--
166
--
95
2.24.1
167
2.24.1
96
168
97
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
The ctx->first_bh list contains all created BHs, including those that
2
2
are not scheduled. The list is iterated by the event loop and therefore
3
qcow2_can_store_new_dirty_bitmap works wrong, as it considers only
3
has O(n) time complexity with respected to the number of created BHs.
4
bitmaps already stored in the qcow2 image and ignores persistent
4
5
BdrvDirtyBitmap objects.
5
Rewrite BHs so that only scheduled or deleted BHs are enqueued.
6
6
Only BHs that actually require action will be iterated.
7
So, let's instead count persistent BdrvDirtyBitmaps. We load all qcow2
7
8
bitmaps on open, so there should not be any bitmap in the image for
8
One semantic change is required: qemu_bh_delete() enqueues the BH and
9
which we don't have BdrvDirtyBitmaps version. If it is - it's a kind of
9
therefore invokes aio_notify(). The
10
corruption, and no reason to check for corruptions here (open() and
10
tests/test-aio.c:test_source_bh_delete_from_cb() test case assumed that
11
close() are better places for it).
11
g_main_context_iteration(NULL, false) returns false after
12
12
qemu_bh_delete() but it now returns true for one iteration. Fix up the
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
test case.
14
Message-id: 20191014115126.15360-2-vsementsov@virtuozzo.com
14
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
This patch makes aio_compute_timeout() and aio_bh_poll() drop from a CPU
16
Cc: qemu-stable@nongnu.org
16
profile reported by perf-top(1). Previously they combined to 9% CPU
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
utilization when AioContext polling is commented out and the guest has 2
18
virtio-blk,num-queues=1 and 99 virtio-blk,num-queues=32 devices.
19
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
21
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
22
Message-id: 20200221093951.1414693-1-stefanha@redhat.com
23
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
18
---
24
---
19
block/qcow2-bitmap.c | 41 ++++++++++++++++++-----------------------
25
include/block/aio.h | 20 +++-
20
1 file changed, 18 insertions(+), 23 deletions(-)
26
tests/test-aio.c | 3 +-
21
27
util/async.c | 237 ++++++++++++++++++++++++++------------------
22
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
28
3 files changed, 158 insertions(+), 102 deletions(-)
29
30
diff --git a/include/block/aio.h b/include/block/aio.h
23
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2-bitmap.c
32
--- a/include/block/aio.h
25
+++ b/block/qcow2-bitmap.c
33
+++ b/include/block/aio.h
26
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
34
@@ -XXX,XX +XXX,XX @@ struct ThreadPool;
27
Error **errp)
35
struct LinuxAioState;
28
{
36
struct LuringState;
29
BDRVQcow2State *s = bs->opaque;
37
30
- bool found;
38
+/*
31
- Qcow2BitmapList *bm_list;
39
+ * Each aio_bh_poll() call carves off a slice of the BH list, so that newly
32
+ BdrvDirtyBitmap *bitmap;
40
+ * scheduled BHs are not processed until the next aio_bh_poll() call. All
33
+ uint64_t bitmap_directory_size = 0;
41
+ * active aio_bh_poll() calls chain their slices together in a list, so that
34
+ uint32_t nb_bitmaps = 0;
42
+ * nested aio_bh_poll() calls process all scheduled bottom halves.
35
+
43
+ */
36
+ if (bdrv_find_dirty_bitmap(bs, name)) {
44
+typedef QSLIST_HEAD(, QEMUBH) BHList;
37
+ error_setg(errp, "Bitmap already exists: %s", name);
45
+typedef struct BHListSlice BHListSlice;
38
+ return false;
46
+struct BHListSlice {
47
+ BHList bh_list;
48
+ QSIMPLEQ_ENTRY(BHListSlice) next;
49
+};
50
+
51
struct AioContext {
52
GSource source;
53
54
@@ -XXX,XX +XXX,XX @@ struct AioContext {
55
*/
56
QemuLockCnt list_lock;
57
58
- /* Anchor of the list of Bottom Halves belonging to the context */
59
- struct QEMUBH *first_bh;
60
+ /* Bottom Halves pending aio_bh_poll() processing */
61
+ BHList bh_list;
62
+
63
+ /* Chained BH list slices for each nested aio_bh_poll() call */
64
+ QSIMPLEQ_HEAD(, BHListSlice) bh_slice_list;
65
66
/* Used by aio_notify.
67
*
68
diff --git a/tests/test-aio.c b/tests/test-aio.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/tests/test-aio.c
71
+++ b/tests/test-aio.c
72
@@ -XXX,XX +XXX,XX @@ static void test_source_bh_delete_from_cb(void)
73
g_assert_cmpint(data1.n, ==, data1.max);
74
g_assert(data1.bh == NULL);
75
76
- g_assert(!g_main_context_iteration(NULL, false));
77
+ assert(g_main_context_iteration(NULL, false));
78
+ assert(!g_main_context_iteration(NULL, false));
79
}
80
81
static void test_source_bh_delete_from_cb_many(void)
82
diff --git a/util/async.c b/util/async.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/util/async.c
85
+++ b/util/async.c
86
@@ -XXX,XX +XXX,XX @@
87
#include "block/thread-pool.h"
88
#include "qemu/main-loop.h"
89
#include "qemu/atomic.h"
90
+#include "qemu/rcu_queue.h"
91
#include "block/raw-aio.h"
92
#include "qemu/coroutine_int.h"
93
#include "trace.h"
94
@@ -XXX,XX +XXX,XX @@
95
/***********************************************************/
96
/* bottom halves (can be seen as timers which expire ASAP) */
97
98
+/* QEMUBH::flags values */
99
+enum {
100
+ /* Already enqueued and waiting for aio_bh_poll() */
101
+ BH_PENDING = (1 << 0),
102
+
103
+ /* Invoke the callback */
104
+ BH_SCHEDULED = (1 << 1),
105
+
106
+ /* Delete without invoking callback */
107
+ BH_DELETED = (1 << 2),
108
+
109
+ /* Delete after invoking callback */
110
+ BH_ONESHOT = (1 << 3),
111
+
112
+ /* Schedule periodically when the event loop is idle */
113
+ BH_IDLE = (1 << 4),
114
+};
115
+
116
struct QEMUBH {
117
AioContext *ctx;
118
QEMUBHFunc *cb;
119
void *opaque;
120
- QEMUBH *next;
121
- bool scheduled;
122
- bool idle;
123
- bool deleted;
124
+ QSLIST_ENTRY(QEMUBH) next;
125
+ unsigned flags;
126
};
127
128
+/* Called concurrently from any thread */
129
+static void aio_bh_enqueue(QEMUBH *bh, unsigned new_flags)
130
+{
131
+ AioContext *ctx = bh->ctx;
132
+ unsigned old_flags;
133
+
134
+ /*
135
+ * The memory barrier implicit in atomic_fetch_or makes sure that:
136
+ * 1. idle & any writes needed by the callback are done before the
137
+ * locations are read in the aio_bh_poll.
138
+ * 2. ctx is loaded before the callback has a chance to execute and bh
139
+ * could be freed.
140
+ */
141
+ old_flags = atomic_fetch_or(&bh->flags, BH_PENDING | new_flags);
142
+ if (!(old_flags & BH_PENDING)) {
143
+ QSLIST_INSERT_HEAD_ATOMIC(&ctx->bh_list, bh, next);
39
+ }
144
+ }
40
145
+
41
if (s->qcow_version < 3) {
146
+ aio_notify(ctx);
42
/* Without autoclear_features, we would always have to assume
147
+}
43
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
148
+
44
goto fail;
149
+/* Only called from aio_bh_poll() and aio_ctx_finalize() */
150
+static QEMUBH *aio_bh_dequeue(BHList *head, unsigned *flags)
151
+{
152
+ QEMUBH *bh = QSLIST_FIRST_RCU(head);
153
+
154
+ if (!bh) {
155
+ return NULL;
156
+ }
157
+
158
+ QSLIST_REMOVE_HEAD(head, next);
159
+
160
+ /*
161
+ * The atomic_and is paired with aio_bh_enqueue(). The implicit memory
162
+ * barrier ensures that the callback sees all writes done by the scheduling
163
+ * thread. It also ensures that the scheduling thread sees the cleared
164
+ * flag before bh->cb has run, and thus will call aio_notify again if
165
+ * necessary.
166
+ */
167
+ *flags = atomic_fetch_and(&bh->flags,
168
+ ~(BH_PENDING | BH_SCHEDULED | BH_IDLE));
169
+ return bh;
170
+}
171
+
172
void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
173
{
174
QEMUBH *bh;
175
@@ -XXX,XX +XXX,XX @@ void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
176
.cb = cb,
177
.opaque = opaque,
178
};
179
- qemu_lockcnt_lock(&ctx->list_lock);
180
- bh->next = ctx->first_bh;
181
- bh->scheduled = 1;
182
- bh->deleted = 1;
183
- /* Make sure that the members are ready before putting bh into list */
184
- smp_wmb();
185
- ctx->first_bh = bh;
186
- qemu_lockcnt_unlock(&ctx->list_lock);
187
- aio_notify(ctx);
188
+ aio_bh_enqueue(bh, BH_SCHEDULED | BH_ONESHOT);
189
}
190
191
QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
192
@@ -XXX,XX +XXX,XX @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
193
.cb = cb,
194
.opaque = opaque,
195
};
196
- qemu_lockcnt_lock(&ctx->list_lock);
197
- bh->next = ctx->first_bh;
198
- /* Make sure that the members are ready before putting bh into list */
199
- smp_wmb();
200
- ctx->first_bh = bh;
201
- qemu_lockcnt_unlock(&ctx->list_lock);
202
return bh;
203
}
204
205
@@ -XXX,XX +XXX,XX @@ void aio_bh_call(QEMUBH *bh)
206
bh->cb(bh->opaque);
207
}
208
209
-/* Multiple occurrences of aio_bh_poll cannot be called concurrently.
210
- * The count in ctx->list_lock is incremented before the call, and is
211
- * not affected by the call.
212
- */
213
+/* Multiple occurrences of aio_bh_poll cannot be called concurrently. */
214
int aio_bh_poll(AioContext *ctx)
215
{
216
- QEMUBH *bh, **bhp, *next;
217
- int ret;
218
- bool deleted = false;
219
-
220
- ret = 0;
221
- for (bh = atomic_rcu_read(&ctx->first_bh); bh; bh = next) {
222
- next = atomic_rcu_read(&bh->next);
223
- /* The atomic_xchg is paired with the one in qemu_bh_schedule. The
224
- * implicit memory barrier ensures that the callback sees all writes
225
- * done by the scheduling thread. It also ensures that the scheduling
226
- * thread sees the zero before bh->cb has run, and thus will call
227
- * aio_notify again if necessary.
228
- */
229
- if (atomic_xchg(&bh->scheduled, 0)) {
230
+ BHListSlice slice;
231
+ BHListSlice *s;
232
+ int ret = 0;
233
+
234
+ QSLIST_MOVE_ATOMIC(&slice.bh_list, &ctx->bh_list);
235
+ QSIMPLEQ_INSERT_TAIL(&ctx->bh_slice_list, &slice, next);
236
+
237
+ while ((s = QSIMPLEQ_FIRST(&ctx->bh_slice_list))) {
238
+ QEMUBH *bh;
239
+ unsigned flags;
240
+
241
+ bh = aio_bh_dequeue(&s->bh_list, &flags);
242
+ if (!bh) {
243
+ QSIMPLEQ_REMOVE_HEAD(&ctx->bh_slice_list, next);
244
+ continue;
245
+ }
246
+
247
+ if ((flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) {
248
/* Idle BHs don't count as progress */
249
- if (!bh->idle) {
250
+ if (!(flags & BH_IDLE)) {
251
ret = 1;
252
}
253
- bh->idle = 0;
254
aio_bh_call(bh);
255
}
256
- if (bh->deleted) {
257
- deleted = true;
258
+ if (flags & (BH_DELETED | BH_ONESHOT)) {
259
+ g_free(bh);
260
}
45
}
261
}
46
262
47
- if (s->nb_bitmaps == 0) {
263
- /* remove deleted bhs */
48
- return true;
264
- if (!deleted) {
49
+ FOR_EACH_DIRTY_BITMAP(bs, bitmap) {
265
- return ret;
50
+ if (bdrv_dirty_bitmap_get_persistence(bitmap)) {
51
+ nb_bitmaps++;
52
+ bitmap_directory_size +=
53
+ calc_dir_entry_size(strlen(bdrv_dirty_bitmap_name(bitmap)), 0);
54
+ }
55
}
56
+ nb_bitmaps++;
57
+ bitmap_directory_size += calc_dir_entry_size(strlen(name), 0);
58
59
- if (s->nb_bitmaps >= QCOW2_MAX_BITMAPS) {
60
+ if (nb_bitmaps > QCOW2_MAX_BITMAPS) {
61
error_setg(errp,
62
"Maximum number of persistent bitmaps is already reached");
63
goto fail;
64
}
65
66
- if (s->bitmap_directory_size + calc_dir_entry_size(strlen(name), 0) >
67
- QCOW2_MAX_BITMAP_DIRECTORY_SIZE)
68
- {
69
+ if (bitmap_directory_size > QCOW2_MAX_BITMAP_DIRECTORY_SIZE) {
70
error_setg(errp, "Not enough space in the bitmap directory");
71
goto fail;
72
}
73
74
- qemu_co_mutex_lock(&s->lock);
75
- bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
76
- s->bitmap_directory_size, errp);
77
- qemu_co_mutex_unlock(&s->lock);
78
- if (bm_list == NULL) {
79
- goto fail;
80
- }
266
- }
81
-
267
-
82
- found = find_bitmap_by_name(bm_list, name);
268
- if (qemu_lockcnt_dec_if_lock(&ctx->list_lock)) {
83
- bitmap_list_free(bm_list);
269
- bhp = &ctx->first_bh;
84
- if (found) {
270
- while (*bhp) {
85
- error_setg(errp, "Bitmap with the same name is already stored");
271
- bh = *bhp;
86
- goto fail;
272
- if (bh->deleted && !bh->scheduled) {
273
- *bhp = bh->next;
274
- g_free(bh);
275
- } else {
276
- bhp = &bh->next;
277
- }
278
- }
279
- qemu_lockcnt_inc_and_unlock(&ctx->list_lock);
87
- }
280
- }
281
return ret;
282
}
283
284
void qemu_bh_schedule_idle(QEMUBH *bh)
285
{
286
- bh->idle = 1;
287
- /* Make sure that idle & any writes needed by the callback are done
288
- * before the locations are read in the aio_bh_poll.
289
- */
290
- atomic_mb_set(&bh->scheduled, 1);
291
+ aio_bh_enqueue(bh, BH_SCHEDULED | BH_IDLE);
292
}
293
294
void qemu_bh_schedule(QEMUBH *bh)
295
{
296
- AioContext *ctx;
88
-
297
-
89
return true;
298
- ctx = bh->ctx;
90
299
- bh->idle = 0;
91
fail:
300
- /* The memory barrier implicit in atomic_xchg makes sure that:
301
- * 1. idle & any writes needed by the callback are done before the
302
- * locations are read in the aio_bh_poll.
303
- * 2. ctx is loaded before scheduled is set and the callback has a chance
304
- * to execute.
305
- */
306
- if (atomic_xchg(&bh->scheduled, 1) == 0) {
307
- aio_notify(ctx);
308
- }
309
+ aio_bh_enqueue(bh, BH_SCHEDULED);
310
}
311
312
-
313
/* This func is async.
314
*/
315
void qemu_bh_cancel(QEMUBH *bh)
316
{
317
- atomic_mb_set(&bh->scheduled, 0);
318
+ atomic_and(&bh->flags, ~BH_SCHEDULED);
319
}
320
321
/* This func is async.The bottom half will do the delete action at the finial
322
@@ -XXX,XX +XXX,XX @@ void qemu_bh_cancel(QEMUBH *bh)
323
*/
324
void qemu_bh_delete(QEMUBH *bh)
325
{
326
- bh->scheduled = 0;
327
- bh->deleted = 1;
328
+ aio_bh_enqueue(bh, BH_DELETED);
329
}
330
331
-int64_t
332
-aio_compute_timeout(AioContext *ctx)
333
+static int64_t aio_compute_bh_timeout(BHList *head, int timeout)
334
{
335
- int64_t deadline;
336
- int timeout = -1;
337
QEMUBH *bh;
338
339
- for (bh = atomic_rcu_read(&ctx->first_bh); bh;
340
- bh = atomic_rcu_read(&bh->next)) {
341
- if (bh->scheduled) {
342
- if (bh->idle) {
343
+ QSLIST_FOREACH_RCU(bh, head, next) {
344
+ if ((bh->flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) {
345
+ if (bh->flags & BH_IDLE) {
346
/* idle bottom halves will be polled at least
347
* every 10ms */
348
timeout = 10000000;
349
@@ -XXX,XX +XXX,XX @@ aio_compute_timeout(AioContext *ctx)
350
}
351
}
352
353
+ return timeout;
354
+}
355
+
356
+int64_t
357
+aio_compute_timeout(AioContext *ctx)
358
+{
359
+ BHListSlice *s;
360
+ int64_t deadline;
361
+ int timeout = -1;
362
+
363
+ timeout = aio_compute_bh_timeout(&ctx->bh_list, timeout);
364
+ if (timeout == 0) {
365
+ return 0;
366
+ }
367
+
368
+ QSIMPLEQ_FOREACH(s, &ctx->bh_slice_list, next) {
369
+ timeout = aio_compute_bh_timeout(&s->bh_list, timeout);
370
+ if (timeout == 0) {
371
+ return 0;
372
+ }
373
+ }
374
+
375
deadline = timerlistgroup_deadline_ns(&ctx->tlg);
376
if (deadline == 0) {
377
return 0;
378
@@ -XXX,XX +XXX,XX @@ aio_ctx_check(GSource *source)
379
{
380
AioContext *ctx = (AioContext *) source;
381
QEMUBH *bh;
382
+ BHListSlice *s;
383
384
atomic_and(&ctx->notify_me, ~1);
385
aio_notify_accept(ctx);
386
387
- for (bh = ctx->first_bh; bh; bh = bh->next) {
388
- if (bh->scheduled) {
389
+ QSLIST_FOREACH_RCU(bh, &ctx->bh_list, next) {
390
+ if ((bh->flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) {
391
return true;
392
}
393
}
394
+
395
+ QSIMPLEQ_FOREACH(s, &ctx->bh_slice_list, next) {
396
+ QSLIST_FOREACH_RCU(bh, &s->bh_list, next) {
397
+ if ((bh->flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) {
398
+ return true;
399
+ }
400
+ }
401
+ }
402
return aio_pending(ctx) || (timerlistgroup_deadline_ns(&ctx->tlg) == 0);
403
}
404
405
@@ -XXX,XX +XXX,XX @@ static void
406
aio_ctx_finalize(GSource *source)
407
{
408
AioContext *ctx = (AioContext *) source;
409
+ QEMUBH *bh;
410
+ unsigned flags;
411
412
thread_pool_free(ctx->thread_pool);
413
414
@@ -XXX,XX +XXX,XX @@ aio_ctx_finalize(GSource *source)
415
assert(QSLIST_EMPTY(&ctx->scheduled_coroutines));
416
qemu_bh_delete(ctx->co_schedule_bh);
417
418
- qemu_lockcnt_lock(&ctx->list_lock);
419
- assert(!qemu_lockcnt_count(&ctx->list_lock));
420
- while (ctx->first_bh) {
421
- QEMUBH *next = ctx->first_bh->next;
422
+ /* There must be no aio_bh_poll() calls going on */
423
+ assert(QSIMPLEQ_EMPTY(&ctx->bh_slice_list));
424
425
+ while ((bh = aio_bh_dequeue(&ctx->bh_list, &flags))) {
426
/* qemu_bh_delete() must have been called on BHs in this AioContext */
427
- assert(ctx->first_bh->deleted);
428
+ assert(flags & BH_DELETED);
429
430
- g_free(ctx->first_bh);
431
- ctx->first_bh = next;
432
+ g_free(bh);
433
}
434
- qemu_lockcnt_unlock(&ctx->list_lock);
435
436
aio_set_event_notifier(ctx, &ctx->notifier, false, NULL, NULL);
437
event_notifier_cleanup(&ctx->notifier);
438
@@ -XXX,XX +XXX,XX @@ AioContext *aio_context_new(Error **errp)
439
AioContext *ctx;
440
441
ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
442
+ QSLIST_INIT(&ctx->bh_list);
443
+ QSIMPLEQ_INIT(&ctx->bh_slice_list);
444
aio_context_setup(ctx);
445
446
ret = event_notifier_init(&ctx->notifier, false);
92
--
447
--
93
2.24.1
448
2.24.1
94
449
95
diff view generated by jsdifflib
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
1
epoll_handler is a stack variable and must not be accessed after it goes
2
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
2
out of scope:
3
Message-id: 20191107163708.833192-13-mreitz@redhat.com
3
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
5
AioHandler epoll_handler;
6
...
7
add_pollfd(&epoll_handler);
8
ret = aio_epoll(ctx, pollfds, npfd, timeout);
9
} ...
10
11
...
12
13
/* if we have any readable fds, dispatch event */
14
if (ret > 0) {
15
for (i = 0; i < npfd; i++) {
16
nodes[i]->pfd.revents = pollfds[i].revents;
17
}
18
}
19
20
nodes[0] is &epoll_handler, which has already gone out of scope.
21
22
There is no need to use pollfds[] for epoll. We don't need an
23
AioHandler for the epoll fd.
24
25
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
26
Reviewed-by: Sergio Lopez <slp@redhat.com>
27
Message-id: 20200214171712.541358-2-stefanha@redhat.com
28
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
---
29
---
6
tests/qemu-iotests/071 | 4 ++--
30
util/aio-posix.c | 20 ++++++++------------
7
tests/qemu-iotests/174 | 2 +-
31
1 file changed, 8 insertions(+), 12 deletions(-)
8
tests/qemu-iotests/178 | 4 ++--
9
tests/qemu-iotests/197 | 4 ++--
10
tests/qemu-iotests/215 | 4 ++--
11
5 files changed, 9 insertions(+), 9 deletions(-)
12
32
13
diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
33
diff --git a/util/aio-posix.c b/util/aio-posix.c
14
index XXXXXXX..XXXXXXX 100755
34
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/071
35
--- a/util/aio-posix.c
16
+++ b/tests/qemu-iotests/071
36
+++ b/util/aio-posix.c
17
@@ -XXX,XX +XXX,XX @@ echo
37
@@ -XXX,XX +XXX,XX @@ static void aio_epoll_update(AioContext *ctx, AioHandler *node, bool is_new)
18
echo "=== Testing blkverify through filename ==="
38
}
19
echo
20
21
-TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\
22
+TEST_IMG="$TEST_IMG.base" IMGFMT="raw" _make_test_img --no-opts $IMG_SIZE |\
23
_filter_imgfmt
24
_make_test_img $IMG_SIZE
25
$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \
26
@@ -XXX,XX +XXX,XX @@ echo
27
echo "=== Testing blkverify through file blockref ==="
28
echo
29
30
-TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\
31
+TEST_IMG="$TEST_IMG.base" IMGFMT="raw" _make_test_img --no-opts $IMG_SIZE |\
32
_filter_imgfmt
33
_make_test_img $IMG_SIZE
34
$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base,file.test.driver=$IMGFMT,file.test.file.filename=$TEST_IMG" \
35
diff --git a/tests/qemu-iotests/174 b/tests/qemu-iotests/174
36
index XXXXXXX..XXXXXXX 100755
37
--- a/tests/qemu-iotests/174
38
+++ b/tests/qemu-iotests/174
39
@@ -XXX,XX +XXX,XX @@ _unsupported_fmt raw
40
41
42
size=256K
43
-IMGFMT=raw IMGKEYSECRET= IMGOPTS= _make_test_img $size | _filter_imgfmt
44
+IMGFMT=raw IMGKEYSECRET= _make_test_img --no-opts $size | _filter_imgfmt
45
46
echo
47
echo "== reading wrong format should fail =="
48
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
49
index XXXXXXX..XXXXXXX 100755
50
--- a/tests/qemu-iotests/178
51
+++ b/tests/qemu-iotests/178
52
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG measure -O foo "$TEST_IMG" # unknown image file format
53
54
make_test_img_with_fmt() {
55
# Shadow global variables within this function
56
- local IMGFMT="$1" IMGOPTS=""
57
- _make_test_img "$2"
58
+ local IMGFMT="$1"
59
+ _make_test_img --no-opts "$2"
60
}
39
}
61
40
62
qemu_io_with_fmt() {
41
-static int aio_epoll(AioContext *ctx, GPollFD *pfds,
63
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
42
- unsigned npfd, int64_t timeout)
64
index XXXXXXX..XXXXXXX 100755
43
+static int aio_epoll(AioContext *ctx, int64_t timeout)
65
--- a/tests/qemu-iotests/197
44
{
66
+++ b/tests/qemu-iotests/197
45
+ GPollFD pfd = {
67
@@ -XXX,XX +XXX,XX @@ if [ "$IMGFMT" = "vpc" ]; then
46
+ .fd = ctx->epollfd,
68
fi
47
+ .events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR,
69
_make_test_img 4G
48
+ };
70
$QEMU_IO -c "write -P 55 3G 1k" "$TEST_IMG" | _filter_qemu_io
49
AioHandler *node;
71
-IMGPROTO=file IMGFMT=qcow2 IMGOPTS= TEST_IMG_FILE="$TEST_WRAP" \
50
int i, ret = 0;
72
- _make_test_img -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
51
struct epoll_event events[128];
73
+IMGPROTO=file IMGFMT=qcow2 TEST_IMG_FILE="$TEST_WRAP" \
52
74
+ _make_test_img --no-opts -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
53
- assert(npfd == 1);
75
$QEMU_IO -f qcow2 -c "write -z -u 1M 64k" "$TEST_WRAP" | _filter_qemu_io
54
- assert(pfds[0].fd == ctx->epollfd);
76
55
if (timeout > 0) {
77
# Ensure that a read of two clusters, but where one is already allocated,
56
- ret = qemu_poll_ns(pfds, npfd, timeout);
78
diff --git a/tests/qemu-iotests/215 b/tests/qemu-iotests/215
57
+ ret = qemu_poll_ns(&pfd, 1, timeout);
79
index XXXXXXX..XXXXXXX 100755
58
}
80
--- a/tests/qemu-iotests/215
59
if (timeout <= 0 || ret > 0) {
81
+++ b/tests/qemu-iotests/215
60
ret = epoll_wait(ctx->epollfd, events,
82
@@ -XXX,XX +XXX,XX @@ if [ "$IMGFMT" = "vpc" ]; then
61
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
83
fi
62
84
_make_test_img 4G
63
/* wait until next event */
85
$QEMU_IO -c "write -P 55 3G 1k" "$TEST_IMG" | _filter_qemu_io
64
if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
86
-IMGPROTO=file IMGFMT=qcow2 IMGOPTS= TEST_IMG_FILE="$TEST_WRAP" \
65
- AioHandler epoll_handler;
87
- _make_test_img -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
66
-
88
+IMGPROTO=file IMGFMT=qcow2 TEST_IMG_FILE="$TEST_WRAP" \
67
- epoll_handler.pfd.fd = ctx->epollfd;
89
+ _make_test_img --no-opts -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
68
- epoll_handler.pfd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR;
90
$QEMU_IO -f qcow2 -c "write -z -u 1M 64k" "$TEST_WRAP" | _filter_qemu_io
69
- npfd = 0;
91
70
- add_pollfd(&epoll_handler);
92
# Ensure that a read of two clusters, but where one is already allocated,
71
- ret = aio_epoll(ctx, pollfds, npfd, timeout);
72
+ npfd = 0; /* pollfds[] is not being used */
73
+ ret = aio_epoll(ctx, timeout);
74
} else {
75
ret = qemu_poll_ns(pollfds, npfd, timeout);
76
}
93
--
77
--
94
2.24.1
78
2.24.1
95
79
96
diff view generated by jsdifflib
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
1
Don't pass the nanosecond timeout into epoll_wait(), which expects
2
Message-id: 20191107163708.833192-22-mreitz@redhat.com
2
milliseconds.
3
[mreitz: Also disable 273]
3
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
The epoll_wait() timeout value does not matter if qemu_poll_ns()
5
determined that the poll fd is ready, but passing a value in the wrong
6
units is still ugly. Pass a 0 timeout to epoll_wait() instead.
7
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Sergio Lopez <slp@redhat.com>
10
Message-id: 20200214171712.541358-3-stefanha@redhat.com
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
---
12
---
6
tests/qemu-iotests/007 | 5 +++--
13
util/aio-posix.c | 3 +++
7
tests/qemu-iotests/014 | 2 ++
14
1 file changed, 3 insertions(+)
8
tests/qemu-iotests/015 | 5 +++--
9
tests/qemu-iotests/026 | 5 ++++-
10
tests/qemu-iotests/029 | 5 +++--
11
tests/qemu-iotests/031 | 6 +++---
12
tests/qemu-iotests/036 | 5 +++--
13
tests/qemu-iotests/039 | 3 +++
14
tests/qemu-iotests/046 | 2 ++
15
tests/qemu-iotests/048 | 2 ++
16
tests/qemu-iotests/051 | 5 +++--
17
tests/qemu-iotests/058 | 5 +++--
18
tests/qemu-iotests/060 | 6 ++++--
19
tests/qemu-iotests/061 | 6 ++++--
20
tests/qemu-iotests/062 | 2 +-
21
tests/qemu-iotests/066 | 4 +++-
22
tests/qemu-iotests/067 | 6 ++++--
23
tests/qemu-iotests/068 | 5 +++--
24
tests/qemu-iotests/071 | 3 +++
25
tests/qemu-iotests/073 | 4 ++++
26
tests/qemu-iotests/074 | 2 ++
27
tests/qemu-iotests/080 | 5 +++--
28
tests/qemu-iotests/090 | 2 ++
29
tests/qemu-iotests/098 | 6 ++++--
30
tests/qemu-iotests/099 | 3 ++-
31
tests/qemu-iotests/103 | 5 +++--
32
tests/qemu-iotests/108 | 6 ++++--
33
tests/qemu-iotests/112 | 5 +++--
34
tests/qemu-iotests/114 | 2 ++
35
tests/qemu-iotests/121 | 3 +++
36
tests/qemu-iotests/138 | 3 +++
37
tests/qemu-iotests/156 | 2 ++
38
tests/qemu-iotests/176 | 7 +++++--
39
tests/qemu-iotests/191 | 2 ++
40
tests/qemu-iotests/201 | 6 +++---
41
tests/qemu-iotests/214 | 3 ++-
42
tests/qemu-iotests/217 | 3 ++-
43
tests/qemu-iotests/220 | 5 +++--
44
tests/qemu-iotests/243 | 6 ++++--
45
tests/qemu-iotests/244 | 5 +++--
46
tests/qemu-iotests/250 | 2 ++
47
tests/qemu-iotests/261 | 3 ++-
48
tests/qemu-iotests/267 | 5 +++--
49
tests/qemu-iotests/273 | 3 +++
50
44 files changed, 127 insertions(+), 53 deletions(-)
51
15
52
diff --git a/tests/qemu-iotests/007 b/tests/qemu-iotests/007
16
diff --git a/util/aio-posix.c b/util/aio-posix.c
53
index XXXXXXX..XXXXXXX 100755
17
index XXXXXXX..XXXXXXX 100644
54
--- a/tests/qemu-iotests/007
18
--- a/util/aio-posix.c
55
+++ b/tests/qemu-iotests/007
19
+++ b/util/aio-posix.c
56
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
20
@@ -XXX,XX +XXX,XX @@ static int aio_epoll(AioContext *ctx, int64_t timeout)
57
_supported_fmt qcow2
21
58
_supported_proto generic
22
if (timeout > 0) {
59
# refcount_bits must be at least 4 so we can create ten internal snapshots
23
ret = qemu_poll_ns(&pfd, 1, timeout);
60
-# (1 bit supports none, 2 bits support two, 4 bits support 14)
24
+ if (ret > 0) {
61
-_unsupported_imgopts 'refcount_bits=\(1\|2\)[^0-9]'
25
+ timeout = 0;
62
+# (1 bit supports none, 2 bits support two, 4 bits support 14);
26
+ }
63
+# snapshot are generally impossible with external data files
27
}
64
+_unsupported_imgopts 'refcount_bits=\(1\|2\)[^0-9]' data_file
28
if (timeout <= 0 || ret > 0) {
65
29
ret = epoll_wait(ctx->epollfd, events,
66
echo
67
echo "creating image"
68
diff --git a/tests/qemu-iotests/014 b/tests/qemu-iotests/014
69
index XXXXXXX..XXXXXXX 100755
70
--- a/tests/qemu-iotests/014
71
+++ b/tests/qemu-iotests/014
72
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
73
_supported_fmt qcow2
74
_supported_proto file
75
_supported_os Linux
76
+# Compression and snapshots do not work with external data files
77
+_unsupported_imgopts data_file
78
79
TEST_OFFSETS="0 4294967296"
80
TEST_OPS="writev read write readv"
81
diff --git a/tests/qemu-iotests/015 b/tests/qemu-iotests/015
82
index XXXXXXX..XXXXXXX 100755
83
--- a/tests/qemu-iotests/015
84
+++ b/tests/qemu-iotests/015
85
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
86
# actually any format that supports snapshots
87
_supported_fmt qcow2
88
_supported_proto generic
89
-# Internal snapshots are (currently) impossible with refcount_bits=1
90
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
91
+# Internal snapshots are (currently) impossible with refcount_bits=1,
92
+# and generally impossible with external data files
93
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
94
95
echo
96
echo "creating image"
97
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
98
index XXXXXXX..XXXXXXX 100755
99
--- a/tests/qemu-iotests/026
100
+++ b/tests/qemu-iotests/026
101
@@ -XXX,XX +XXX,XX @@ _supported_cache_modes writethrough none
102
# 32 and 64 bits do not work either, however, due to different leaked cluster
103
# count on error.
104
# Thus, the only remaining option is refcount_bits=16.
105
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
106
+#
107
+# As for data_file, none of the refcount tests can work for it.
108
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' \
109
+ data_file
110
111
echo "Errors while writing 128 kB"
112
echo
113
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
114
index XXXXXXX..XXXXXXX 100755
115
--- a/tests/qemu-iotests/029
116
+++ b/tests/qemu-iotests/029
117
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
118
_supported_fmt qcow2
119
_supported_proto generic
120
_unsupported_proto vxhs
121
-# Internal snapshots are (currently) impossible with refcount_bits=1
122
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
123
+# Internal snapshots are (currently) impossible with refcount_bits=1,
124
+# and generally impossible with external data files
125
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
126
127
offset_size=24
128
offset_l1_size=36
129
diff --git a/tests/qemu-iotests/031 b/tests/qemu-iotests/031
130
index XXXXXXX..XXXXXXX 100755
131
--- a/tests/qemu-iotests/031
132
+++ b/tests/qemu-iotests/031
133
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
134
# This tests qcow2-specific low-level functionality
135
_supported_fmt qcow2
136
_supported_proto file
137
-# We want to test compat=0.10, which does not support refcount widths
138
-# other than 16
139
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
140
+# We want to test compat=0.10, which does not support external data
141
+# files or refcount widths other than 16
142
+_unsupported_imgopts data_file 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
143
144
CLUSTER_SIZE=65536
145
146
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
147
index XXXXXXX..XXXXXXX 100755
148
--- a/tests/qemu-iotests/036
149
+++ b/tests/qemu-iotests/036
150
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
151
# This tests qcow2-specific low-level functionality
152
_supported_fmt qcow2
153
_supported_proto file
154
-# Only qcow2v3 and later supports feature bits
155
-_unsupported_imgopts 'compat=0.10'
156
+# Only qcow2v3 and later supports feature bits;
157
+# qcow2.py does not support external data files
158
+_unsupported_imgopts 'compat=0.10' data_file
159
160
echo
161
echo === Image with unknown incompatible feature bit ===
162
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
163
index XXXXXXX..XXXXXXX 100755
164
--- a/tests/qemu-iotests/039
165
+++ b/tests/qemu-iotests/039
166
@@ -XXX,XX +XXX,XX @@ _supported_proto file
167
_supported_os Linux
168
_default_cache_mode writethrough
169
_supported_cache_modes writethrough
170
+# Some of these test cases expect no external data file so that all
171
+# clusters are part of the qcow2 image and refcounted
172
+_unsupported_imgopts data_file
173
174
size=128M
175
176
diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046
177
index XXXXXXX..XXXXXXX 100755
178
--- a/tests/qemu-iotests/046
179
+++ b/tests/qemu-iotests/046
180
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
181
182
_supported_fmt qcow2
183
_supported_proto file
184
+# data_file does not support compressed clusters
185
+_unsupported_imgopts data_file
186
187
CLUSTER_SIZE=64k
188
size=128M
189
diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048
190
index XXXXXXX..XXXXXXX 100755
191
--- a/tests/qemu-iotests/048
192
+++ b/tests/qemu-iotests/048
193
@@ -XXX,XX +XXX,XX @@ _compare()
194
_supported_fmt raw qcow2 qed luks
195
_supported_proto file
196
_supported_os Linux
197
+# Using 'cp' is incompatible with external data files
198
+_unsupported_imgopts data_file
199
200
# Remove once all tests are fixed to use TEST_IMG_FILE
201
# correctly and common.rc sets it unconditionally
202
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
203
index XXXXXXX..XXXXXXX 100755
204
--- a/tests/qemu-iotests/051
205
+++ b/tests/qemu-iotests/051
206
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
207
_supported_fmt qcow2
208
_supported_proto file
209
# A compat=0.10 image is created in this test which does not support anything
210
-# other than refcount_bits=16
211
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
212
+# other than refcount_bits=16;
213
+# it also will not support an external data file
214
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
215
_require_drivers nbd
216
217
do_run_qemu()
218
diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058
219
index XXXXXXX..XXXXXXX 100755
220
--- a/tests/qemu-iotests/058
221
+++ b/tests/qemu-iotests/058
222
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow2
223
_supported_proto file
224
_supported_os Linux
225
_require_command QEMU_NBD
226
-# Internal snapshots are (currently) impossible with refcount_bits=1
227
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
228
+# Internal snapshots are (currently) impossible with refcount_bits=1,
229
+# and generally impossible with external data files
230
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
231
232
nbd_snapshot_img="nbd:unix:$nbd_unix_socket"
233
234
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
235
index XXXXXXX..XXXXXXX 100755
236
--- a/tests/qemu-iotests/060
237
+++ b/tests/qemu-iotests/060
238
@@ -XXX,XX +XXX,XX @@ _filter_io_error()
239
_supported_fmt qcow2
240
_supported_proto file
241
_supported_os Linux
242
-# These tests only work for compat=1.1 images with refcount_bits=16
243
-_unsupported_imgopts 'compat=0.10' 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
244
+# These tests only work for compat=1.1 images without an external
245
+# data file with refcount_bits=16
246
+_unsupported_imgopts 'compat=0.10' data_file \
247
+ 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
248
249
# The repair process will create a large file - so check for availability first
250
_require_large_file 64G
251
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
252
index XXXXXXX..XXXXXXX 100755
253
--- a/tests/qemu-iotests/061
254
+++ b/tests/qemu-iotests/061
255
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow2
256
_supported_proto file
257
_supported_os Linux
258
# Conversion between different compat versions can only really work
259
-# with refcount_bits=16
260
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
261
+# with refcount_bits=16;
262
+# we have explicit tests for data_file here, but the whole test does
263
+# not work with it
264
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
265
266
echo
267
echo "=== Testing version downgrade with zero expansion ==="
268
diff --git a/tests/qemu-iotests/062 b/tests/qemu-iotests/062
269
index XXXXXXX..XXXXXXX 100755
270
--- a/tests/qemu-iotests/062
271
+++ b/tests/qemu-iotests/062
272
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
273
_supported_fmt qcow2
274
_supported_proto generic
275
# We need zero clusters and snapshots
276
-_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
277
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
278
279
IMG_SIZE=64M
280
281
diff --git a/tests/qemu-iotests/066 b/tests/qemu-iotests/066
282
index XXXXXXX..XXXXXXX 100755
283
--- a/tests/qemu-iotests/066
284
+++ b/tests/qemu-iotests/066
285
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
286
_supported_fmt qcow2
287
_supported_proto generic
288
# We need zero clusters and snapshots
289
-_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
290
+# (TODO: Consider splitting the snapshot part into a separate test
291
+# file, so this one runs with refcount_bits=1 and data_file)
292
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
293
294
# Intentionally create an unaligned image
295
IMG_SIZE=$((64 * 1024 * 1024 + 512))
296
diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067
297
index XXXXXXX..XXXXXXX 100755
298
--- a/tests/qemu-iotests/067
299
+++ b/tests/qemu-iotests/067
300
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
301
302
_supported_fmt qcow2
303
_supported_proto file
304
-# Because anything other than 16 would change the output of query-block
305
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
306
+# Because anything other than 16 would change the output of query-block,
307
+# and external data files would change the output of
308
+# query-named-block-nodes
309
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
310
311
do_run_qemu()
312
{
313
diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068
314
index XXXXXXX..XXXXXXX 100755
315
--- a/tests/qemu-iotests/068
316
+++ b/tests/qemu-iotests/068
317
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
318
# This tests qcow2-specific low-level functionality
319
_supported_fmt qcow2
320
_supported_proto generic
321
-# Internal snapshots are (currently) impossible with refcount_bits=1
322
-_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
323
+# Internal snapshots are (currently) impossible with refcount_bits=1,
324
+# and generally impossible with external data files
325
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
326
327
IMG_SIZE=128K
328
329
diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
330
index XXXXXXX..XXXXXXX 100755
331
--- a/tests/qemu-iotests/071
332
+++ b/tests/qemu-iotests/071
333
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
334
_supported_fmt qcow2
335
_supported_proto file
336
_require_drivers blkdebug blkverify
337
+# blkdebug can only inject errors on bs->file, not on the data_file,
338
+# so thie test does not work with external data files
339
+_unsupported_imgopts data_file
340
341
do_run_qemu()
342
{
343
diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073
344
index XXXXXXX..XXXXXXX 100755
345
--- a/tests/qemu-iotests/073
346
+++ b/tests/qemu-iotests/073
347
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
348
_supported_fmt qcow2
349
_supported_proto generic
350
_unsupported_proto vxhs
351
+# External data files do not support compressed clusters
352
+# (TODO: Consider writing a version for external data files that does
353
+# not test compressed clusters)
354
+_unsupported_imgopts data_file
355
356
CLUSTER_SIZE=64k
357
size=128M
358
diff --git a/tests/qemu-iotests/074 b/tests/qemu-iotests/074
359
index XXXXXXX..XXXXXXX 100755
360
--- a/tests/qemu-iotests/074
361
+++ b/tests/qemu-iotests/074
362
@@ -XXX,XX +XXX,XX @@ _compare()
363
_supported_fmt qcow2
364
_supported_proto file
365
_supported_os Linux
366
+# blkdebug can only inject errors on bs->file
367
+_unsupported_imgopts data_file
368
369
# Setup test basic parameters
370
TEST_IMG2=$TEST_IMG.2
371
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
372
index XXXXXXX..XXXXXXX 100755
373
--- a/tests/qemu-iotests/080
374
+++ b/tests/qemu-iotests/080
375
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
376
_supported_fmt qcow2
377
_supported_proto file
378
_supported_os Linux
379
-# - Internal snapshots are (currently) impossible with refcount_bits=1
380
+# - Internal snapshots are (currently) impossible with refcount_bits=1,
381
+# and generally impossible with external data files
382
# - This is generally a test for compat=1.1 images
383
-_unsupported_imgopts 'refcount_bits=1[^0-9]' 'compat=0.10'
384
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file 'compat=0.10'
385
386
header_size=104
387
388
diff --git a/tests/qemu-iotests/090 b/tests/qemu-iotests/090
389
index XXXXXXX..XXXXXXX 100755
390
--- a/tests/qemu-iotests/090
391
+++ b/tests/qemu-iotests/090
392
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
393
394
_supported_fmt qcow2
395
_supported_proto file nfs
396
+# External data files do not support compressed clusters
397
+_unsupported_imgopts data_file
398
399
IMG_SIZE=128K
400
401
diff --git a/tests/qemu-iotests/098 b/tests/qemu-iotests/098
402
index XXXXXXX..XXXXXXX 100755
403
--- a/tests/qemu-iotests/098
404
+++ b/tests/qemu-iotests/098
405
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
406
407
_supported_fmt qcow2
408
_supported_proto file
409
-# The code path we want to test here only works for compat=1.1 images
410
-_unsupported_imgopts 'compat=0.10'
411
+# The code path we want to test here only works for compat=1.1 images;
412
+# blkdebug can only inject errors on bs->file, so external data files
413
+# do not work with this test
414
+_unsupported_imgopts 'compat=0.10' data_file
415
416
for event in l1_update empty_image_prepare reftable_update refblock_alloc; do
417
418
diff --git a/tests/qemu-iotests/099 b/tests/qemu-iotests/099
419
index XXXXXXX..XXXXXXX 100755
420
--- a/tests/qemu-iotests/099
421
+++ b/tests/qemu-iotests/099
422
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow qcow2 qed vdi vhdx vmdk vpc
423
_supported_proto file
424
_supported_os Linux
425
_require_drivers blkdebug blkverify
426
+# data_file would change the json:{} filenames
427
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
428
- "subformat=twoGbMaxExtentSparse"
429
+ "subformat=twoGbMaxExtentSparse" data_file
430
431
do_run_qemu()
432
{
433
diff --git a/tests/qemu-iotests/103 b/tests/qemu-iotests/103
434
index XXXXXXX..XXXXXXX 100755
435
--- a/tests/qemu-iotests/103
436
+++ b/tests/qemu-iotests/103
437
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
438
439
_supported_fmt qcow2
440
_supported_proto file nfs
441
-# Internal snapshots are (currently) impossible with refcount_bits=1
442
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
443
+# Internal snapshots are (currently) impossible with refcount_bits=1,
444
+# and generally impossible with external data files
445
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
446
447
IMG_SIZE=64K
448
449
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
450
index XXXXXXX..XXXXXXX 100755
451
--- a/tests/qemu-iotests/108
452
+++ b/tests/qemu-iotests/108
453
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
454
_supported_fmt qcow2
455
_supported_proto file
456
_supported_os Linux
457
-# This test directly modifies a refblock so it relies on refcount_bits being 16
458
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
459
+# This test directly modifies a refblock so it relies on refcount_bits being 16;
460
+# and the low-level modification it performs are not tuned for external data
461
+# files
462
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
463
464
echo
465
echo '=== Repairing an image without any refcount table ==='
466
diff --git a/tests/qemu-iotests/112 b/tests/qemu-iotests/112
467
index XXXXXXX..XXXXXXX 100755
468
--- a/tests/qemu-iotests/112
469
+++ b/tests/qemu-iotests/112
470
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
471
_supported_fmt qcow2
472
_supported_proto file
473
# This test will set refcount_bits on its own which would conflict with the
474
-# manual setting; compat will be overridden as well
475
-_unsupported_imgopts refcount_bits 'compat=0.10'
476
+# manual setting; compat will be overridden as well;
477
+# and external data files do not work well with our refcount testing
478
+_unsupported_imgopts refcount_bits 'compat=0.10' data_file
479
480
print_refcount_bits()
481
{
482
diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114
483
index XXXXXXX..XXXXXXX 100755
484
--- a/tests/qemu-iotests/114
485
+++ b/tests/qemu-iotests/114
486
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
487
_supported_fmt qcow2
488
_supported_proto generic
489
_unsupported_proto vxhs
490
+# qcow2.py does not work too well with external data files
491
+_unsupported_imgopts data_file
492
493
494
TEST_IMG="$TEST_IMG.base" _make_test_img 64M
495
diff --git a/tests/qemu-iotests/121 b/tests/qemu-iotests/121
496
index XXXXXXX..XXXXXXX 100755
497
--- a/tests/qemu-iotests/121
498
+++ b/tests/qemu-iotests/121
499
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
500
_supported_fmt qcow2
501
_supported_proto file
502
_supported_os Linux
503
+# Refcount structures are used much differently with external data
504
+# files
505
+_unsupported_imgopts data_file
506
507
echo
508
echo '=== New refcount structures may not conflict with existing structures ==='
509
diff --git a/tests/qemu-iotests/138 b/tests/qemu-iotests/138
510
index XXXXXXX..XXXXXXX 100755
511
--- a/tests/qemu-iotests/138
512
+++ b/tests/qemu-iotests/138
513
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
514
_supported_fmt qcow2
515
_supported_proto file
516
_supported_os Linux
517
+# With an external data file, data clusters are not refcounted
518
+# (and so qemu-img check does not check their refcount)
519
+_unsupported_imgopts data_file
520
521
echo
522
echo '=== Check on an image with a multiple of 2^32 clusters ==='
523
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
524
index XXXXXXX..XXXXXXX 100755
525
--- a/tests/qemu-iotests/156
526
+++ b/tests/qemu-iotests/156
527
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
528
_supported_fmt qcow2 qed
529
_supported_proto generic
530
_unsupported_proto vxhs
531
+# Copying files around with cp does not work with external data files
532
+_unsupported_imgopts data_file
533
534
# Create source disk
535
TEST_IMG="$TEST_IMG.backing" _make_test_img 1M
536
diff --git a/tests/qemu-iotests/176 b/tests/qemu-iotests/176
537
index XXXXXXX..XXXXXXX 100755
538
--- a/tests/qemu-iotests/176
539
+++ b/tests/qemu-iotests/176
540
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
541
_supported_fmt qcow2
542
_supported_proto file
543
_supported_os Linux
544
-# Persistent dirty bitmaps require compat=1.1
545
-_unsupported_imgopts 'compat=0.10'
546
+# Persistent dirty bitmaps require compat=1.1;
547
+# Internal snapshots forbid using an external data file
548
+# (they work with refcount_bits=1 here, though, because there actually
549
+# is no data when creating the snapshot)
550
+_unsupported_imgopts 'compat=0.10' data_file
551
552
run_qemu()
553
{
554
diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191
555
index XXXXXXX..XXXXXXX 100755
556
--- a/tests/qemu-iotests/191
557
+++ b/tests/qemu-iotests/191
558
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
559
560
_supported_fmt qcow2
561
_supported_proto file
562
+# An external data file would change the query-named-block-nodes output
563
+_unsupported_imgopts data_file
564
565
size=64M
566
567
diff --git a/tests/qemu-iotests/201 b/tests/qemu-iotests/201
568
index XXXXXXX..XXXXXXX 100755
569
--- a/tests/qemu-iotests/201
570
+++ b/tests/qemu-iotests/201
571
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow2
572
_supported_proto generic
573
_supported_os Linux
574
575
-# Internal snapshots are (currently) impossible with refcount_bits=1
576
-# This was taken from test 080
577
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
578
+# Internal snapshots are (currently) impossible with refcount_bits=1,
579
+# and generally impossible with external data files
580
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
581
582
size=64M
583
_make_test_img $size
584
diff --git a/tests/qemu-iotests/214 b/tests/qemu-iotests/214
585
index XXXXXXX..XXXXXXX 100755
586
--- a/tests/qemu-iotests/214
587
+++ b/tests/qemu-iotests/214
588
@@ -XXX,XX +XXX,XX @@ _supported_proto file
589
590
# Repairing the corrupted image requires qemu-img check to store a
591
# refcount up to 3, which requires at least two refcount bits.
592
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
593
+# External data files do not support compressed clusters.
594
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
595
596
597
echo
598
diff --git a/tests/qemu-iotests/217 b/tests/qemu-iotests/217
599
index XXXXXXX..XXXXXXX 100755
600
--- a/tests/qemu-iotests/217
601
+++ b/tests/qemu-iotests/217
602
@@ -XXX,XX +XXX,XX @@ _supported_proto file
603
604
# This test needs clusters with at least a refcount of 2 so that
605
# OFLAG_COPIED is not set. refcount_bits=1 is therefore unsupported.
606
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
607
+# (As are external data files.)
608
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
609
610
echo
611
echo '=== Simulating an I/O error during snapshot deletion ==='
612
diff --git a/tests/qemu-iotests/220 b/tests/qemu-iotests/220
613
index XXXXXXX..XXXXXXX 100755
614
--- a/tests/qemu-iotests/220
615
+++ b/tests/qemu-iotests/220
616
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
617
_supported_fmt qcow2
618
_supported_proto file
619
_supported_os Linux
620
-# To use a different refcount width but 16 bits we need compat=1.1
621
-_unsupported_imgopts 'compat=0.10'
622
+# To use a different refcount width but 16 bits we need compat=1.1,
623
+# and external data files do not support compressed clusters.
624
+_unsupported_imgopts 'compat=0.10' data_file
625
626
echo "== Creating huge file =="
627
628
diff --git a/tests/qemu-iotests/243 b/tests/qemu-iotests/243
629
index XXXXXXX..XXXXXXX 100755
630
--- a/tests/qemu-iotests/243
631
+++ b/tests/qemu-iotests/243
632
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
633
_supported_fmt qcow2
634
_supported_proto file
635
_supported_os Linux
636
-# External data files do not work with compat=0.10
637
-_unsupported_imgopts 'compat=0.10'
638
+# External data files do not work with compat=0.10, and because there
639
+# is an explicit case for external data files here, we cannot allow
640
+# the user to specify whether to use one
641
+_unsupported_imgopts 'compat=0.10' data_file
642
643
for mode in off metadata falloc full; do
644
645
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
646
index XXXXXXX..XXXXXXX 100755
647
--- a/tests/qemu-iotests/244
648
+++ b/tests/qemu-iotests/244
649
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
650
_supported_fmt qcow2
651
_supported_proto file
652
_supported_os Linux
653
-# External data files do not work with compat=0.10
654
-_unsupported_imgopts 'compat=0.10'
655
+# External data files do not work with compat=0.10, and because we use
656
+# our own external data file, we cannot let the user specify one
657
+_unsupported_imgopts 'compat=0.10' data_file
658
659
echo
660
echo "=== Create and open image with external data file ==="
661
diff --git a/tests/qemu-iotests/250 b/tests/qemu-iotests/250
662
index XXXXXXX..XXXXXXX 100755
663
--- a/tests/qemu-iotests/250
664
+++ b/tests/qemu-iotests/250
665
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
666
_supported_fmt qcow2
667
_supported_proto file
668
_supported_os Linux
669
+# This test does not make much sense with external data files
670
+_unsupported_imgopts data_file
671
672
# This test checks that qcow2_process_discards does not truncate a discard
673
# request > 2G.
674
diff --git a/tests/qemu-iotests/261 b/tests/qemu-iotests/261
675
index XXXXXXX..XXXXXXX 100755
676
--- a/tests/qemu-iotests/261
677
+++ b/tests/qemu-iotests/261
678
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
679
# (1) We create a v2 image that supports nothing but refcount_bits=16
680
# (2) We do some refcount management on our own which expects
681
# refcount_bits=16
682
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
683
+# As for data files, they do not support snapshots at all.
684
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
685
686
# Parameters:
687
# $1: image filename
688
diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267
689
index XXXXXXX..XXXXXXX 100755
690
--- a/tests/qemu-iotests/267
691
+++ b/tests/qemu-iotests/267
692
@@ -XXX,XX +XXX,XX @@ _supported_proto file
693
_supported_os Linux
694
_require_drivers copy-on-read
695
696
-# Internal snapshots are (currently) impossible with refcount_bits=1
697
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
698
+# Internal snapshots are (currently) impossible with refcount_bits=1,
699
+# and generally impossible with external data files
700
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
701
702
do_run_qemu()
703
{
704
diff --git a/tests/qemu-iotests/273 b/tests/qemu-iotests/273
705
index XXXXXXX..XXXXXXX 100755
706
--- a/tests/qemu-iotests/273
707
+++ b/tests/qemu-iotests/273
708
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
709
_supported_fmt qcow2
710
_supported_proto file
711
_supported_os Linux
712
+# External data files would add nodes to the block graph, so it would
713
+# not match the reference output
714
+_unsupported_imgopts data_file
715
716
do_run_qemu()
717
{
718
--
30
--
719
2.24.1
31
2.24.1
720
32
721
diff view generated by jsdifflib
1
We can save some LoC in xdbg_graph_add_edge() by using
1
QLIST_REMOVE() assumes the element is in a list. It also leaves the
2
bdrv_qapi_perm_to_blk_perm().
2
element's linked list pointers dangling.
3
3
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Introduce a safe version of QLIST_REMOVE() and convert open-coded
5
Message-id: 20191108123455.39445-3-mreitz@redhat.com
5
instances of this pattern.
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Sergio Lopez <slp@redhat.com>
9
Message-id: 20200214171712.541358-4-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
11
---
9
block.c | 29 ++++++++---------------------
12
block.c | 5 +----
10
1 file changed, 8 insertions(+), 21 deletions(-)
13
chardev/spice.c | 4 +---
14
include/qemu/queue.h | 14 ++++++++++++++
15
3 files changed, 16 insertions(+), 7 deletions(-)
11
16
12
diff --git a/block.c b/block.c
17
diff --git a/block.c b/block.c
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/block.c
19
--- a/block.c
15
+++ b/block.c
20
+++ b/block.c
16
@@ -XXX,XX +XXX,XX @@ static void xdbg_graph_add_node(XDbgBlockGraphConstructor *gr, void *node,
21
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
17
static void xdbg_graph_add_edge(XDbgBlockGraphConstructor *gr, void *parent,
22
18
const BdrvChild *child)
23
static void bdrv_detach_child(BdrvChild *child)
19
{
24
{
20
- typedef struct {
25
- if (child->next.le_prev) {
21
- unsigned int flag;
26
- QLIST_REMOVE(child, next);
22
- BlockPermission num;
27
- child->next.le_prev = NULL;
23
- } PermissionMap;
28
- }
24
-
29
+ QLIST_SAFE_REMOVE(child, next);
25
- static const PermissionMap permissions[] = {
30
26
- { BLK_PERM_CONSISTENT_READ, BLOCK_PERMISSION_CONSISTENT_READ },
31
bdrv_replace_child(child, NULL);
27
- { BLK_PERM_WRITE, BLOCK_PERMISSION_WRITE },
32
28
- { BLK_PERM_WRITE_UNCHANGED, BLOCK_PERMISSION_WRITE_UNCHANGED },
33
diff --git a/chardev/spice.c b/chardev/spice.c
29
- { BLK_PERM_RESIZE, BLOCK_PERMISSION_RESIZE },
34
index XXXXXXX..XXXXXXX 100644
30
- { BLK_PERM_GRAPH_MOD, BLOCK_PERMISSION_GRAPH_MOD },
35
--- a/chardev/spice.c
31
- { 0, 0 }
36
+++ b/chardev/spice.c
32
- };
37
@@ -XXX,XX +XXX,XX @@ static void char_spice_finalize(Object *obj)
33
- const PermissionMap *p;
38
34
+ BlockPermission qapi_perm;
39
vmc_unregister_interface(s);
35
XDbgBlockGraphEdge *edge;
40
36
41
- if (s->next.le_prev) {
37
- QEMU_BUILD_BUG_ON(1UL << (ARRAY_SIZE(permissions) - 1) != BLK_PERM_ALL + 1);
42
- QLIST_REMOVE(s, next);
38
-
43
- }
39
edge = g_new0(XDbgBlockGraphEdge, 1);
44
+ QLIST_SAFE_REMOVE(s, next);
40
45
41
edge->parent = xdbg_graph_node_num(gr, parent);
46
g_free((char *)s->sin.subtype);
42
edge->child = xdbg_graph_node_num(gr, child->bs);
47
g_free((char *)s->sin.portname);
43
edge->name = g_strdup(child->name);
48
diff --git a/include/qemu/queue.h b/include/qemu/queue.h
44
49
index XXXXXXX..XXXXXXX 100644
45
- for (p = permissions; p->flag; p++) {
50
--- a/include/qemu/queue.h
46
- if (p->flag & child->perm) {
51
+++ b/include/qemu/queue.h
47
- QAPI_LIST_ADD(edge->perm, p->num);
52
@@ -XXX,XX +XXX,XX @@ struct { \
48
+ for (qapi_perm = 0; qapi_perm < BLOCK_PERMISSION__MAX; qapi_perm++) {
53
*(elm)->field.le_prev = (elm)->field.le_next; \
49
+ uint64_t flag = bdrv_qapi_perm_to_blk_perm(qapi_perm);
54
} while (/*CONSTCOND*/0)
55
56
+/*
57
+ * Like QLIST_REMOVE() but safe to call when elm is not in a list
58
+ */
59
+#define QLIST_SAFE_REMOVE(elm, field) do { \
60
+ if ((elm)->field.le_prev != NULL) { \
61
+ if ((elm)->field.le_next != NULL) \
62
+ (elm)->field.le_next->field.le_prev = \
63
+ (elm)->field.le_prev; \
64
+ *(elm)->field.le_prev = (elm)->field.le_next; \
65
+ (elm)->field.le_next = NULL; \
66
+ (elm)->field.le_prev = NULL; \
67
+ } \
68
+} while (/*CONSTCOND*/0)
50
+
69
+
51
+ if (flag & child->perm) {
70
#define QLIST_FOREACH(var, head, field) \
52
+ QAPI_LIST_ADD(edge->perm, qapi_perm);
71
for ((var) = ((head)->lh_first); \
53
}
72
(var); \
54
- if (p->flag & child->shared_perm) {
55
- QAPI_LIST_ADD(edge->shared_perm, p->num);
56
+ if (flag & child->shared_perm) {
57
+ QAPI_LIST_ADD(edge->shared_perm, qapi_perm);
58
}
59
}
60
61
--
73
--
62
2.24.1
74
2.24.1
63
75
64
diff view generated by jsdifflib
1
Sometimes it is useful to be able to add a node to the block graph that
1
It is not necessary to scan all AioHandlers for deletion. Keep a list
2
takes or unshare a certain set of permissions for debugging purposes.
2
of deleted handlers instead of scanning the full list of all handlers.
3
This patch adds this capability to blkdebug.
3
4
4
The AioHandler->deleted field can be dropped. Let's check if the
5
(Note that you cannot make blkdebug release or share permissions that it
5
handler has been inserted into the deleted list instead. Add a new
6
needs to take or cannot share, because this might result in assertion
6
QLIST_IS_INSERTED() API for this check.
7
failures in the block layer. But if the blkdebug node has no parents,
7
8
it will not take any permissions and share everything by default, so you
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
can then freely choose what permissions to take and share.)
9
Reviewed-by: Sergio Lopez <slp@redhat.com>
10
10
Message-id: 20200214171712.541358-5-stefanha@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-id: 20191108123455.39445-4-mreitz@redhat.com
13
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
12
---
16
block/blkdebug.c | 93 +++++++++++++++++++++++++++++++++++++++++++-
13
include/block/aio.h | 6 ++++-
17
qapi/block-core.json | 14 ++++++-
14
include/qemu/queue.h | 3 +++
18
2 files changed, 105 insertions(+), 2 deletions(-)
15
util/aio-posix.c | 53 +++++++++++++++++++++++++++++---------------
19
16
3 files changed, 43 insertions(+), 19 deletions(-)
20
diff --git a/block/blkdebug.c b/block/blkdebug.c
17
18
diff --git a/include/block/aio.h b/include/block/aio.h
21
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
22
--- a/block/blkdebug.c
20
--- a/include/block/aio.h
23
+++ b/block/blkdebug.c
21
+++ b/include/block/aio.h
24
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ void qemu_aio_unref(void *p);
25
#include "qemu/cutils.h"
23
void qemu_aio_ref(void *p);
26
#include "qemu/config-file.h"
24
27
#include "block/block_int.h"
25
typedef struct AioHandler AioHandler;
28
+#include "block/qdict.h"
26
+typedef QLIST_HEAD(, AioHandler) AioHandlerList;
29
#include "qemu/module.h"
27
typedef void QEMUBHFunc(void *opaque);
30
#include "qemu/option.h"
28
typedef bool AioPollFn(void *opaque);
31
+#include "qapi/qapi-visit-block-core.h"
29
typedef void IOHandler(void *opaque);
32
#include "qapi/qmp/qdict.h"
30
@@ -XXX,XX +XXX,XX @@ struct AioContext {
33
+#include "qapi/qmp/qlist.h"
31
QemuRecMutex lock;
34
#include "qapi/qmp/qstring.h"
32
35
+#include "qapi/qobject-input-visitor.h"
33
/* The list of registered AIO handlers. Protected by ctx->list_lock. */
36
#include "sysemu/qtest.h"
34
- QLIST_HEAD(, AioHandler) aio_handlers;
37
35
+ AioHandlerList aio_handlers;
38
typedef struct BDRVBlkdebugState {
36
+
39
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVBlkdebugState {
37
+ /* The list of AIO handlers to be deleted. Protected by ctx->list_lock. */
40
uint64_t opt_discard;
38
+ AioHandlerList deleted_aio_handlers;
41
uint64_t max_discard;
39
42
40
/* Used to avoid unnecessary event_notifier_set calls in aio_notify;
43
+ uint64_t take_child_perms;
41
* accessed with atomic primitives. If this field is 0, everything
44
+ uint64_t unshare_child_perms;
42
diff --git a/include/qemu/queue.h b/include/qemu/queue.h
45
+
43
index XXXXXXX..XXXXXXX 100644
46
/* For blkdebug_refresh_filename() */
44
--- a/include/qemu/queue.h
47
char *config_file;
45
+++ b/include/qemu/queue.h
48
46
@@ -XXX,XX +XXX,XX @@ struct { \
49
@@ -XXX,XX +XXX,XX @@ static void blkdebug_parse_filename(const char *filename, QDict *options,
47
} \
50
qdict_put_str(options, "x-image", filename);
48
} while (/*CONSTCOND*/0)
49
50
+/* Is elm in a list? */
51
+#define QLIST_IS_INSERTED(elm, field) ((elm)->field.le_prev != NULL)
52
+
53
#define QLIST_FOREACH(var, head, field) \
54
for ((var) = ((head)->lh_first); \
55
(var); \
56
diff --git a/util/aio-posix.c b/util/aio-posix.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/util/aio-posix.c
59
+++ b/util/aio-posix.c
60
@@ -XXX,XX +XXX,XX @@ struct AioHandler
61
AioPollFn *io_poll;
62
IOHandler *io_poll_begin;
63
IOHandler *io_poll_end;
64
- int deleted;
65
void *opaque;
66
bool is_external;
67
QLIST_ENTRY(AioHandler) node;
68
+ QLIST_ENTRY(AioHandler) node_deleted;
69
};
70
71
#ifdef CONFIG_EPOLL_CREATE1
72
@@ -XXX,XX +XXX,XX @@ static bool aio_epoll_try_enable(AioContext *ctx)
73
74
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
75
int r;
76
- if (node->deleted || !node->pfd.events) {
77
+ if (QLIST_IS_INSERTED(node, node_deleted) || !node->pfd.events) {
78
continue;
79
}
80
event.events = epoll_events_from_pfd(node->pfd.events);
81
@@ -XXX,XX +XXX,XX @@ static AioHandler *find_aio_handler(AioContext *ctx, int fd)
82
AioHandler *node;
83
84
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
85
- if (node->pfd.fd == fd)
86
- if (!node->deleted)
87
+ if (node->pfd.fd == fd) {
88
+ if (!QLIST_IS_INSERTED(node, node_deleted)) {
89
return node;
90
+ }
91
+ }
92
}
93
94
return NULL;
95
@@ -XXX,XX +XXX,XX @@ static bool aio_remove_fd_handler(AioContext *ctx, AioHandler *node)
96
97
/* If a read is in progress, just mark the node as deleted */
98
if (qemu_lockcnt_count(&ctx->list_lock)) {
99
- node->deleted = 1;
100
+ QLIST_INSERT_HEAD_RCU(&ctx->deleted_aio_handlers, node, node_deleted);
101
node->pfd.revents = 0;
102
return false;
103
}
104
@@ -XXX,XX +XXX,XX @@ static void poll_set_started(AioContext *ctx, bool started)
105
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
106
IOHandler *fn;
107
108
- if (node->deleted) {
109
+ if (QLIST_IS_INSERTED(node, node_deleted)) {
110
continue;
111
}
112
113
@@ -XXX,XX +XXX,XX @@ bool aio_pending(AioContext *ctx)
114
return result;
51
}
115
}
52
116
53
+static int blkdebug_parse_perm_list(uint64_t *dest, QDict *options,
117
+static void aio_free_deleted_handlers(AioContext *ctx)
54
+ const char *prefix, Error **errp)
55
+{
118
+{
56
+ int ret = 0;
119
+ AioHandler *node;
57
+ QDict *subqdict = NULL;
120
+
58
+ QObject *crumpled_subqdict = NULL;
121
+ if (QLIST_EMPTY_RCU(&ctx->deleted_aio_handlers)) {
59
+ Visitor *v = NULL;
122
+ return;
60
+ BlockPermissionList *perm_list = NULL, *element;
61
+ Error *local_err = NULL;
62
+
63
+ *dest = 0;
64
+
65
+ qdict_extract_subqdict(options, &subqdict, prefix);
66
+ if (!qdict_size(subqdict)) {
67
+ goto out;
68
+ }
123
+ }
69
+
124
+ if (!qemu_lockcnt_dec_if_lock(&ctx->list_lock)) {
70
+ crumpled_subqdict = qdict_crumple(subqdict, errp);
125
+ return; /* we are nested, let the parent do the freeing */
71
+ if (!crumpled_subqdict) {
72
+ ret = -EINVAL;
73
+ goto out;
74
+ }
126
+ }
75
+
127
+
76
+ v = qobject_input_visitor_new(crumpled_subqdict);
128
+ while ((node = QLIST_FIRST_RCU(&ctx->deleted_aio_handlers))) {
77
+ visit_type_BlockPermissionList(v, NULL, &perm_list, &local_err);
129
+ QLIST_REMOVE(node, node);
78
+ if (local_err) {
130
+ QLIST_REMOVE(node, node_deleted);
79
+ error_propagate(errp, local_err);
131
+ g_free(node);
80
+ ret = -EINVAL;
81
+ goto out;
82
+ }
132
+ }
83
+
133
+
84
+ for (element = perm_list; element; element = element->next) {
134
+ qemu_lockcnt_inc_and_unlock(&ctx->list_lock);
85
+ *dest |= bdrv_qapi_perm_to_blk_perm(element->value);
86
+ }
87
+
88
+out:
89
+ qapi_free_BlockPermissionList(perm_list);
90
+ visit_free(v);
91
+ qobject_unref(subqdict);
92
+ qobject_unref(crumpled_subqdict);
93
+ return ret;
94
+}
135
+}
95
+
136
+
96
+static int blkdebug_parse_perms(BDRVBlkdebugState *s, QDict *options,
137
static bool aio_dispatch_handlers(AioContext *ctx)
97
+ Error **errp)
138
{
98
+{
139
AioHandler *node, *tmp;
99
+ int ret;
140
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx)
100
+
141
revents = node->pfd.revents & node->pfd.events;
101
+ ret = blkdebug_parse_perm_list(&s->take_child_perms, options,
142
node->pfd.revents = 0;
102
+ "take-child-perms.", errp);
143
103
+ if (ret < 0) {
144
- if (!node->deleted &&
104
+ return ret;
145
+ if (!QLIST_IS_INSERTED(node, node_deleted) &&
105
+ }
146
(revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
106
+
147
aio_node_check(ctx, node->is_external) &&
107
+ ret = blkdebug_parse_perm_list(&s->unshare_child_perms, options,
148
node->io_read) {
108
+ "unshare-child-perms.", errp);
149
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx)
109
+ if (ret < 0) {
150
progress = true;
110
+ return ret;
151
}
111
+ }
152
}
112
+
153
- if (!node->deleted &&
113
+ return 0;
154
+ if (!QLIST_IS_INSERTED(node, node_deleted) &&
114
+}
155
(revents & (G_IO_OUT | G_IO_ERR)) &&
115
+
156
aio_node_check(ctx, node->is_external) &&
116
static QemuOptsList runtime_opts = {
157
node->io_write) {
117
.name = "blkdebug",
158
node->io_write(node->opaque);
118
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
159
progress = true;
119
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
160
}
120
/* Set initial state */
161
-
121
s->state = 1;
162
- if (node->deleted) {
122
163
- if (qemu_lockcnt_dec_if_lock(&ctx->list_lock)) {
123
+ /* Parse permissions modifiers before opening the image file */
164
- QLIST_REMOVE(node, node);
124
+ ret = blkdebug_parse_perms(s, options, errp);
165
- g_free(node);
125
+ if (ret < 0) {
166
- qemu_lockcnt_inc_and_unlock(&ctx->list_lock);
126
+ goto out;
167
- }
127
+ }
168
- }
128
+
169
}
129
/* Open the image file */
170
130
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
171
return progress;
131
bs, &child_file, false, &local_err);
172
@@ -XXX,XX +XXX,XX @@ void aio_dispatch(AioContext *ctx)
132
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
173
qemu_lockcnt_inc(&ctx->list_lock);
133
return 0;
174
aio_bh_poll(ctx);
134
}
175
aio_dispatch_handlers(ctx);
135
176
+ aio_free_deleted_handlers(ctx);
136
+static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
177
qemu_lockcnt_dec(&ctx->list_lock);
137
+ const BdrvChildRole *role,
178
138
+ BlockReopenQueue *reopen_queue,
179
timerlistgroup_run_timers(&ctx->tlg);
139
+ uint64_t perm, uint64_t shared,
180
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers_once(AioContext *ctx, int64_t *timeout)
140
+ uint64_t *nperm, uint64_t *nshared)
181
RCU_READ_LOCK_GUARD();
141
+{
182
142
+ BDRVBlkdebugState *s = bs->opaque;
183
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
143
+
184
- if (!node->deleted && node->io_poll &&
144
+ bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
185
+ if (!QLIST_IS_INSERTED(node, node_deleted) && node->io_poll &&
145
+ nperm, nshared);
186
aio_node_check(ctx, node->is_external) &&
146
+
187
node->io_poll(node->opaque)) {
147
+ *nperm |= s->take_child_perms;
188
/*
148
+ *nshared &= ~s->unshare_child_perms;
189
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
149
+}
190
150
+
191
if (!aio_epoll_enabled(ctx)) {
151
static const char *const blkdebug_strong_runtime_opts[] = {
192
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
152
"config",
193
- if (!node->deleted && node->pfd.events
153
"inject-error.",
194
+ if (!QLIST_IS_INSERTED(node, node_deleted) && node->pfd.events
154
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
195
&& aio_node_check(ctx, node->is_external)) {
155
.bdrv_file_open = blkdebug_open,
196
add_pollfd(node);
156
.bdrv_close = blkdebug_close,
197
}
157
.bdrv_reopen_prepare = blkdebug_reopen_prepare,
198
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
158
- .bdrv_child_perm = bdrv_filter_default_perms,
199
progress |= aio_dispatch_handlers(ctx);
159
+ .bdrv_child_perm = blkdebug_child_perm,
200
}
160
201
161
.bdrv_getlength = blkdebug_getlength,
202
+ aio_free_deleted_handlers(ctx);
162
.bdrv_refresh_filename = blkdebug_refresh_filename,
203
+
163
diff --git a/qapi/block-core.json b/qapi/block-core.json
204
qemu_lockcnt_dec(&ctx->list_lock);
164
index XXXXXXX..XXXXXXX 100644
205
165
--- a/qapi/block-core.json
206
progress |= timerlistgroup_run_timers(&ctx->tlg);
166
+++ b/qapi/block-core.json
167
@@ -XXX,XX +XXX,XX @@
168
#
169
# @set-state: array of state-change descriptions
170
#
171
+# @take-child-perms: Permissions to take on @image in addition to what
172
+# is necessary anyway (which depends on how the
173
+# blkdebug node is used). Defaults to none.
174
+# (since 5.0)
175
+#
176
+# @unshare-child-perms: Permissions not to share on @image in addition
177
+# to what cannot be shared anyway (which depends
178
+# on how the blkdebug node is used). Defaults
179
+# to none. (since 5.0)
180
+#
181
# Since: 2.9
182
##
183
{ 'struct': 'BlockdevOptionsBlkdebug',
184
@@ -XXX,XX +XXX,XX @@
185
'*opt-write-zero': 'int32', '*max-write-zero': 'int32',
186
'*opt-discard': 'int32', '*max-discard': 'int32',
187
'*inject-error': ['BlkdebugInjectErrorOptions'],
188
- '*set-state': ['BlkdebugSetStateOptions'] } }
189
+ '*set-state': ['BlkdebugSetStateOptions'],
190
+ '*take-child-perms': ['BlockPermission'],
191
+ '*unshare-child-perms': ['BlockPermission'] } }
192
193
##
194
# @BlockdevOptionsBlklogwrites:
195
--
207
--
196
2.24.1
208
2.24.1
197
209
198
diff view generated by jsdifflib
1
We do not care about the json:{} filenames here, so we can just filter
1
File descriptor monitoring is O(1) with epoll(7), but
2
them out and thus make the test work both with and without external data
2
aio_dispatch_handlers() still scans all AioHandlers instead of
3
files.
3
dispatching just those that are ready. This makes aio_poll() O(n) with
4
4
respect to the total number of registered handlers.
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
6
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
6
Add a local ready_list to aio_poll() so that each nested aio_poll()
7
Message-id: 20191107163708.833192-21-mreitz@redhat.com
7
builds a list of handlers ready to be dispatched. Since file descriptor
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
polling is level-triggered, nested aio_poll() calls also see fds that
9
were ready in the parent but not yet dispatched. This guarantees that
10
nested aio_poll() invocations will dispatch all fds, even those that
11
became ready before the nested invocation.
12
13
Since only handlers ready to be dispatched are placed onto the
14
ready_list, the new aio_dispatch_ready_handlers() function provides O(1)
15
dispatch.
16
17
Note that AioContext polling is still O(n) and currently cannot be fully
18
disabled. This still needs to be fixed before aio_poll() is fully O(1).
19
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
21
Reviewed-by: Sergio Lopez <slp@redhat.com>
22
Message-id: 20200214171712.541358-6-stefanha@redhat.com
23
[Fix compilation error on macOS where there is no epoll(87). The
24
aio_epoll() prototype was out of date and aio_add_ready_list() needed to
25
be moved outside the ifdef.
26
--Stefan]
27
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
28
---
10
tests/qemu-iotests/198 | 6 ++++--
29
util/aio-posix.c | 110 +++++++++++++++++++++++++++++++++--------------
11
tests/qemu-iotests/198.out | 4 ++--
30
1 file changed, 78 insertions(+), 32 deletions(-)
12
2 files changed, 6 insertions(+), 4 deletions(-)
31
13
32
diff --git a/util/aio-posix.c b/util/aio-posix.c
14
diff --git a/tests/qemu-iotests/198 b/tests/qemu-iotests/198
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/198
17
+++ b/tests/qemu-iotests/198
18
@@ -XXX,XX +XXX,XX @@ echo
19
echo "== checking image base =="
20
$QEMU_IMG info --image-opts $IMGSPECBASE | _filter_img_info --format-specific \
21
| sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
22
- -e '/lazy refcounts:/ D' -e '/corrupt:/ D'
23
+ -e '/lazy refcounts:/ D' -e '/corrupt:/ D' -e '/^\s*data file/ D' \
24
+ | _filter_json_filename
25
26
echo
27
echo "== checking image layer =="
28
$QEMU_IMG info --image-opts $IMGSPECLAYER | _filter_img_info --format-specific \
29
| sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
30
- -e '/lazy refcounts:/ D' -e '/corrupt:/ D'
31
+ -e '/lazy refcounts:/ D' -e '/corrupt:/ D' -e '/^\s*data file/ D' \
32
+ | _filter_json_filename
33
34
35
# success, all done
36
diff --git a/tests/qemu-iotests/198.out b/tests/qemu-iotests/198.out
37
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qemu-iotests/198.out
34
--- a/util/aio-posix.c
39
+++ b/tests/qemu-iotests/198.out
35
+++ b/util/aio-posix.c
40
@@ -XXX,XX +XXX,XX @@ read 16777216/16777216 bytes at offset 0
36
@@ -XXX,XX +XXX,XX @@ struct AioHandler
41
16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
37
void *opaque;
42
38
bool is_external;
43
== checking image base ==
39
QLIST_ENTRY(AioHandler) node;
44
-image: json:{"encrypt.key-secret": "sec0", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.base"}}
40
+ QLIST_ENTRY(AioHandler) node_ready; /* only used during aio_poll() */
45
+image: json:{ /* filtered */ }
41
QLIST_ENTRY(AioHandler) node_deleted;
46
file format: IMGFMT
42
};
47
virtual size: 16 MiB (16777216 bytes)
43
48
Format specific information:
44
+/* Add a handler to a ready list */
49
@@ -XXX,XX +XXX,XX @@ Format specific information:
45
+static void add_ready_handler(AioHandlerList *ready_list,
50
master key iters: 1024
46
+ AioHandler *node,
51
47
+ int revents)
52
== checking image layer ==
48
+{
53
-image: json:{"encrypt.key-secret": "sec1", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}}
49
+ QLIST_SAFE_REMOVE(node, node_ready); /* remove from nested parent's list */
54
+image: json:{ /* filtered */ }
50
+ node->pfd.revents = revents;
55
file format: IMGFMT
51
+ QLIST_INSERT_HEAD(ready_list, node, node_ready);
56
virtual size: 16 MiB (16777216 bytes)
52
+}
57
backing file: TEST_DIR/t.IMGFMT.base
53
+
54
#ifdef CONFIG_EPOLL_CREATE1
55
56
/* The fd number threshold to switch to epoll */
57
@@ -XXX,XX +XXX,XX @@ static void aio_epoll_update(AioContext *ctx, AioHandler *node, bool is_new)
58
}
59
}
60
61
-static int aio_epoll(AioContext *ctx, int64_t timeout)
62
+static int aio_epoll(AioContext *ctx, AioHandlerList *ready_list,
63
+ int64_t timeout)
64
{
65
GPollFD pfd = {
66
.fd = ctx->epollfd,
67
@@ -XXX,XX +XXX,XX @@ static int aio_epoll(AioContext *ctx, int64_t timeout)
68
}
69
for (i = 0; i < ret; i++) {
70
int ev = events[i].events;
71
+ int revents = (ev & EPOLLIN ? G_IO_IN : 0) |
72
+ (ev & EPOLLOUT ? G_IO_OUT : 0) |
73
+ (ev & EPOLLHUP ? G_IO_HUP : 0) |
74
+ (ev & EPOLLERR ? G_IO_ERR : 0);
75
+
76
node = events[i].data.ptr;
77
- node->pfd.revents = (ev & EPOLLIN ? G_IO_IN : 0) |
78
- (ev & EPOLLOUT ? G_IO_OUT : 0) |
79
- (ev & EPOLLHUP ? G_IO_HUP : 0) |
80
- (ev & EPOLLERR ? G_IO_ERR : 0);
81
+ add_ready_handler(ready_list, node, revents);
82
}
83
}
84
out:
85
@@ -XXX,XX +XXX,XX @@ static void aio_epoll_update(AioContext *ctx, AioHandler *node, bool is_new)
86
{
87
}
88
89
-static int aio_epoll(AioContext *ctx, GPollFD *pfds,
90
- unsigned npfd, int64_t timeout)
91
+static int aio_epoll(AioContext *ctx, AioHandlerList *ready_list,
92
+ int64_t timeout)
93
{
94
assert(false);
95
}
96
@@ -XXX,XX +XXX,XX @@ static void aio_free_deleted_handlers(AioContext *ctx)
97
qemu_lockcnt_inc_and_unlock(&ctx->list_lock);
98
}
99
100
-static bool aio_dispatch_handlers(AioContext *ctx)
101
+static bool aio_dispatch_handler(AioContext *ctx, AioHandler *node)
102
{
103
- AioHandler *node, *tmp;
104
bool progress = false;
105
+ int revents;
106
107
- QLIST_FOREACH_SAFE_RCU(node, &ctx->aio_handlers, node, tmp) {
108
- int revents;
109
+ revents = node->pfd.revents & node->pfd.events;
110
+ node->pfd.revents = 0;
111
112
- revents = node->pfd.revents & node->pfd.events;
113
- node->pfd.revents = 0;
114
+ if (!QLIST_IS_INSERTED(node, node_deleted) &&
115
+ (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
116
+ aio_node_check(ctx, node->is_external) &&
117
+ node->io_read) {
118
+ node->io_read(node->opaque);
119
120
- if (!QLIST_IS_INSERTED(node, node_deleted) &&
121
- (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
122
- aio_node_check(ctx, node->is_external) &&
123
- node->io_read) {
124
- node->io_read(node->opaque);
125
-
126
- /* aio_notify() does not count as progress */
127
- if (node->opaque != &ctx->notifier) {
128
- progress = true;
129
- }
130
- }
131
- if (!QLIST_IS_INSERTED(node, node_deleted) &&
132
- (revents & (G_IO_OUT | G_IO_ERR)) &&
133
- aio_node_check(ctx, node->is_external) &&
134
- node->io_write) {
135
- node->io_write(node->opaque);
136
+ /* aio_notify() does not count as progress */
137
+ if (node->opaque != &ctx->notifier) {
138
progress = true;
139
}
140
}
141
+ if (!QLIST_IS_INSERTED(node, node_deleted) &&
142
+ (revents & (G_IO_OUT | G_IO_ERR)) &&
143
+ aio_node_check(ctx, node->is_external) &&
144
+ node->io_write) {
145
+ node->io_write(node->opaque);
146
+ progress = true;
147
+ }
148
+
149
+ return progress;
150
+}
151
+
152
+/*
153
+ * If we have a list of ready handlers then this is more efficient than
154
+ * scanning all handlers with aio_dispatch_handlers().
155
+ */
156
+static bool aio_dispatch_ready_handlers(AioContext *ctx,
157
+ AioHandlerList *ready_list)
158
+{
159
+ bool progress = false;
160
+ AioHandler *node;
161
+
162
+ while ((node = QLIST_FIRST(ready_list))) {
163
+ QLIST_SAFE_REMOVE(node, node_ready);
164
+ progress = aio_dispatch_handler(ctx, node) || progress;
165
+ }
166
+
167
+ return progress;
168
+}
169
+
170
+/* Slower than aio_dispatch_ready_handlers() but only used via glib */
171
+static bool aio_dispatch_handlers(AioContext *ctx)
172
+{
173
+ AioHandler *node, *tmp;
174
+ bool progress = false;
175
+
176
+ QLIST_FOREACH_SAFE_RCU(node, &ctx->aio_handlers, node, tmp) {
177
+ progress = aio_dispatch_handler(ctx, node) || progress;
178
+ }
179
180
return progress;
181
}
182
@@ -XXX,XX +XXX,XX @@ static bool try_poll_mode(AioContext *ctx, int64_t *timeout)
183
184
bool aio_poll(AioContext *ctx, bool blocking)
185
{
186
+ AioHandlerList ready_list = QLIST_HEAD_INITIALIZER(ready_list);
187
AioHandler *node;
188
int i;
189
int ret = 0;
190
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
191
/* wait until next event */
192
if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
193
npfd = 0; /* pollfds[] is not being used */
194
- ret = aio_epoll(ctx, timeout);
195
+ ret = aio_epoll(ctx, &ready_list, timeout);
196
} else {
197
ret = qemu_poll_ns(pollfds, npfd, timeout);
198
}
199
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
200
/* if we have any readable fds, dispatch event */
201
if (ret > 0) {
202
for (i = 0; i < npfd; i++) {
203
- nodes[i]->pfd.revents = pollfds[i].revents;
204
+ int revents = pollfds[i].revents;
205
+
206
+ if (revents) {
207
+ add_ready_handler(&ready_list, nodes[i], revents);
208
+ }
209
}
210
}
211
212
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
213
progress |= aio_bh_poll(ctx);
214
215
if (ret > 0) {
216
- progress |= aio_dispatch_handlers(ctx);
217
+ progress |= aio_dispatch_ready_handlers(ctx, &ready_list);
218
}
219
220
aio_free_deleted_handlers(ctx);
58
--
221
--
59
2.24.1
222
2.24.1
60
223
61
diff view generated by jsdifflib
1
When using an external data file, there are no refcounts for data
1
From: Alexander Bulekov <alxndr@bu.edu>
2
clusters. We thus have to adjust the corruption test in this patch to
3
not be based around a data cluster allocation, but the L2 table
4
allocation (L2 tables are still refcounted with external data files).
5
2
6
Furthermore, we should not print qcow2.py's list of incompatible
3
Move vl.c to a separate directory, similar to linux-user/
7
features because it differs depending on whether there is an external
4
Update the chechpatch and get_maintainer scripts, since they relied on
8
data file or not.
5
/vl.c for top_of_tree checks.
9
6
10
With those two changes, the test will work both with and without
7
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
11
external data files (once that options works with the iotests at all).
8
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
9
Message-id: 20200220041118.23264-2-alxndr@bu.edu
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
MAINTAINERS | 2 +-
13
Makefile.objs | 2 --
14
Makefile.target | 1 +
15
scripts/checkpatch.pl | 2 +-
16
scripts/get_maintainer.pl | 3 ++-
17
softmmu/Makefile.objs | 2 ++
18
vl.c => softmmu/vl.c | 0
19
7 files changed, 7 insertions(+), 5 deletions(-)
20
create mode 100644 softmmu/Makefile.objs
21
rename vl.c => softmmu/vl.c (100%)
12
22
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
diff --git a/MAINTAINERS b/MAINTAINERS
14
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
24
index XXXXXXX..XXXXXXX 100644
15
Message-id: 20191107163708.833192-20-mreitz@redhat.com
25
--- a/MAINTAINERS
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
+++ b/MAINTAINERS
17
---
27
@@ -XXX,XX +XXX,XX @@ F: include/qemu/main-loop.h
18
tests/qemu-iotests/137 | 15 +++++++++++----
28
F: include/sysemu/runstate.h
19
tests/qemu-iotests/137.out | 6 ++----
29
F: util/main-loop.c
20
2 files changed, 13 insertions(+), 8 deletions(-)
30
F: util/qemu-timer.c
21
31
-F: vl.c
22
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
32
+F: softmmu/vl.c
33
F: qapi/run-state.json
34
35
Human Monitor (HMP)
36
diff --git a/Makefile.objs b/Makefile.objs
37
index XXXXXXX..XXXXXXX 100644
38
--- a/Makefile.objs
39
+++ b/Makefile.objs
40
@@ -XXX,XX +XXX,XX @@ common-obj-y += ui/
41
common-obj-m += ui/
42
43
common-obj-y += dma-helpers.o
44
-common-obj-y += vl.o
45
-vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
46
common-obj-$(CONFIG_TPM) += tpm.o
47
48
common-obj-y += backends/
49
diff --git a/Makefile.target b/Makefile.target
50
index XXXXXXX..XXXXXXX 100644
51
--- a/Makefile.target
52
+++ b/Makefile.target
53
@@ -XXX,XX +XXX,XX @@ obj-y += qapi/
54
obj-y += memory.o
55
obj-y += memory_mapping.o
56
obj-y += migration/ram.o
57
+obj-y += softmmu/
58
LIBS := $(libs_softmmu) $(LIBS)
59
60
# Hardware support
61
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
23
index XXXXXXX..XXXXXXX 100755
62
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/137
63
--- a/scripts/checkpatch.pl
25
+++ b/tests/qemu-iotests/137
64
+++ b/scripts/checkpatch.pl
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO \
65
@@ -XXX,XX +XXX,XX @@ sub top_of_kernel_tree {
27
"$TEST_IMG" 2>&1 | _filter_qemu_io
66
    my @tree_check = (
28
67
        "COPYING", "MAINTAINERS", "Makefile",
29
# The dirty bit must not be set
68
        "README.rst", "docs", "VERSION",
30
-$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
69
-        "vl.c"
31
+# (Filter the external data file bit)
70
+        "linux-user", "softmmu"
32
+if $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features \
71
    );
33
+ | grep -q '\<0\>'
72
34
+then
73
    foreach my $check (@tree_check) {
35
+ echo 'ERROR: Dirty bit set'
74
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
36
+else
75
index XXXXXXX..XXXXXXX 100755
37
+ echo 'OK: Dirty bit not set'
76
--- a/scripts/get_maintainer.pl
38
+fi
77
+++ b/scripts/get_maintainer.pl
39
78
@@ -XXX,XX +XXX,XX @@ sub top_of_tree {
40
# Similarly we can test whether corruption detection has been enabled:
79
&& (-f "${lk_path}Makefile")
41
-# Create L1/L2, overwrite first entry in refcount block, allocate something.
80
&& (-d "${lk_path}docs")
42
+# Create L1, overwrite refcounts, force allocation of L2 by writing
81
&& (-f "${lk_path}VERSION")
43
+# data.
82
- && (-f "${lk_path}vl.c")) {
44
# Disabling the checks should fail, so the corruption must be detected.
83
+ && (-d "${lk_path}linux-user/")
45
_make_test_img 64M
84
+ && (-d "${lk_path}softmmu/")) {
46
-$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
85
    return 1;
47
-poke_file "$TEST_IMG" "$((0x20000))" "\x00\x00"
86
}
48
+poke_file "$TEST_IMG" "$((0x20000))" "\x00\x00\x00\x00\x00\x00\x00\x00"
87
return 0;
49
$QEMU_IO \
88
diff --git a/softmmu/Makefile.objs b/softmmu/Makefile.objs
50
-c "reopen -o overlap-check=none,lazy-refcounts=42" \
89
new file mode 100644
51
-c "write 64k 64k" \
90
index XXXXXXX..XXXXXXX
52
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
91
--- /dev/null
53
index XXXXXXX..XXXXXXX 100644
92
+++ b/softmmu/Makefile.objs
54
--- a/tests/qemu-iotests/137.out
93
@@ -XXX,XX +XXX,XX @@
55
+++ b/tests/qemu-iotests/137.out
94
+obj-y += vl.o
56
@@ -XXX,XX +XXX,XX @@ qemu-io: Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are
95
+vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
57
wrote 512/512 bytes at offset 0
96
diff --git a/vl.c b/softmmu/vl.c
58
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
97
similarity index 100%
59
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
98
rename from vl.c
60
-incompatible_features []
99
rename to softmmu/vl.c
61
+OK: Dirty bit not set
62
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
63
-wrote 65536/65536 bytes at offset 0
64
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
65
qemu-io: Parameter 'lazy-refcounts' expects 'on' or 'off'
66
-qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with qcow2_header); further corruption events will be suppressed
67
+qcow2: Marking image as corrupt: Preventing invalid allocation of L2 table at offset 0; further corruption events will be suppressed
68
write failed: Input/output error
69
*** done
70
--
100
--
71
2.24.1
101
2.24.1
72
102
73
diff view generated by jsdifflib
1
This will not work with external data files, so try to get tests working
1
From: Alexander Bulekov <alxndr@bu.edu>
2
without it as far as possible.
2
3
3
A program might rely on functions implemented in vl.c, but implement its
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
own main(). By placing main into a separate source file, there are no
5
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
5
complaints about duplicate main()s when linking against vl.o. For
6
Message-id: 20191107163708.833192-17-mreitz@redhat.com
6
example, the virtual-device fuzzer uses a main() provided by libfuzzer,
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
and needs to perform some initialization before running the softmmu
8
initialization. Now, main simply calls three vl.c functions which
9
handle the guest initialization, main loop and cleanup.
10
11
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
14
Message-id: 20200220041118.23264-3-alxndr@bu.edu
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
16
---
9
tests/qemu-iotests/063 | 12 ++++--------
17
MAINTAINERS | 1 +
10
tests/qemu-iotests/063.out | 3 ++-
18
Makefile.target | 2 +-
11
tests/qemu-iotests/085 | 9 +++------
19
include/sysemu/sysemu.h | 4 ++++
12
tests/qemu-iotests/085.out | 8 ++++----
20
softmmu/Makefile.objs | 1 +
13
4 files changed, 13 insertions(+), 19 deletions(-)
21
softmmu/main.c | 53 +++++++++++++++++++++++++++++++++++++++++
14
22
softmmu/vl.c | 36 +++++++---------------------
15
diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063
23
6 files changed, 69 insertions(+), 28 deletions(-)
16
index XXXXXXX..XXXXXXX 100755
24
create mode 100644 softmmu/main.c
17
--- a/tests/qemu-iotests/063
25
18
+++ b/tests/qemu-iotests/063
26
diff --git a/MAINTAINERS b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ _unsupported_imgopts "subformat=monolithicFlat" \
27
index XXXXXXX..XXXXXXX 100644
20
_make_test_img 4M
28
--- a/MAINTAINERS
21
29
+++ b/MAINTAINERS
22
echo "== Testing conversion with -n fails with no target file =="
30
@@ -XXX,XX +XXX,XX @@ F: include/sysemu/runstate.h
23
-# check .orig file does not exist
31
F: util/main-loop.c
24
-rm -f "$TEST_IMG.orig"
32
F: util/qemu-timer.c
25
if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.orig" >/dev/null 2>&1; then
33
F: softmmu/vl.c
26
exit 1
34
+F: softmmu/main.c
27
fi
35
F: qapi/run-state.json
28
36
29
echo "== Testing conversion with -n succeeds with a target file =="
37
Human Monitor (HMP)
30
-rm -f "$TEST_IMG.orig"
38
diff --git a/Makefile.target b/Makefile.target
31
-cp "$TEST_IMG" "$TEST_IMG.orig"
39
index XXXXXXX..XXXXXXX 100644
32
+_rm_test_img "$TEST_IMG.orig"
40
--- a/Makefile.target
33
+TEST_IMG="$TEST_IMG.orig" _make_test_img 4M
41
+++ b/Makefile.target
34
if ! $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.orig" ; then
42
@@ -XXX,XX +XXX,XX @@ endif
35
exit 1
43
COMMON_LDADDS = ../libqemuutil.a
36
fi
44
37
@@ -XXX,XX +XXX,XX @@ fi
45
# build either PROG or PROGW
38
_check_test_img
46
-$(QEMU_PROG_BUILD): $(all-obj-y) $(COMMON_LDADDS)
39
47
+$(QEMU_PROG_BUILD): $(all-obj-y) $(COMMON_LDADDS) $(softmmu-main-y)
40
echo "== Testing conversion to a smaller file fails =="
48
    $(call LINK, $(filter-out %.mak, $^))
41
-rm -f "$TEST_IMG.orig"
49
ifdef CONFIG_DARWIN
42
-mv "$TEST_IMG" "$TEST_IMG.orig"
50
    $(call quiet-command,Rez -append $(SRC_PATH)/pc-bios/qemu.rsrc -o $@,"REZ","$(TARGET_DIR)$@")
43
-_make_test_img 2M
51
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
44
-if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG.orig" "$TEST_IMG" >/dev/null 2>&1; then
52
index XXXXXXX..XXXXXXX 100644
45
+TEST_IMG="$TEST_IMG.target" _make_test_img 2M
53
--- a/include/sysemu/sysemu.h
46
+if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.target" >/dev/null 2>&1; then
54
+++ b/include/sysemu/sysemu.h
47
exit 1
55
@@ -XXX,XX +XXX,XX @@ QemuOpts *qemu_get_machine_opts(void);
48
fi
56
49
57
bool defaults_enabled(void);
50
diff --git a/tests/qemu-iotests/063.out b/tests/qemu-iotests/063.out
58
51
index XXXXXXX..XXXXXXX 100644
59
+void qemu_init(int argc, char **argv, char **envp);
52
--- a/tests/qemu-iotests/063.out
60
+void qemu_main_loop(void);
53
+++ b/tests/qemu-iotests/063.out
61
+void qemu_cleanup(void);
54
@@ -XXX,XX +XXX,XX @@ QA output created by 063
62
+
55
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
63
extern QemuOptsList qemu_legacy_drive_opts;
56
== Testing conversion with -n fails with no target file ==
64
extern QemuOptsList qemu_common_drive_opts;
57
== Testing conversion with -n succeeds with a target file ==
65
extern QemuOptsList qemu_drive_opts;
58
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=4194304
66
diff --git a/softmmu/Makefile.objs b/softmmu/Makefile.objs
59
== Testing conversion to raw is the same after conversion with -n ==
67
index XXXXXXX..XXXXXXX 100644
60
== Testing conversion back to original format ==
68
--- a/softmmu/Makefile.objs
61
No errors were found on the image.
69
+++ b/softmmu/Makefile.objs
62
== Testing conversion to a smaller file fails ==
70
@@ -XXX,XX +XXX,XX @@
63
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
71
+softmmu-main-y = softmmu/main.o
64
+Formatting 'TEST_DIR/t.IMGFMT.target', fmt=IMGFMT size=2097152
72
obj-y += vl.o
65
== Regression testing for copy offloading bug ==
73
vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
66
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
74
diff --git a/softmmu/main.c b/softmmu/main.c
67
Formatting 'TEST_DIR/t.IMGFMT.target', fmt=IMGFMT size=1048576
75
new file mode 100644
68
diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085
76
index XXXXXXX..XXXXXXX
69
index XXXXXXX..XXXXXXX 100755
77
--- /dev/null
70
--- a/tests/qemu-iotests/085
78
+++ b/softmmu/main.c
71
+++ b/tests/qemu-iotests/085
79
@@ -XXX,XX +XXX,XX @@
72
@@ -XXX,XX +XXX,XX @@ add_snapshot_image()
80
+/*
81
+ * QEMU System Emulator
82
+ *
83
+ * Copyright (c) 2003-2020 Fabrice Bellard
84
+ *
85
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
86
+ * of this software and associated documentation files (the "Software"), to deal
87
+ * in the Software without restriction, including without limitation the rights
88
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
89
+ * copies of the Software, and to permit persons to whom the Software is
90
+ * furnished to do so, subject to the following conditions:
91
+ *
92
+ * The above copyright notice and this permission notice shall be included in
93
+ * all copies or substantial portions of the Software.
94
+ *
95
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
96
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
97
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
98
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
99
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
100
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
101
+ * THE SOFTWARE.
102
+ */
103
+
104
+#include "qemu/osdep.h"
105
+#include "qemu-common.h"
106
+#include "sysemu/sysemu.h"
107
+
108
+#ifdef CONFIG_SDL
109
+#if defined(__APPLE__) || defined(main)
110
+#include <SDL.h>
111
+int main(int argc, char **argv)
112
+{
113
+ return qemu_main(argc, argv, NULL);
114
+}
115
+#undef main
116
+#define main qemu_main
117
+#endif
118
+#endif /* CONFIG_SDL */
119
+
120
+#ifdef CONFIG_COCOA
121
+#undef main
122
+#define main qemu_main
123
+#endif /* CONFIG_COCOA */
124
+
125
+int main(int argc, char **argv, char **envp)
126
+{
127
+ qemu_init(argc, argv, envp);
128
+ qemu_main_loop();
129
+ qemu_cleanup();
130
+
131
+ return 0;
132
+}
133
diff --git a/softmmu/vl.c b/softmmu/vl.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/softmmu/vl.c
136
+++ b/softmmu/vl.c
137
@@ -XXX,XX +XXX,XX @@
138
#include "sysemu/seccomp.h"
139
#include "sysemu/tcg.h"
140
141
-#ifdef CONFIG_SDL
142
-#if defined(__APPLE__) || defined(main)
143
-#include <SDL.h>
144
-int qemu_main(int argc, char **argv, char **envp);
145
-int main(int argc, char **argv)
146
-{
147
- return qemu_main(argc, argv, NULL);
148
-}
149
-#undef main
150
-#define main qemu_main
151
-#endif
152
-#endif /* CONFIG_SDL */
153
-
154
-#ifdef CONFIG_COCOA
155
-#undef main
156
-#define main qemu_main
157
-#endif /* CONFIG_COCOA */
158
-
159
-
160
#include "qemu/error-report.h"
161
#include "qemu/sockets.h"
162
#include "sysemu/accel.h"
163
@@ -XXX,XX +XXX,XX @@ static bool main_loop_should_exit(void)
164
return false;
165
}
166
167
-static void main_loop(void)
168
+void qemu_main_loop(void)
73
{
169
{
74
base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}"
170
#ifdef CONFIG_PROFILER
75
snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}"
171
int64_t ti;
76
- _make_test_img -u -b "${base_image}" "$size"
172
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
77
- mv "${TEST_IMG}" "${snapshot_file}"
173
}
78
+ TEST_IMG=$snapshot_file _make_test_img -u -b "${base_image}" "$size"
79
do_blockdev_add "$1" "'backing': null, " "${snapshot_file}"
80
}
174
}
81
175
82
@@ -XXX,XX +XXX,XX @@ blockdev_snapshot()
176
-int main(int argc, char **argv, char **envp)
83
177
+void qemu_init(int argc, char **argv, char **envp)
84
size=128M
178
{
85
179
int i;
86
-_make_test_img $size
180
int snapshot, linux_boot;
87
-mv "${TEST_IMG}" "${TEST_IMG}.1"
181
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
88
-_make_test_img $size
182
case QEMU_OPTION_watchdog:
89
-mv "${TEST_IMG}" "${TEST_IMG}.2"
183
if (watchdog) {
90
+TEST_IMG="$TEST_IMG.1" _make_test_img $size
184
error_report("only one watchdog option may be given");
91
+TEST_IMG="$TEST_IMG.2" _make_test_img $size
185
- return 1;
92
186
+ exit(1);
93
echo
187
}
94
echo === Running QEMU ===
188
watchdog = optarg;
95
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
189
break;
96
index XXXXXXX..XXXXXXX 100644
190
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
97
--- a/tests/qemu-iotests/085.out
191
parse_numa_opts(current_machine);
98
+++ b/tests/qemu-iotests/085.out
192
99
@@ -XXX,XX +XXX,XX @@
193
/* do monitor/qmp handling at preconfig state if requested */
100
QA output created by 085
194
- main_loop();
101
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
195
+ qemu_main_loop();
102
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
196
103
+Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=134217728
197
audio_init_audiodevs();
104
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
198
105
199
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
106
=== Running QEMU ===
200
if (vmstate_dump_file) {
107
201
/* dump and exit */
108
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_fil
202
dump_vmstate_json_to_file(vmstate_dump_file);
109
203
- return 0;
110
=== Create a couple of snapshots using blockdev-snapshot ===
204
+ exit(0);
111
205
}
112
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT
206
113
+Formatting 'TEST_DIR/11-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT
207
if (incoming) {
114
{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_11', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/11-snapshot-v0.IMGFMT', 'node-name': 'file_11' } } }
208
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
115
{"return": {}}
209
accel_setup_post(current_machine);
116
{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } }
210
os_setup_post();
117
{"return": {}}
211
118
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT
212
- main_loop();
119
+Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT
213
+ return;
120
{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_12', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/12-snapshot-v0.IMGFMT', 'node-name': 'file_12' } } }
214
+}
121
{"return": {}}
215
122
{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_12' } }
216
+void qemu_cleanup(void)
217
+{
218
gdbserver_cleanup();
219
220
/*
221
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
222
qemu_chr_cleanup();
223
user_creatable_cleanup();
224
/* TODO: unref root container, check all devices are ok */
225
-
226
- return 0;
227
}
123
--
228
--
124
2.24.1
229
2.24.1
125
230
126
diff view generated by jsdifflib
1
Overwriting IMGOPTS means ignoring all user-supplied options, which is
1
From: Alexander Bulekov <alxndr@bu.edu>
2
not what we want. Replace the current IMGOPTS use by a new BACKING_FILE
3
variable.
4
2
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
The virtual-device fuzzer must initialize QOM, prior to running
6
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
vl:qemu_init, so that it can use the qos_graph to identify the arguments
7
Message-id: 20191107163708.833192-14-mreitz@redhat.com
5
required to initialize a guest for libqos-assisted fuzzing. This change
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
prevents errors when vl:qemu_init tries to (re)initialize the previously
7
initialized QOM module.
8
9
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Message-id: 20200220041118.23264-4-alxndr@bu.edu
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
15
---
10
tests/qemu-iotests/267 | 12 ++++++++----
16
util/module.c | 7 +++++++
11
1 file changed, 8 insertions(+), 4 deletions(-)
17
1 file changed, 7 insertions(+)
12
18
13
diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267
19
diff --git a/util/module.c b/util/module.c
14
index XXXXXXX..XXXXXXX 100755
20
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/267
21
--- a/util/module.c
16
+++ b/tests/qemu-iotests/267
22
+++ b/util/module.c
17
@@ -XXX,XX +XXX,XX @@ size=128M
23
@@ -XXX,XX +XXX,XX @@ typedef struct ModuleEntry
18
24
typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
19
run_test()
25
20
{
26
static ModuleTypeList init_type_list[MODULE_INIT_MAX];
21
- _make_test_img $size
27
+static bool modules_init_done[MODULE_INIT_MAX];
22
+ if [ -n "$BACKING_FILE" ]; then
28
23
+ _make_test_img -b "$BACKING_FILE" $size
29
static ModuleTypeList dso_init_list;
24
+ else
30
25
+ _make_test_img $size
31
@@ -XXX,XX +XXX,XX @@ void module_call_init(module_init_type type)
26
+ fi
32
ModuleTypeList *l;
27
printf "savevm snap0\ninfo snapshots\nloadvm snap0\n" | run_qemu "$@" | _filter_date
33
ModuleEntry *e;
34
35
+ if (modules_init_done[type]) {
36
+ return;
37
+ }
38
+
39
l = find_type(type);
40
41
QTAILQ_FOREACH(e, l, node) {
42
e->init();
43
}
44
+
45
+ modules_init_done[type] = true;
28
}
46
}
29
47
30
@@ -XXX,XX +XXX,XX @@ echo
48
#ifdef CONFIG_MODULES
31
32
TEST_IMG="$TEST_IMG.base" _make_test_img $size
33
34
-IMGOPTS="backing_file=$TEST_IMG.base" \
35
+BACKING_FILE="$TEST_IMG.base" \
36
run_test -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \
37
-blockdev driver=file,filename="$TEST_IMG",node-name=file \
38
-blockdev driver=$IMGFMT,file=file,backing=backing-file,node-name=fmt
39
40
-IMGOPTS="backing_file=$TEST_IMG.base" \
41
+BACKING_FILE="$TEST_IMG.base" \
42
run_test -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \
43
-blockdev driver=$IMGFMT,file=backing-file,node-name=backing-fmt \
44
-blockdev driver=file,filename="$TEST_IMG",node-name=file \
45
@@ -XXX,XX +XXX,XX @@ echo
46
echo "=== -blockdev with NBD server on the backing file ==="
47
echo
48
49
-IMGOPTS="backing_file=$TEST_IMG.base" _make_test_img $size
50
+_make_test_img -b "$TEST_IMG.base" $size
51
cat <<EOF |
52
nbd_server_start unix:$SOCK_DIR/nbd
53
nbd_server_add -w backing-fmt
54
--
49
--
55
2.24.1
50
2.24.1
56
51
57
diff view generated by jsdifflib
1
The only difference is that the json:{} filename of the image looks
1
From: Alexander Bulekov <alxndr@bu.edu>
2
different. We actually do not care about that filename in this test, we
3
are only interested in (1) that there is a json:{} filename, and (2)
4
whether the backing filename can be constructed.
5
2
6
So just filter out the json:{} data, thus making this test pass both
3
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
7
with and without data_file.
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
6
Message-id: 20200220041118.23264-5-alxndr@bu.edu
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
include/qemu/module.h | 4 +++-
10
1 file changed, 3 insertions(+), 1 deletion(-)
8
11
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
diff --git a/include/qemu/module.h b/include/qemu/module.h
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
11
Message-id: 20191107163708.833192-19-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
tests/qemu-iotests/110 | 7 +++++--
15
tests/qemu-iotests/110.out | 4 ++--
16
2 files changed, 7 insertions(+), 4 deletions(-)
17
18
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/110
21
+++ b/tests/qemu-iotests/110
22
@@ -XXX,XX +XXX,XX @@ echo
23
# Across blkdebug without a config file, you cannot reconstruct filenames, so
24
# qemu is incapable of knowing the directory of the top image from the filename
25
# alone. However, using bdrv_dirname(), it should still work.
26
+# (Filter out the json:{} filename so this test works with external data files)
27
TEST_IMG="json:{
28
'driver': '$IMGFMT',
29
'file': {
30
@@ -XXX,XX +XXX,XX @@ TEST_IMG="json:{
31
}
32
]
33
}
34
-}" _img_info | _filter_img_info | grep -v 'backing file format'
35
+}" _img_info | _filter_img_info | grep -v 'backing file format' \
36
+ | _filter_json_filename
37
38
echo
39
echo '=== Backing name is always relative to the backed image ==='
40
@@ -XXX,XX +XXX,XX @@ TEST_IMG="json:{
41
}
42
]
43
}
44
-}" _img_info | _filter_img_info | grep -v 'backing file format'
45
+}" _img_info | _filter_img_info | grep -v 'backing file format' \
46
+ | _filter_json_filename
47
48
49
# success, all done
50
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
51
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
52
--- a/tests/qemu-iotests/110.out
14
--- a/include/qemu/module.h
53
+++ b/tests/qemu-iotests/110.out
15
+++ b/include/qemu/module.h
54
@@ -XXX,XX +XXX,XX @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
16
@@ -XXX,XX +XXX,XX @@ typedef enum {
55
17
MODULE_INIT_TRACE,
56
=== Non-reconstructable filename ===
18
MODULE_INIT_XEN_BACKEND,
57
19
MODULE_INIT_LIBQOS,
58
-image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}
20
+ MODULE_INIT_FUZZ_TARGET,
59
+image: json:{ /* filtered */ }
21
MODULE_INIT_MAX
60
file format: IMGFMT
22
} module_init_type;
61
virtual size: 64 MiB (67108864 bytes)
23
62
backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
24
@@ -XXX,XX +XXX,XX @@ typedef enum {
63
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.b
25
#define xen_backend_init(function) module_init(function, \
64
26
MODULE_INIT_XEN_BACKEND)
65
=== Nodes without a common directory ===
27
#define libqos_init(function) module_init(function, MODULE_INIT_LIBQOS)
66
28
-
67
-image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "vote-threshold": 1}}
29
+#define fuzz_target_init(function) module_init(function, \
68
+image: json:{ /* filtered */ }
30
+ MODULE_INIT_FUZZ_TARGET)
69
file format: IMGFMT
31
#define block_module_load_one(lib) module_load_one("block-", lib)
70
virtual size: 64 MiB (67108864 bytes)
32
#define ui_module_load_one(lib) module_load_one("ui-", lib)
71
backing file: t.IMGFMT.base (cannot determine actual path)
33
#define audio_module_load_one(lib) module_load_one("audio-", lib)
72
--
34
--
73
2.24.1
35
2.24.1
74
36
75
diff view generated by jsdifflib
1
Tests should not overwrite all user-supplied image options, but only add
1
From: Alexander Bulekov <alxndr@bu.edu>
2
to it (which will effectively overwrite conflicting values). Accomplish
3
this by passing options to _make_test_img via -o instead of $IMGOPTS.
4
2
5
For some tests, there is no functional change because they already only
3
qtest_server_send is a function pointer specifying the handler used to
6
appended options to IMGOPTS. For these, this patch is just a
4
transmit data to the qtest client. In the standard configuration, this
7
simplification.
5
calls the CharBackend handler, but now it is possible for other types of
6
handlers, e.g direct-function calls if the qtest client and server
7
exist within the same process (inproc)
8
8
9
For others, this is a change, so they now heed user-specified $IMGOPTS.
9
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
10
Some of those tests do not work with all image options, though, so we
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
need to disable them accordingly.
11
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
12
Acked-by: Thomas Huth <thuth@redhat.com>
13
Message-id: 20200220041118.23264-6-alxndr@bu.edu
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
---
16
include/sysemu/qtest.h | 3 +++
17
qtest.c | 18 ++++++++++++++++--
18
2 files changed, 19 insertions(+), 2 deletions(-)
12
19
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h
14
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
21
index XXXXXXX..XXXXXXX 100644
15
Message-id: 20191107163708.833192-12-mreitz@redhat.com
22
--- a/include/sysemu/qtest.h
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
+++ b/include/sysemu/qtest.h
17
---
24
@@ -XXX,XX +XXX,XX @@ bool qtest_driver(void);
18
tests/qemu-iotests/031 | 9 ++++---
25
19
tests/qemu-iotests/039 | 24 ++++++------------
26
void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp);
20
tests/qemu-iotests/059 | 18 ++++++-------
27
21
tests/qemu-iotests/060 | 6 ++---
28
+void qtest_server_set_send_handler(void (*send)(void *, const char *),
22
tests/qemu-iotests/061 | 57 ++++++++++++++++++++++--------------------
29
+ void *opaque);
23
tests/qemu-iotests/079 | 3 +--
30
+
24
tests/qemu-iotests/106 | 2 +-
31
#endif
25
tests/qemu-iotests/108 | 2 +-
32
diff --git a/qtest.c b/qtest.c
26
tests/qemu-iotests/112 | 32 ++++++++++++------------
33
index XXXXXXX..XXXXXXX 100644
27
tests/qemu-iotests/115 | 3 +--
34
--- a/qtest.c
28
tests/qemu-iotests/121 | 6 ++---
35
+++ b/qtest.c
29
tests/qemu-iotests/125 | 2 +-
36
@@ -XXX,XX +XXX,XX @@ static GString *inbuf;
30
tests/qemu-iotests/137 | 2 +-
37
static int irq_levels[MAX_IRQ];
31
tests/qemu-iotests/138 | 3 +--
38
static qemu_timeval start_time;
32
tests/qemu-iotests/175 | 2 +-
39
static bool qtest_opened;
33
tests/qemu-iotests/190 | 2 +-
40
+static void (*qtest_server_send)(void*, const char*);
34
tests/qemu-iotests/191 | 3 +--
41
+static void *qtest_server_send_opaque;
35
tests/qemu-iotests/220 | 4 ++-
42
36
tests/qemu-iotests/243 | 6 +++--
43
#define FMT_timeval "%ld.%06ld"
37
tests/qemu-iotests/244 | 10 +++++---
44
38
tests/qemu-iotests/250 | 3 +--
45
@@ -XXX,XX +XXX,XX @@ static void GCC_FMT_ATTR(1, 2) qtest_log_send(const char *fmt, ...)
39
tests/qemu-iotests/265 | 2 +-
46
va_end(ap);
40
22 files changed, 100 insertions(+), 101 deletions(-)
41
42
diff --git a/tests/qemu-iotests/031 b/tests/qemu-iotests/031
43
index XXXXXXX..XXXXXXX 100755
44
--- a/tests/qemu-iotests/031
45
+++ b/tests/qemu-iotests/031
46
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
47
# This tests qcow2-specific low-level functionality
48
_supported_fmt qcow2
49
_supported_proto file
50
+# We want to test compat=0.10, which does not support refcount widths
51
+# other than 16
52
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
53
54
CLUSTER_SIZE=65536
55
56
# qcow2.py output depends on the exact options used, so override the command
57
# line here as an exception
58
-for IMGOPTS in "compat=0.10" "compat=1.1"; do
59
+for compat in "compat=0.10" "compat=1.1"; do
60
61
echo
62
- echo ===== Testing with -o $IMGOPTS =====
63
+ echo ===== Testing with -o $compat =====
64
echo
65
echo === Create image with unknown header extension ===
66
echo
67
- _make_test_img 64M
68
+ _make_test_img -o $compat 64M
69
$PYTHON qcow2.py "$TEST_IMG" add-header-ext 0x12345678 "This is a test header extension"
70
$PYTHON qcow2.py "$TEST_IMG" dump-header
71
_check_test_img
72
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
73
index XXXXXXX..XXXXXXX 100755
74
--- a/tests/qemu-iotests/039
75
+++ b/tests/qemu-iotests/039
76
@@ -XXX,XX +XXX,XX @@ size=128M
77
echo
78
echo "== Checking that image is clean on shutdown =="
79
80
-IMGOPTS="compat=1.1,lazy_refcounts=on"
81
-_make_test_img $size
82
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
83
84
$QEMU_IO -c "write -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
85
86
@@ -XXX,XX +XXX,XX @@ _check_test_img
87
echo
88
echo "== Creating a dirty image file =="
89
90
-IMGOPTS="compat=1.1,lazy_refcounts=on"
91
-_make_test_img $size
92
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
93
94
_NO_VALGRIND \
95
$QEMU_IO -c "write -P 0x5a 0 512" \
96
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
97
echo
98
echo "== Opening a dirty image read/write should repair it =="
99
100
-IMGOPTS="compat=1.1,lazy_refcounts=on"
101
-_make_test_img $size
102
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
103
104
_NO_VALGRIND \
105
$QEMU_IO -c "write -P 0x5a 0 512" \
106
@@ -XXX,XX +XXX,XX @@ $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
107
echo
108
echo "== Creating an image file with lazy_refcounts=off =="
109
110
-IMGOPTS="compat=1.1,lazy_refcounts=off"
111
-_make_test_img $size
112
+_make_test_img -o "compat=1.1,lazy_refcounts=off" $size
113
114
_NO_VALGRIND \
115
$QEMU_IO -c "write -P 0x5a 0 512" \
116
@@ -XXX,XX +XXX,XX @@ _check_test_img
117
echo
118
echo "== Committing to a backing file with lazy_refcounts=on =="
119
120
-IMGOPTS="compat=1.1,lazy_refcounts=on"
121
-TEST_IMG="$TEST_IMG".base _make_test_img $size
122
+TEST_IMG="$TEST_IMG".base _make_test_img -o "compat=1.1,lazy_refcounts=on" $size
123
124
-IMGOPTS="compat=1.1,lazy_refcounts=on,backing_file=$TEST_IMG.base"
125
-_make_test_img $size
126
+_make_test_img -o "compat=1.1,lazy_refcounts=on,backing_file=$TEST_IMG.base" $size
127
128
$QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io
129
$QEMU_IMG commit "$TEST_IMG"
130
@@ -XXX,XX +XXX,XX @@ TEST_IMG="$TEST_IMG".base _check_test_img
131
echo
132
echo "== Changing lazy_refcounts setting at runtime =="
133
134
-IMGOPTS="compat=1.1,lazy_refcounts=off"
135
-_make_test_img $size
136
+_make_test_img -o "compat=1.1,lazy_refcounts=off" $size
137
138
_NO_VALGRIND \
139
$QEMU_IO -c "reopen -o lazy-refcounts=on" \
140
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "reopen -o lazy-refcounts=on" \
141
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
142
_check_test_img
143
144
-IMGOPTS="compat=1.1,lazy_refcounts=on"
145
-_make_test_img $size
146
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
147
148
_NO_VALGRIND \
149
$QEMU_IO -c "reopen -o lazy-refcounts=off" \
150
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
151
index XXXXXXX..XXXXXXX 100755
152
--- a/tests/qemu-iotests/059
153
+++ b/tests/qemu-iotests/059
154
@@ -XXX,XX +XXX,XX @@ poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00"
155
156
echo
157
echo "=== Testing monolithicFlat creation and opening ==="
158
-IMGOPTS="subformat=monolithicFlat" _make_test_img 2G
159
+_make_test_img -o "subformat=monolithicFlat" 2G
160
_img_info
161
_cleanup_test_img
162
163
echo
164
echo "=== Testing monolithicFlat with zeroed_grain ==="
165
-IMGOPTS="subformat=monolithicFlat,zeroed_grain=on" _make_test_img 2G
166
+_make_test_img -o "subformat=monolithicFlat,zeroed_grain=on" 2G
167
_cleanup_test_img
168
169
echo
170
echo "=== Testing big twoGbMaxExtentFlat ==="
171
-IMGOPTS="subformat=twoGbMaxExtentFlat" _make_test_img 1000G
172
+_make_test_img -o "subformat=twoGbMaxExtentFlat" 1000G
173
$QEMU_IMG info $TEST_IMG | _filter_testdir | sed -e 's/cid: [0-9]*/cid: XXXXXXXX/'
174
_cleanup_test_img
175
176
@@ -XXX,XX +XXX,XX @@ _img_info
177
178
echo
179
echo "=== Testing truncated sparse ==="
180
-IMGOPTS="subformat=monolithicSparse" _make_test_img 100G
181
+_make_test_img -o "subformat=monolithicSparse" 100G
182
truncate -s 10M $TEST_IMG
183
_img_info
184
185
echo
186
echo "=== Converting to streamOptimized from image with small cluster size==="
187
-TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 IMGOPTS="cluster_size=4096" _make_test_img 1G
188
+TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 _make_test_img -o "cluster_size=4096" 1G
189
$QEMU_IO -f qcow2 -c "write -P 0xa 0 512" "$TEST_IMG.qcow2" | _filter_qemu_io
190
$QEMU_IO -f qcow2 -c "write -P 0xb 10240 512" "$TEST_IMG.qcow2" | _filter_qemu_io
191
$QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2" "$TEST_IMG" 2>&1
192
@@ -XXX,XX +XXX,XX @@ echo "=== Testing monolithicFlat with internally generated JSON file name ==="
193
194
echo '--- blkdebug ---'
195
# Should work, because bdrv_dirname() works fine with blkdebug
196
-IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
197
+_make_test_img -o "subformat=monolithicFlat" 64M
198
$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=read_aio" \
199
-c info \
200
2>&1 \
201
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img
202
203
echo '--- quorum ---'
204
# Should not work, because bdrv_dirname() does not work with quorum
205
-IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
206
+_make_test_img -o "subformat=monolithicFlat" 64M
207
cp "$TEST_IMG" "$TEST_IMG.orig"
208
209
filename="json:{
210
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img
211
212
echo
213
echo "=== Testing 4TB monolithicFlat creation and IO ==="
214
-IMGOPTS="subformat=monolithicFlat" _make_test_img 4T
215
+_make_test_img -o "subformat=monolithicFlat" 4T
216
_img_info
217
$QEMU_IO -c "write -P 0xa 900G 512" "$TEST_IMG" | _filter_qemu_io
218
$QEMU_IO -c "read -v 900G 1024" "$TEST_IMG" | _filter_qemu_io
219
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img
220
echo
221
echo "=== Testing qemu-img map on extents ==="
222
for fmt in monolithicSparse twoGbMaxExtentSparse; do
223
- IMGOPTS="subformat=$fmt" _make_test_img 31G
224
+ _make_test_img -o "subformat=$fmt" 31G
225
$QEMU_IO -c "write 65024 1k" "$TEST_IMG" | _filter_qemu_io
226
$QEMU_IO -c "write 2147483136 1k" "$TEST_IMG" | _filter_qemu_io
227
$QEMU_IO -c "write 5G 1k" "$TEST_IMG" | _filter_qemu_io
228
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
229
index XXXXXXX..XXXXXXX 100755
230
--- a/tests/qemu-iotests/060
231
+++ b/tests/qemu-iotests/060
232
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'write 0k 64k' "$BACKING_IMG" | _filter_qemu_io
233
# compat=0.10 is required in order to make the following discard actually
234
# unallocate the sector rather than make it a zero sector - we want COW, after
235
# all.
236
-IMGOPTS='compat=0.10' _make_test_img -b "$BACKING_IMG" 1G
237
+_make_test_img -o 'compat=0.10' -b "$BACKING_IMG" 1G
238
# Write two clusters, the second one enforces creation of an L2 table after
239
# the first data cluster.
240
$QEMU_IO -c 'write 0k 64k' -c 'write 512M 64k' "$TEST_IMG" | _filter_qemu_io
241
@@ -XXX,XX +XXX,XX @@ echo
242
echo "=== Discarding a non-covered in-bounds refblock ==="
243
echo
244
245
-IMGOPTS='refcount_bits=1' _make_test_img 64M
246
+_make_test_img -o 'refcount_bits=1' 64M
247
248
# Pretend there's a refblock somewhere where there is no refblock to
249
# cover it (but the covering refblock has a valid index in the
250
@@ -XXX,XX +XXX,XX @@ echo
251
echo "=== Discarding a refblock covered by an unaligned refblock ==="
252
echo
253
254
-IMGOPTS='refcount_bits=1' _make_test_img 64M
255
+_make_test_img -o 'refcount_bits=1' 64M
256
257
# Same as above
258
poke_file "$TEST_IMG" "$(($rt_offset+8))" "\x00\x00\x00\x10\x00\x00\x00\x00"
259
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
260
index XXXXXXX..XXXXXXX 100755
261
--- a/tests/qemu-iotests/061
262
+++ b/tests/qemu-iotests/061
263
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
264
_supported_fmt qcow2
265
_supported_proto file
266
_supported_os Linux
267
+# Conversion between different compat versions can only really work
268
+# with refcount_bits=16
269
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
270
271
echo
272
echo "=== Testing version downgrade with zero expansion ==="
273
echo
274
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
275
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
276
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
277
$PYTHON qcow2.py "$TEST_IMG" dump-header
278
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
279
@@ -XXX,XX +XXX,XX @@ _check_test_img
280
echo
281
echo "=== Testing version downgrade with zero expansion and 4K cache entries ==="
282
echo
283
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
284
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
285
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
286
$QEMU_IO -c "write -z 32M 128k" "$TEST_IMG" | _filter_qemu_io
287
$QEMU_IO -c map "$TEST_IMG" | _filter_qemu_io
288
@@ -XXX,XX +XXX,XX @@ _check_test_img
289
echo
290
echo "=== Testing dirty version downgrade ==="
291
echo
292
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
293
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
294
_NO_VALGRIND \
295
$QEMU_IO -c "write -P 0x2a 0 128k" -c flush \
296
-c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 | _filter_qemu_io
297
@@ -XXX,XX +XXX,XX @@ _check_test_img
298
echo
299
echo "=== Testing version downgrade with unknown compat/autoclear flags ==="
300
echo
301
-IMGOPTS="compat=1.1" _make_test_img 64M
302
+_make_test_img -o "compat=1.1" 64M
303
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit compatible 42
304
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit autoclear 42
305
$PYTHON qcow2.py "$TEST_IMG" dump-header
306
@@ -XXX,XX +XXX,XX @@ _check_test_img
307
echo
308
echo "=== Testing version upgrade and resize ==="
309
echo
310
-IMGOPTS="compat=0.10" _make_test_img 64M
311
+_make_test_img -o "compat=0.10" 64M
312
$QEMU_IO -c "write -P 0x2a 42M 64k" "$TEST_IMG" | _filter_qemu_io
313
$PYTHON qcow2.py "$TEST_IMG" dump-header
314
$QEMU_IMG amend -o "compat=1.1,lazy_refcounts=on,size=128M" "$TEST_IMG"
315
@@ -XXX,XX +XXX,XX @@ _check_test_img
316
echo
317
echo "=== Testing dirty lazy_refcounts=off ==="
318
echo
319
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
320
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
321
_NO_VALGRIND \
322
$QEMU_IO -c "write -P 0x2a 0 128k" -c flush \
323
-c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 | _filter_qemu_io
324
@@ -XXX,XX +XXX,XX @@ _check_test_img
325
echo
326
echo "=== Testing backing file ==="
327
echo
328
-IMGOPTS="compat=1.1" _make_test_img 64M
329
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
330
+_make_test_img -o "compat=1.1" 64M
331
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
332
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
333
$QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
334
$QEMU_IMG amend -o "backing_file=$TEST_IMG.base,backing_fmt=qcow2" "$TEST_IMG"
335
@@ -XXX,XX +XXX,XX @@ _check_test_img
336
echo
337
echo "=== Testing invalid configurations ==="
338
echo
339
-IMGOPTS="compat=0.10" _make_test_img 64M
340
+_make_test_img -o "compat=0.10" 64M
341
$QEMU_IMG amend -o "lazy_refcounts=on" "$TEST_IMG"
342
$QEMU_IMG amend -o "compat=1.1" "$TEST_IMG" # actually valid
343
$QEMU_IMG amend -o "compat=0.10,lazy_refcounts=on" "$TEST_IMG"
344
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG amend -o "preallocation=on" "$TEST_IMG"
345
echo
346
echo "=== Testing correct handling of unset value ==="
347
echo
348
-IMGOPTS="compat=1.1,cluster_size=1k" _make_test_img 64M
349
+_make_test_img -o "compat=1.1,cluster_size=1k" 64M
350
echo "Should work:"
351
$QEMU_IMG amend -o "lazy_refcounts=on" "$TEST_IMG"
352
echo "Should not work:" # Just to know which of these tests actually fails
353
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG amend -o "cluster_size=64k" "$TEST_IMG"
354
echo
355
echo "=== Testing zero expansion on inactive clusters ==="
356
echo
357
-IMGOPTS="compat=1.1" _make_test_img 64M
358
+_make_test_img -o "compat=1.1" 64M
359
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
360
$QEMU_IMG snapshot -c foo "$TEST_IMG"
361
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG" | _filter_qemu_io
362
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
363
echo
364
echo "=== Testing zero expansion on shared L2 table ==="
365
echo
366
-IMGOPTS="compat=1.1" _make_test_img 64M
367
+_make_test_img -o "compat=1.1" 64M
368
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
369
$QEMU_IMG snapshot -c foo "$TEST_IMG"
370
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
371
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
372
echo
373
echo "=== Testing zero expansion on backed image ==="
374
echo
375
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
376
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
377
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
378
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
379
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M
380
$QEMU_IO -c "read -P 0x2a 0 128k" -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io
381
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
382
_check_test_img
383
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 64k" -c "read -P 0x2a 64k 64k" "$TEST_IMG" | _filter_qe
384
echo
385
echo "=== Testing zero expansion on backed inactive clusters ==="
386
echo
387
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
388
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
389
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
390
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
391
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M
392
$QEMU_IO -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io
393
$QEMU_IMG snapshot -c foo "$TEST_IMG"
394
$QEMU_IO -c "write -P 0x42 0 128k" "$TEST_IMG" | _filter_qemu_io
395
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 64k" -c "read -P 0x2a 64k 64k" "$TEST_IMG" | _filter_qe
396
echo
397
echo "=== Testing zero expansion on backed image with shared L2 table ==="
398
echo
399
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
400
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
401
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
402
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
403
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M
404
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
405
$QEMU_IMG snapshot -c foo "$TEST_IMG"
406
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
407
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
408
echo
409
echo "=== Testing preallocated zero expansion on full image ==="
410
echo
411
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG" _make_test_img 64M
412
+TEST_IMG="$TEST_IMG" _make_test_img -o "compat=1.1" 64M
413
$QEMU_IO -c "write -P 0x2a 0 64M" "$TEST_IMG" -c "write -z 0 64M" | _filter_qemu_io
414
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
415
_check_test_img
416
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 64M" "$TEST_IMG" | _filter_qemu_io
417
echo
418
echo "=== Testing progress report without snapshot ==="
419
echo
420
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 4G
421
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 4G
422
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 4G
423
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 4G
424
$QEMU_IO -c "write -z 0 64k" \
425
-c "write -z 1G 64k" \
426
-c "write -z 2G 64k" \
427
@@ -XXX,XX +XXX,XX @@ _check_test_img
428
echo
429
echo "=== Testing progress report with snapshot ==="
430
echo
431
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 4G
432
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 4G
433
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 4G
434
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 4G
435
$QEMU_IO -c "write -z 0 64k" \
436
-c "write -z 1G 64k" \
437
-c "write -z 2G 64k" \
438
@@ -XXX,XX +XXX,XX @@ _check_test_img
439
echo
440
echo "=== Testing version downgrade with external data file ==="
441
echo
442
-IMGOPTS="compat=1.1,data_file=$TEST_IMG.data" _make_test_img 64M
443
+_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
444
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
445
_img_info --format-specific
446
_check_test_img
447
@@ -XXX,XX +XXX,XX @@ _check_test_img
448
echo
449
echo "=== Try changing the external data file ==="
450
echo
451
-IMGOPTS="compat=1.1" _make_test_img 64M
452
+_make_test_img -o "compat=1.1" 64M
453
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
454
455
echo
456
-IMGOPTS="compat=1.1,data_file=$TEST_IMG.data" _make_test_img 64M
457
+_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
458
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
459
_img_info --format-specific
460
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
461
@@ -XXX,XX +XXX,XX @@ TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info -
462
echo
463
echo "=== Clearing and setting data-file-raw ==="
464
echo
465
-IMGOPTS="compat=1.1,data_file=$TEST_IMG.data,data_file_raw=on" _make_test_img 64M
466
+_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data,data_file_raw=on" 64M
467
$QEMU_IMG amend -o "data_file_raw=on" "$TEST_IMG"
468
_img_info --format-specific
469
_check_test_img
470
diff --git a/tests/qemu-iotests/079 b/tests/qemu-iotests/079
471
index XXXXXXX..XXXXXXX 100755
472
--- a/tests/qemu-iotests/079
473
+++ b/tests/qemu-iotests/079
474
@@ -XXX,XX +XXX,XX @@ echo
475
cluster_sizes="16384 32768 65536 131072 262144 524288 1048576 2097152 4194304"
476
477
for s in $cluster_sizes; do
478
- IMGOPTS=$(_optstr_add "$IMGOPTS" "preallocation=metadata,cluster_size=$s") \
479
- _make_test_img 4G
480
+ _make_test_img -o "preallocation=metadata,cluster_size=$s" 4G
481
done
482
483
# success, all done
484
diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106
485
index XXXXXXX..XXXXXXX 100755
486
--- a/tests/qemu-iotests/106
487
+++ b/tests/qemu-iotests/106
488
@@ -XXX,XX +XXX,XX @@ for create_mode in off falloc full; do
489
echo
490
echo "--- create_mode=$create_mode growth_mode=$growth_mode ---"
491
492
- IMGOPTS="preallocation=$create_mode" _make_test_img ${CREATION_SIZE}K
493
+ _make_test_img -o "preallocation=$create_mode" ${CREATION_SIZE}K
494
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
495
496
expected_size=0
497
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
498
index XXXXXXX..XXXXXXX 100755
499
--- a/tests/qemu-iotests/108
500
+++ b/tests/qemu-iotests/108
501
@@ -XXX,XX +XXX,XX @@ echo
502
echo '=== Repairing unreferenced data cluster in new refblock area ==='
503
echo
504
505
-IMGOPTS='cluster_size=512' _make_test_img 64M
506
+_make_test_img -o 'cluster_size=512' 64M
507
# Allocate the first 128 kB in the image (first refblock)
508
$QEMU_IO -c 'write 0 0x1b200' "$TEST_IMG" | _filter_qemu_io
509
# should be 131072 == 0x20000
510
diff --git a/tests/qemu-iotests/112 b/tests/qemu-iotests/112
511
index XXXXXXX..XXXXXXX 100755
512
--- a/tests/qemu-iotests/112
513
+++ b/tests/qemu-iotests/112
514
@@ -XXX,XX +XXX,XX @@ echo '=== refcount_bits limits ==='
515
echo
516
517
# Must be positive (non-zero)
518
-IMGOPTS="$IMGOPTS,refcount_bits=0" _make_test_img 64M
519
+_make_test_img -o "refcount_bits=0" 64M
520
# Must be positive (non-negative)
521
-IMGOPTS="$IMGOPTS,refcount_bits=-1" _make_test_img 64M
522
+_make_test_img -o "refcount_bits=-1" 64M
523
# May not exceed 64
524
-IMGOPTS="$IMGOPTS,refcount_bits=128" _make_test_img 64M
525
+_make_test_img -o "refcount_bits=128" 64M
526
# Must be a power of two
527
-IMGOPTS="$IMGOPTS,refcount_bits=42" _make_test_img 64M
528
+_make_test_img -o "refcount_bits=42" 64M
529
530
# 1 is the minimum
531
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
532
+_make_test_img -o "refcount_bits=1" 64M
533
print_refcount_bits
534
535
# 64 is the maximum
536
-IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
537
+_make_test_img -o "refcount_bits=64" 64M
538
print_refcount_bits
539
540
# 16 is the default
541
@@ -XXX,XX +XXX,XX @@ echo '=== refcount_bits and compat=0.10 ==='
542
echo
543
544
# Should work
545
-IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=16" _make_test_img 64M
546
+_make_test_img -o "compat=0.10,refcount_bits=16" 64M
547
print_refcount_bits
548
549
# Should not work
550
-IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=1" _make_test_img 64M
551
-IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=64" _make_test_img 64M
552
+_make_test_img -o "compat=0.10,refcount_bits=1" 64M
553
+_make_test_img -o "compat=0.10,refcount_bits=64" 64M
554
555
556
echo
557
echo '=== Snapshot limit on refcount_bits=1 ==='
558
echo
559
560
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
561
+_make_test_img -o "refcount_bits=1" 64M
562
print_refcount_bits
563
564
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
565
@@ -XXX,XX +XXX,XX @@ echo
566
echo '=== Snapshot limit on refcount_bits=2 ==='
567
echo
568
569
-IMGOPTS="$IMGOPTS,refcount_bits=2" _make_test_img 64M
570
+_make_test_img -o "refcount_bits=2" 64M
571
print_refcount_bits
572
573
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
574
@@ -XXX,XX +XXX,XX @@ echo
575
echo '=== Compressed clusters with refcount_bits=1 ==='
576
echo
577
578
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
579
+_make_test_img -o "refcount_bits=1" 64M
580
print_refcount_bits
581
582
# Both should fit into a single host cluster; instead of failing to increase the
583
@@ -XXX,XX +XXX,XX @@ echo
584
echo '=== MSb set in 64 bit refcount ==='
585
echo
586
587
-IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
588
+_make_test_img -o "refcount_bits=64" 64M
589
print_refcount_bits
590
591
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
592
@@ -XXX,XX +XXX,XX @@ echo
593
echo '=== Snapshot on maximum 64 bit refcount value ==='
594
echo
595
596
-IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
597
+_make_test_img -o "refcount_bits=64" 64M
598
print_refcount_bits
599
600
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
601
@@ -XXX,XX +XXX,XX @@ echo
602
echo '=== Testing too many references for check ==='
603
echo
604
605
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
606
+_make_test_img -o "refcount_bits=1" 64M
607
print_refcount_bits
608
609
# This cluster should be created at 0x50000
610
@@ -XXX,XX +XXX,XX @@ echo
611
echo '=== Multiple walks necessary during amend ==='
612
echo
613
614
-IMGOPTS="$IMGOPTS,refcount_bits=1,cluster_size=512" _make_test_img 64k
615
+_make_test_img -o "refcount_bits=1,cluster_size=512" 64k
616
617
# Cluster 0 is the image header, clusters 1 to 4 are used by the L1 table, a
618
# single L2 table, the reftable and a single refblock. This creates 58 data
619
diff --git a/tests/qemu-iotests/115 b/tests/qemu-iotests/115
620
index XXXXXXX..XXXXXXX 100755
621
--- a/tests/qemu-iotests/115
622
+++ b/tests/qemu-iotests/115
623
@@ -XXX,XX +XXX,XX @@ echo
624
# least 256 MB. We can achieve that by using preallocation=metadata for an image
625
# which has a guest disk size of 256 MB.
626
627
-IMGOPTS="$IMGOPTS,refcount_bits=64,cluster_size=512,preallocation=metadata" \
628
- _make_test_img 256M
629
+_make_test_img -o "refcount_bits=64,cluster_size=512,preallocation=metadata" 256M
630
631
# We know for sure that the L1 and refcount tables do not overlap with any other
632
# structure because the metadata overlap checks would have caught that case.
633
diff --git a/tests/qemu-iotests/121 b/tests/qemu-iotests/121
634
index XXXXXXX..XXXXXXX 100755
635
--- a/tests/qemu-iotests/121
636
+++ b/tests/qemu-iotests/121
637
@@ -XXX,XX +XXX,XX @@ echo
638
# Preallocation speeds up the write operation, but preallocating everything will
639
# destroy the purpose of the write; so preallocate one KB less than what would
640
# cause a reftable growth...
641
-IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64512K
642
+_make_test_img -o 'preallocation=metadata,cluster_size=1k' 64512K
643
# ...and make the image the desired size afterwards.
644
$QEMU_IMG resize "$TEST_IMG" 65M
645
646
@@ -XXX,XX +XXX,XX @@ echo
647
echo '--- Test 2 ---'
648
echo
649
650
-IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64513K
651
+_make_test_img -o 'preallocation=metadata,cluster_size=1k' 64513K
652
# This results in an L1 table growth which in turn results in some clusters at
653
# the start of the image becoming free
654
$QEMU_IMG resize "$TEST_IMG" 65M
655
@@ -XXX,XX +XXX,XX @@ echo
656
echo '=== Allocating a new refcount block must not leave holes in the image ==='
657
echo
658
659
-IMGOPTS='cluster_size=512,refcount_bits=16' _make_test_img 1M
660
+_make_test_img -o 'cluster_size=512,refcount_bits=16' 1M
661
662
# This results in an image with 256 used clusters: the qcow2 header,
663
# the refcount table, one refcount block, the L1 table, four L2 tables
664
diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125
665
index XXXXXXX..XXXXXXX 100755
666
--- a/tests/qemu-iotests/125
667
+++ b/tests/qemu-iotests/125
668
@@ -XXX,XX +XXX,XX @@ for GROWTH_SIZE in 16 48 80; do
669
for growth_mode in off metadata falloc full; do
670
echo "--- cluster_size=$cluster_size growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---"
671
672
- IMGOPTS="preallocation=$create_mode,cluster_size=$cluster_size" _make_test_img ${CREATION_SIZE}
673
+ _make_test_img -o "preallocation=$create_mode,cluster_size=$cluster_size" ${CREATION_SIZE}
674
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
675
676
host_size_0=$(get_image_size_on_host)
677
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
678
index XXXXXXX..XXXXXXX 100755
679
--- a/tests/qemu-iotests/137
680
+++ b/tests/qemu-iotests/137
681
@@ -XXX,XX +XXX,XX @@ $QEMU_IO \
682
-c "reopen -o cache-clean-interval=-1" \
683
"$TEST_IMG" | _filter_qemu_io
684
685
-IMGOPTS="cluster_size=256k" _make_test_img 32P
686
+_make_test_img -o "cluster_size=256k" 32P
687
$QEMU_IO \
688
-c "reopen -o l2-cache-entry-size=512,l2-cache-size=1T" \
689
"$TEST_IMG" | _filter_qemu_io
690
diff --git a/tests/qemu-iotests/138 b/tests/qemu-iotests/138
691
index XXXXXXX..XXXXXXX 100755
692
--- a/tests/qemu-iotests/138
693
+++ b/tests/qemu-iotests/138
694
@@ -XXX,XX +XXX,XX @@ echo
695
echo '=== Check on an image with a multiple of 2^32 clusters ==='
696
echo
697
698
-IMGOPTS=$(_optstr_add "$IMGOPTS" "cluster_size=512") \
699
- _make_test_img 512
700
+_make_test_img -o "cluster_size=512" 512
701
702
# Allocate L2 table
703
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
704
diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175
705
index XXXXXXX..XXXXXXX 100755
706
--- a/tests/qemu-iotests/175
707
+++ b/tests/qemu-iotests/175
708
@@ -XXX,XX +XXX,XX @@ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_block
709
for mode in off full falloc; do
710
echo
711
echo "== creating image with preallocation $mode =="
712
- IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt
713
+ _make_test_img -o preallocation=$mode $size | _filter_imgfmt
714
stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
715
done
716
717
diff --git a/tests/qemu-iotests/190 b/tests/qemu-iotests/190
718
index XXXXXXX..XXXXXXX 100755
719
--- a/tests/qemu-iotests/190
720
+++ b/tests/qemu-iotests/190
721
@@ -XXX,XX +XXX,XX @@ _supported_proto file
722
echo "== Huge file =="
723
echo
724
725
-IMGOPTS='cluster_size=2M' _make_test_img 2T
726
+_make_test_img -o 'cluster_size=2M' 2T
727
728
$QEMU_IMG measure -O raw -f qcow2 "$TEST_IMG"
729
$QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG"
730
diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191
731
index XXXXXXX..XXXXXXX 100755
732
--- a/tests/qemu-iotests/191
733
+++ b/tests/qemu-iotests/191
734
@@ -XXX,XX +XXX,XX @@ echo === Preparing and starting VM ===
735
echo
736
737
TEST_IMG="${TEST_IMG}.base" _make_test_img $size
738
-IMGOPTS=$(_optstr_add "$IMGOPTS" "backing_fmt=$IMGFMT") \
739
- TEST_IMG="${TEST_IMG}.mid" _make_test_img -b "${TEST_IMG}.base"
740
+TEST_IMG="${TEST_IMG}.mid" _make_test_img -o "backing_fmt=$IMGFMT" -b "${TEST_IMG}.base"
741
_make_test_img -b "${TEST_IMG}.mid"
742
TEST_IMG="${TEST_IMG}.ovl2" _make_test_img -b "${TEST_IMG}.mid"
743
744
diff --git a/tests/qemu-iotests/220 b/tests/qemu-iotests/220
745
index XXXXXXX..XXXXXXX 100755
746
--- a/tests/qemu-iotests/220
747
+++ b/tests/qemu-iotests/220
748
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
749
_supported_fmt qcow2
750
_supported_proto file
751
_supported_os Linux
752
+# To use a different refcount width but 16 bits we need compat=1.1
753
+_unsupported_imgopts 'compat=0.10'
754
755
echo "== Creating huge file =="
756
757
@@ -XXX,XX +XXX,XX @@ echo "== Creating huge file =="
758
# of a HUGE (but very sparse) file. tmpfs works, ext4 does not.
759
_require_large_file 513T
760
761
-IMGOPTS='cluster_size=2M,refcount_bits=1' _make_test_img 513T
762
+_make_test_img -o 'cluster_size=2M,refcount_bits=1' 513T
763
764
echo "== Populating refcounts =="
765
# We want an image with 256M refcounts * 2M clusters = 512T referenced.
766
diff --git a/tests/qemu-iotests/243 b/tests/qemu-iotests/243
767
index XXXXXXX..XXXXXXX 100755
768
--- a/tests/qemu-iotests/243
769
+++ b/tests/qemu-iotests/243
770
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
771
_supported_fmt qcow2
772
_supported_proto file
773
_supported_os Linux
774
+# External data files do not work with compat=0.10
775
+_unsupported_imgopts 'compat=0.10'
776
777
for mode in off metadata falloc full; do
778
779
@@ -XXX,XX +XXX,XX @@ for mode in off metadata falloc full; do
780
echo "=== preallocation=$mode ==="
781
echo
782
783
- IMGOPTS="preallocation=$mode" _make_test_img 64M
784
+ _make_test_img -o "preallocation=$mode" 64M
785
786
printf "File size: "
787
du -b $TEST_IMG | cut -f1
788
@@ -XXX,XX +XXX,XX @@ for mode in off metadata falloc full; do
789
echo "=== External data file: preallocation=$mode ==="
790
echo
791
792
- IMGOPTS="data_file=$TEST_IMG.data,preallocation=$mode" _make_test_img 64M
793
+ _make_test_img -o "data_file=$TEST_IMG.data,preallocation=$mode" 64M
794
795
echo -n "qcow2 file size: "
796
du -b $TEST_IMG | cut -f1
797
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
798
index XXXXXXX..XXXXXXX 100755
799
--- a/tests/qemu-iotests/244
800
+++ b/tests/qemu-iotests/244
801
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
802
_supported_fmt qcow2
803
_supported_proto file
804
_supported_os Linux
805
+# External data files do not work with compat=0.10
806
+_unsupported_imgopts 'compat=0.10'
807
808
echo
809
echo "=== Create and open image with external data file ==="
810
echo
811
812
echo "With data file name in the image:"
813
-IMGOPTS="data_file=$TEST_IMG.data" _make_test_img 64M
814
+_make_test_img -o "data_file=$TEST_IMG.data" 64M
815
_check_test_img
816
817
$QEMU_IO -c "open $TEST_IMG" -c "read -P 0 0 64k" 2>&1 | _filter_qemu_io | _filter_testdir
818
@@ -XXX,XX +XXX,XX @@ echo
819
echo "=== Standalone image with external data file (efficient) ==="
820
echo
821
822
-IMGOPTS="data_file=$TEST_IMG.data" _make_test_img 64M
823
+_make_test_img -o "data_file=$TEST_IMG.data" 64M
824
825
echo -n "qcow2 file size before I/O: "
826
du -b $TEST_IMG | cut -f1
827
@@ -XXX,XX +XXX,XX @@ echo
828
echo "=== Standalone image with external data file (valid raw) ==="
829
echo
830
831
-IMGOPTS="data_file=$TEST_IMG.data,data_file_raw=on" _make_test_img 64M
832
+_make_test_img -o "data_file=$TEST_IMG.data,data_file_raw=on" 64M
833
834
echo -n "qcow2 file size before I/O: "
835
du -b $TEST_IMG | cut -f1
836
@@ -XXX,XX +XXX,XX @@ echo
837
echo "=== bdrv_co_block_status test for file and offset=0 ==="
838
echo
839
840
-IMGOPTS="data_file=$TEST_IMG.data" _make_test_img 64M
841
+_make_test_img -o "data_file=$TEST_IMG.data" 64M
842
843
$QEMU_IO -c 'write -P 0x11 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
844
$QEMU_IO -c 'read -P 0x11 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
845
diff --git a/tests/qemu-iotests/250 b/tests/qemu-iotests/250
846
index XXXXXXX..XXXXXXX 100755
847
--- a/tests/qemu-iotests/250
848
+++ b/tests/qemu-iotests/250
849
@@ -XXX,XX +XXX,XX @@ disk_usage()
850
}
47
}
851
48
852
size=2100M
49
-static void do_qtest_send(CharBackend *chr, const char *str, size_t len)
853
-IMGOPTS="cluster_size=1M,preallocation=metadata"
50
+static void qtest_server_char_be_send(void *opaque, const char *str)
854
51
{
855
-_make_test_img $size
52
+ size_t len = strlen(str);
856
+_make_test_img -o "cluster_size=1M,preallocation=metadata" $size
53
+ CharBackend* chr = (CharBackend *)opaque;
857
$QEMU_IO -c 'discard 0 10M' -c 'discard 2090M 10M' \
54
qemu_chr_fe_write_all(chr, (uint8_t *)str, len);
858
-c 'write 2090M 10M' -c 'write 0 10M' "$TEST_IMG" | _filter_qemu_io
55
if (qtest_log_fp && qtest_opened) {
859
56
fprintf(qtest_log_fp, "%s", str);
860
diff --git a/tests/qemu-iotests/265 b/tests/qemu-iotests/265
57
@@ -XXX,XX +XXX,XX @@ static void do_qtest_send(CharBackend *chr, const char *str, size_t len)
861
index XXXXXXX..XXXXXXX 100755
58
862
--- a/tests/qemu-iotests/265
59
static void qtest_send(CharBackend *chr, const char *str)
863
+++ b/tests/qemu-iotests/265
60
{
864
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
61
- do_qtest_send(chr, str, strlen(str));
865
echo '--- Writing to the image ---'
62
+ qtest_server_send(qtest_server_send_opaque, str);
866
63
}
867
# Reduce cluster size so we get more and quicker I/O
64
868
-IMGOPTS='cluster_size=4096' _make_test_img 1M
65
static void GCC_FMT_ATTR(2, 3) qtest_sendf(CharBackend *chr,
869
+_make_test_img -o 'cluster_size=4096' 1M
66
@@ -XXX,XX +XXX,XX @@ void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **
870
(for ((kb = 1024 - 4; kb >= 0; kb -= 4)); do \
67
qemu_chr_fe_set_echo(&qtest_chr, true);
871
echo "aio_write -P 42 $((kb + 1))k 2k"; \
68
872
done) \
69
inbuf = g_string_new("");
70
+
71
+ if (!qtest_server_send) {
72
+ qtest_server_set_send_handler(qtest_server_char_be_send, &qtest_chr);
73
+ }
74
+}
75
+
76
+void qtest_server_set_send_handler(void (*send)(void*, const char*), void *opaque)
77
+{
78
+ qtest_server_send = send;
79
+ qtest_server_send_opaque = opaque;
80
}
81
82
bool qtest_driver(void)
873
--
83
--
874
2.24.1
84
2.24.1
875
85
876
diff view generated by jsdifflib
1
The problem with allowing the data_file option is that you want to use a
1
From: Alexander Bulekov <alxndr@bu.edu>
2
different data file per image used in the test. Therefore, we need to
3
allow patterns like -o data_file='$TEST_IMG.data_file'.
4
2
5
Then, we need to filter it out from qemu-img map, qemu-img create, and
3
This makes it simple to swap the transport functions for qtest commands
6
remove the data file in _rm_test_img.
4
to and from the qtest client. For example, now it is possible to
5
directly pass qtest commands to a server handler that exists within the
6
same process, without the standard way of writing to a file descriptor.
7
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
9
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-id: 20191107163708.833192-23-mreitz@redhat.com
10
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 20200220041118.23264-7-alxndr@bu.edu
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
13
---
13
tests/qemu-iotests/common.filter | 23 +++++++++++++++++++++--
14
tests/qtest/libqtest.c | 48 ++++++++++++++++++++++++++++++++++--------
14
tests/qemu-iotests/common.rc | 22 +++++++++++++++++++++-
15
1 file changed, 39 insertions(+), 9 deletions(-)
15
2 files changed, 42 insertions(+), 3 deletions(-)
16
16
17
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
17
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/common.filter
19
--- a/tests/qtest/libqtest.c
20
+++ b/tests/qemu-iotests/common.filter
20
+++ b/tests/qtest/libqtest.c
21
@@ -XXX,XX +XXX,XX @@ _filter_actual_image_size()
21
@@ -XXX,XX +XXX,XX @@
22
# replace driver-specific options in the "Formatting..." line
22
#define SOCKET_TIMEOUT 50
23
_filter_img_create()
23
#define SOCKET_MAX_FDS 16
24
25
+
26
+typedef void (*QTestSendFn)(QTestState *s, const char *buf);
27
+typedef GString* (*QTestRecvFn)(QTestState *);
28
+
29
+typedef struct QTestClientTransportOps {
30
+ QTestSendFn send; /* for sending qtest commands */
31
+ QTestRecvFn recv_line; /* for receiving qtest command responses */
32
+} QTestTransportOps;
33
+
34
struct QTestState
24
{
35
{
25
- $SED -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
36
int fd;
26
+ data_file_filter=()
37
@@ -XXX,XX +XXX,XX @@ struct QTestState
27
+ if data_file=$(_get_data_file "$TEST_IMG"); then
38
bool big_endian;
28
+ data_file_filter=(-e "s# data_file=$data_file##")
39
bool irq_level[MAX_IRQ];
29
+ fi
40
GString *rx;
41
+ QTestTransportOps ops;
42
};
43
44
static GHookList abrt_hooks;
45
@@ -XXX,XX +XXX,XX @@ static struct sigaction sigact_old;
46
47
static int qtest_query_target_endianness(QTestState *s);
48
49
+static void qtest_client_socket_send(QTestState*, const char *buf);
50
+static void socket_send(int fd, const char *buf, size_t size);
30
+
51
+
31
+ $SED "${data_file_filter[@]}" \
52
+static GString *qtest_client_socket_recv_line(QTestState *);
32
+ -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
53
+
33
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
54
+static void qtest_client_set_tx_handler(QTestState *s, QTestSendFn send);
34
-e "s#$TEST_DIR#TEST_DIR#g" \
55
+static void qtest_client_set_rx_handler(QTestState *s, QTestRecvFn recv);
35
-e "s#$SOCK_DIR#SOCK_DIR#g" \
56
+
36
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
57
static int init_socket(const char *socket_path)
37
# human and json output
38
_filter_qemu_img_map()
39
{
58
{
40
+ # Assuming the data_file value in $IMGOPTS contains a '$TEST_IMG',
59
struct sockaddr_un addr;
41
+ # create a filter that replaces the data file name by $TEST_IMG.
60
@@ -XXX,XX +XXX,XX @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
42
+ # Example:
61
sock = init_socket(socket_path);
43
+ # In $IMGOPTS: 'data_file=$TEST_IMG.data_file'
62
qmpsock = init_socket(qmp_socket_path);
44
+ # Then data_file_pattern == '\(.*\).data_file'
63
45
+ # And data_file_filter == -e 's#\(.*\).data_file#\1#
64
+ qtest_client_set_rx_handler(s, qtest_client_socket_recv_line);
46
+ data_file_filter=()
65
+ qtest_client_set_tx_handler(s, qtest_client_socket_send);
47
+ if data_file_pattern=$(_get_data_file '\\(.*\\)'); then
48
+ data_file_filter=(-e "s#$data_file_pattern#\\1#")
49
+ fi
50
+
66
+
51
$SED -e 's/\([0-9a-fx]* *[0-9a-fx]* *\)[0-9a-fx]* */\1/g' \
67
qtest_add_abrt_handler(kill_qemu_hook_func, s);
52
-e 's/"offset": [0-9]\+/"offset": OFFSET/g' \
68
53
- -e 's/Mapped to *//' | _filter_testdir | _filter_imgfmt
69
command = g_strdup_printf("exec %s "
54
+ -e 's/Mapped to *//' \
70
@@ -XXX,XX +XXX,XX @@ static void socket_send(int fd, const char *buf, size_t size)
55
+ "${data_file_filter[@]}" \
71
}
56
+ | _filter_testdir | _filter_imgfmt
57
}
72
}
58
73
59
_filter_nbd()
74
-static void socket_sendf(int fd, const char *fmt, va_list ap)
60
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
75
+static void qtest_client_socket_send(QTestState *s, const char *buf)
61
index XXXXXXX..XXXXXXX 100644
76
{
62
--- a/tests/qemu-iotests/common.rc
77
- gchar *str = g_strdup_vprintf(fmt, ap);
63
+++ b/tests/qemu-iotests/common.rc
78
- size_t size = strlen(str);
64
@@ -XXX,XX +XXX,XX @@ _stop_nbd_server()
79
-
65
fi
80
- socket_send(fd, str, size);
81
- g_free(str);
82
+ socket_send(s->fd, buf, strlen(buf));
66
}
83
}
67
84
68
+# Gets the data_file value from IMGOPTS and replaces the '$TEST_IMG'
85
static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
69
+# pattern by '$1'
86
@@ -XXX,XX +XXX,XX @@ static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
70
+# Caution: The replacement is done with sed, so $1 must be escaped
87
va_list ap;
71
+# properly. (The delimiter is '#'.)
88
72
+_get_data_file()
89
va_start(ap, fmt);
90
- socket_sendf(s->fd, fmt, ap);
91
+ gchar *str = g_strdup_vprintf(fmt, ap);
92
va_end(ap);
93
+
94
+ s->ops.send(s, str);
95
+ g_free(str);
96
}
97
98
/* Sends a message and file descriptors to the socket.
99
@@ -XXX,XX +XXX,XX @@ static void socket_send_fds(int socket_fd, int *fds, size_t fds_num,
100
g_assert_cmpint(ret, >, 0);
101
}
102
103
-static GString *qtest_recv_line(QTestState *s)
104
+static GString *qtest_client_socket_recv_line(QTestState *s)
105
{
106
GString *line;
107
size_t offset;
108
@@ -XXX,XX +XXX,XX @@ static gchar **qtest_rsp(QTestState *s, int expected_args)
109
int i;
110
111
redo:
112
- line = qtest_recv_line(s);
113
+ line = s->ops.recv_line(s);
114
words = g_strsplit(line->str, " ", 0);
115
g_string_free(line, TRUE);
116
117
@@ -XXX,XX +XXX,XX @@ void qmp_assert_error_class(QDict *rsp, const char *class)
118
119
qobject_unref(rsp);
120
}
121
+
122
+static void qtest_client_set_tx_handler(QTestState *s,
123
+ QTestSendFn send)
73
+{
124
+{
74
+ if ! echo "$IMGOPTS" | grep -q 'data_file='; then
125
+ s->ops.send = send;
75
+ return 1
76
+ fi
77
+
78
+ echo "$IMGOPTS" | sed -e 's/.*data_file=\([^,]*\).*/\1/' \
79
+ | sed -e "s#\\\$TEST_IMG#$1#"
80
+}
126
+}
81
+
127
+static void qtest_client_set_rx_handler(QTestState *s, QTestRecvFn recv)
82
_make_test_img()
128
+{
83
{
129
+ s->ops.recv_line = recv;
84
# extra qemu-img options can be added by tests
130
+}
85
@@ -XXX,XX +XXX,XX @@ _make_test_img()
86
fi
87
88
if [ -n "$IMGOPTS" ]; then
89
- optstr=$(_optstr_add "$optstr" "$IMGOPTS")
90
+ imgopts_expanded=$(echo "$IMGOPTS" | sed -e "s#\\\$TEST_IMG#$img_name#")
91
+ optstr=$(_optstr_add "$optstr" "$imgopts_expanded")
92
fi
93
if [ -n "$IMGKEYSECRET" ]; then
94
object_options="--object secret,id=keysec0,data=$IMGKEYSECRET"
95
@@ -XXX,XX +XXX,XX @@ _rm_test_img()
96
# Remove all the extents for vmdk
97
"$QEMU_IMG" info "$img" 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
98
| xargs -I {} rm -f "{}"
99
+ elif [ "$IMGFMT" = "qcow2" ]; then
100
+ # Remove external data file
101
+ if data_file=$(_get_data_file "$img"); then
102
+ rm -f "$data_file"
103
+ fi
104
fi
105
rm -f "$img"
106
}
107
--
131
--
108
2.24.1
132
2.24.1
109
133
110
diff view generated by jsdifflib
1
The image end offset as reported by qemu-img check is different when
1
From: Alexander Bulekov <alxndr@bu.edu>
2
using an external data file; we do not care about its value here, so we
3
can just filter it. Incidentally, common.rc already has _check_test_img
4
for us which does exactly that.
5
2
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
When using qtest "in-process" communication, qtest_sendf directly calls
7
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
a function in the server (qtest.c). Previously, bufwrite used
8
Message-id: 20191107163708.833192-18-mreitz@redhat.com
5
socket_send, which bypasses the TransportOps enabling the call into
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
qtest.c. This change replaces the socket_send calls with ops->send,
7
maintaining the benefits of the direct socket_send call, while adding
8
support for in-process qtest calls.
9
10
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
13
Message-id: 20200220041118.23264-8-alxndr@bu.edu
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
15
---
11
tests/qemu-iotests/091 | 2 +-
16
tests/qtest/libqtest.c | 71 ++++++++++++++++++++++++++++++++++++++++--
12
tests/qemu-iotests/091.out | 2 --
17
tests/qtest/libqtest.h | 4 +++
13
2 files changed, 1 insertion(+), 3 deletions(-)
18
2 files changed, 73 insertions(+), 2 deletions(-)
14
19
15
diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091
20
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/091
18
+++ b/tests/qemu-iotests/091
19
@@ -XXX,XX +XXX,XX @@ echo "Check image pattern"
20
${QEMU_IO} -c "read -P 0x22 0 4M" "${TEST_IMG}" | _filter_testdir | _filter_qemu_io
21
22
echo "Running 'qemu-img check -r all \$TEST_IMG'"
23
-"${QEMU_IMG}" check -r all "${TEST_IMG}" 2>&1 | _filter_testdir | _filter_qemu
24
+_check_test_img -r all
25
26
echo "*** done"
27
rm -f $seq.full
28
diff --git a/tests/qemu-iotests/091.out b/tests/qemu-iotests/091.out
29
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
30
--- a/tests/qemu-iotests/091.out
22
--- a/tests/qtest/libqtest.c
31
+++ b/tests/qemu-iotests/091.out
23
+++ b/tests/qtest/libqtest.c
32
@@ -XXX,XX +XXX,XX @@ read 4194304/4194304 bytes at offset 0
24
@@ -XXX,XX +XXX,XX @@
33
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
25
34
Running 'qemu-img check -r all $TEST_IMG'
26
35
No errors were found on the image.
27
typedef void (*QTestSendFn)(QTestState *s, const char *buf);
36
-80/16384 = 0.49% allocated, 0.00% fragmented, 0.00% compressed clusters
28
+typedef void (*ExternalSendFn)(void *s, const char *buf);
37
-Image end offset: 5570560
29
typedef GString* (*QTestRecvFn)(QTestState *);
38
*** done
30
31
typedef struct QTestClientTransportOps {
32
QTestSendFn send; /* for sending qtest commands */
33
+
34
+ /*
35
+ * use external_send to send qtest command strings through functions which
36
+ * do not accept a QTestState as the first parameter.
37
+ */
38
+ ExternalSendFn external_send;
39
+
40
QTestRecvFn recv_line; /* for receiving qtest command responses */
41
} QTestTransportOps;
42
43
@@ -XXX,XX +XXX,XX @@ void qtest_bufwrite(QTestState *s, uint64_t addr, const void *data, size_t size)
44
45
bdata = g_base64_encode(data, size);
46
qtest_sendf(s, "b64write 0x%" PRIx64 " 0x%zx ", addr, size);
47
- socket_send(s->fd, bdata, strlen(bdata));
48
- socket_send(s->fd, "\n", 1);
49
+ s->ops.send(s, bdata);
50
+ s->ops.send(s, "\n");
51
qtest_rsp(s, 0);
52
g_free(bdata);
53
}
54
@@ -XXX,XX +XXX,XX @@ static void qtest_client_set_rx_handler(QTestState *s, QTestRecvFn recv)
55
{
56
s->ops.recv_line = recv;
57
}
58
+/* A type-safe wrapper for s->send() */
59
+static void send_wrapper(QTestState *s, const char *buf)
60
+{
61
+ s->ops.external_send(s, buf);
62
+}
63
+
64
+static GString *qtest_client_inproc_recv_line(QTestState *s)
65
+{
66
+ GString *line;
67
+ size_t offset;
68
+ char *eol;
69
+
70
+ eol = strchr(s->rx->str, '\n');
71
+ offset = eol - s->rx->str;
72
+ line = g_string_new_len(s->rx->str, offset);
73
+ g_string_erase(s->rx, 0, offset + 1);
74
+ return line;
75
+}
76
+
77
+QTestState *qtest_inproc_init(QTestState **s, bool log, const char* arch,
78
+ void (*send)(void*, const char*))
79
+{
80
+ QTestState *qts;
81
+ qts = g_new0(QTestState, 1);
82
+ *s = qts; /* Expose qts early on, since the query endianness relies on it */
83
+ qts->wstatus = 0;
84
+ for (int i = 0; i < MAX_IRQ; i++) {
85
+ qts->irq_level[i] = false;
86
+ }
87
+
88
+ qtest_client_set_rx_handler(qts, qtest_client_inproc_recv_line);
89
+
90
+ /* send() may not have a matching protoype, so use a type-safe wrapper */
91
+ qts->ops.external_send = send;
92
+ qtest_client_set_tx_handler(qts, send_wrapper);
93
+
94
+ qts->big_endian = qtest_query_target_endianness(qts);
95
+
96
+ /*
97
+ * Set a dummy path for QTEST_QEMU_BINARY. Doesn't need to exist, but this
98
+ * way, qtest_get_arch works for inproc qtest.
99
+ */
100
+ gchar *bin_path = g_strconcat("/qemu-system-", arch, NULL);
101
+ setenv("QTEST_QEMU_BINARY", bin_path, 0);
102
+ g_free(bin_path);
103
+
104
+ return qts;
105
+}
106
+
107
+void qtest_client_inproc_recv(void *opaque, const char *str)
108
+{
109
+ QTestState *qts = *(QTestState **)opaque;
110
+
111
+ if (!qts->rx) {
112
+ qts->rx = g_string_new(NULL);
113
+ }
114
+ g_string_append(qts->rx, str);
115
+ return;
116
+}
117
diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h
118
index XXXXXXX..XXXXXXX 100644
119
--- a/tests/qtest/libqtest.h
120
+++ b/tests/qtest/libqtest.h
121
@@ -XXX,XX +XXX,XX @@ bool qtest_probe_child(QTestState *s);
122
*/
123
void qtest_set_expected_status(QTestState *s, int status);
124
125
+QTestState *qtest_inproc_init(QTestState **s, bool log, const char* arch,
126
+ void (*send)(void*, const char*));
127
+
128
+void qtest_client_inproc_recv(void *opaque, const char *str);
129
#endif
39
--
130
--
40
2.24.1
131
2.24.1
41
132
42
diff view generated by jsdifflib
1
Just rm will not delete external data files. Use _rm_test_img every
1
From: Alexander Bulekov <alxndr@bu.edu>
2
time we delete a test image.
3
2
4
(In the process, clean up the indentation of every _cleanup() this patch
3
The handler allows a qtest client to send commands to the server by
5
touches.)
4
directly calling a function, rather than using a file/CharBackend
6
5
7
((Also, use quotes consistently. I am happy to see unquoted instances
6
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
8
like "rm -rf $TEST_DIR/..." go.))
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
9
Message-id: 20200220041118.23264-9-alxndr@bu.edu
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
include/sysemu/qtest.h | 1 +
13
qtest.c | 13 +++++++++++++
14
2 files changed, 14 insertions(+)
9
15
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h
11
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
17
index XXXXXXX..XXXXXXX 100644
12
Message-id: 20191107163708.833192-16-mreitz@redhat.com
18
--- a/include/sysemu/qtest.h
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
+++ b/include/sysemu/qtest.h
14
---
20
@@ -XXX,XX +XXX,XX @@ void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **
15
tests/qemu-iotests/019 | 6 +++---
21
16
tests/qemu-iotests/020 | 6 +++---
22
void qtest_server_set_send_handler(void (*send)(void *, const char *),
17
tests/qemu-iotests/024 | 10 +++++-----
23
void *opaque);
18
tests/qemu-iotests/028 | 2 +-
24
+void qtest_server_inproc_recv(void *opaque, const char *buf);
19
tests/qemu-iotests/029 | 2 +-
25
20
tests/qemu-iotests/043 | 4 +++-
26
#endif
21
tests/qemu-iotests/048 | 2 +-
27
diff --git a/qtest.c b/qtest.c
22
tests/qemu-iotests/050 | 4 ++--
28
index XXXXXXX..XXXXXXX 100644
23
tests/qemu-iotests/053 | 4 ++--
29
--- a/qtest.c
24
tests/qemu-iotests/058 | 2 +-
30
+++ b/qtest.c
25
tests/qemu-iotests/059 | 2 +-
31
@@ -XXX,XX +XXX,XX @@ bool qtest_driver(void)
26
tests/qemu-iotests/061 | 2 +-
27
tests/qemu-iotests/063 | 6 ++++--
28
tests/qemu-iotests/069 | 2 +-
29
tests/qemu-iotests/074 | 2 +-
30
tests/qemu-iotests/080 | 2 +-
31
tests/qemu-iotests/081 | 6 +++---
32
tests/qemu-iotests/085 | 9 ++++++---
33
tests/qemu-iotests/088 | 2 +-
34
tests/qemu-iotests/092 | 2 +-
35
tests/qemu-iotests/094 | 2 +-
36
tests/qemu-iotests/095 | 5 +++--
37
tests/qemu-iotests/099 | 7 ++++---
38
tests/qemu-iotests/109 | 4 ++--
39
tests/qemu-iotests/110 | 4 ++--
40
tests/qemu-iotests/122 | 6 ++++--
41
tests/qemu-iotests/123 | 2 +-
42
tests/qemu-iotests/141 | 4 +++-
43
tests/qemu-iotests/142 | 2 +-
44
tests/qemu-iotests/144 | 4 +++-
45
tests/qemu-iotests/153 | 10 +++-------
46
tests/qemu-iotests/156 | 8 ++++++--
47
tests/qemu-iotests/159 | 2 +-
48
tests/qemu-iotests/160 | 3 ++-
49
tests/qemu-iotests/161 | 4 ++--
50
tests/qemu-iotests/170 | 2 +-
51
tests/qemu-iotests/172 | 6 +++---
52
tests/qemu-iotests/173 | 3 ++-
53
tests/qemu-iotests/178 | 2 +-
54
tests/qemu-iotests/182 | 2 +-
55
tests/qemu-iotests/183 | 2 +-
56
tests/qemu-iotests/185 | 4 ++--
57
tests/qemu-iotests/187 | 6 +++---
58
tests/qemu-iotests/190 | 2 +-
59
tests/qemu-iotests/191 | 6 +++---
60
tests/qemu-iotests/195 | 2 +-
61
tests/qemu-iotests/197 | 2 +-
62
tests/qemu-iotests/200 | 3 ++-
63
tests/qemu-iotests/215 | 2 +-
64
tests/qemu-iotests/225 | 2 +-
65
tests/qemu-iotests/229 | 3 ++-
66
tests/qemu-iotests/232 | 4 +++-
67
tests/qemu-iotests/243 | 2 +-
68
tests/qemu-iotests/244 | 4 ++--
69
tests/qemu-iotests/247 | 4 +++-
70
tests/qemu-iotests/249 | 4 ++--
71
tests/qemu-iotests/252 | 2 +-
72
57 files changed, 118 insertions(+), 95 deletions(-)
73
74
diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019
75
index XXXXXXX..XXXXXXX 100755
76
--- a/tests/qemu-iotests/019
77
+++ b/tests/qemu-iotests/019
78
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
79
80
_cleanup()
81
{
32
{
82
-    _cleanup_test_img
33
return qtest_chr.chr != NULL;
83
- rm -f "$TEST_IMG.base"
84
- rm -f "$TEST_IMG.orig"
85
+ _cleanup_test_img
86
+ _rm_test_img "$TEST_IMG.base"
87
+ _rm_test_img "$TEST_IMG.orig"
88
}
34
}
89
trap "_cleanup; exit \$status" 0 1 2 3 15
90
91
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
92
index XXXXXXX..XXXXXXX 100755
93
--- a/tests/qemu-iotests/020
94
+++ b/tests/qemu-iotests/020
95
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
96
97
_cleanup()
98
{
99
-    _cleanup_test_img
100
- rm -f "$TEST_IMG.base"
101
- rm -f "$TEST_IMG.orig"
102
+ _cleanup_test_img
103
+ _rm_test_img "$TEST_IMG.base"
104
+ _rm_test_img "$TEST_IMG.orig"
105
}
106
trap "_cleanup; exit \$status" 0 1 2 3 15
107
108
diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024
109
index XXXXXXX..XXXXXXX 100755
110
--- a/tests/qemu-iotests/024
111
+++ b/tests/qemu-iotests/024
112
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
113
_cleanup()
114
{
115
_cleanup_test_img
116
- rm -f "$TEST_DIR/t.$IMGFMT.base_old"
117
- rm -f "$TEST_DIR/t.$IMGFMT.base_new"
118
+ _rm_test_img "$TEST_DIR/t.$IMGFMT.base_old"
119
+ _rm_test_img "$TEST_DIR/t.$IMGFMT.base_new"
120
121
- rm -f "$TEST_DIR/subdir/t.$IMGFMT"
122
- rm -f "$TEST_DIR/subdir/t.$IMGFMT.base_old"
123
- rm -f "$TEST_DIR/subdir/t.$IMGFMT.base_new"
124
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT"
125
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base_old"
126
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base_new"
127
rmdir "$TEST_DIR/subdir" 2> /dev/null
128
}
129
trap "_cleanup; exit \$status" 0 1 2 3 15
130
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
131
index XXXXXXX..XXXXXXX 100755
132
--- a/tests/qemu-iotests/028
133
+++ b/tests/qemu-iotests/028
134
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
135
_cleanup()
136
{
137
_cleanup_qemu
138
- rm -f "${TEST_IMG}.copy"
139
+ _rm_test_img "${TEST_IMG}.copy"
140
_cleanup_test_img
141
}
142
trap "_cleanup; exit \$status" 0 1 2 3 15
143
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
144
index XXXXXXX..XXXXXXX 100755
145
--- a/tests/qemu-iotests/029
146
+++ b/tests/qemu-iotests/029
147
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
148
149
_cleanup()
150
{
151
- rm -f $TEST_IMG.snap
152
+ _rm_test_img "$TEST_IMG.snap"
153
_cleanup_test_img
154
}
155
trap "_cleanup; exit \$status" 0 1 2 3 15
156
diff --git a/tests/qemu-iotests/043 b/tests/qemu-iotests/043
157
index XXXXXXX..XXXXXXX 100755
158
--- a/tests/qemu-iotests/043
159
+++ b/tests/qemu-iotests/043
160
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
161
_cleanup()
162
{
163
_cleanup_test_img
164
- rm -f "$TEST_IMG".[123].base
165
+ for img in "$TEST_IMG".[123].base; do
166
+ _rm_test_img "$img"
167
+ done
168
}
169
trap "_cleanup; exit \$status" 0 1 2 3 15
170
171
diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048
172
index XXXXXXX..XXXXXXX 100755
173
--- a/tests/qemu-iotests/048
174
+++ b/tests/qemu-iotests/048
175
@@ -XXX,XX +XXX,XX @@ _cleanup()
176
{
177
echo "Cleanup"
178
_cleanup_test_img
179
- rm "${TEST_IMG_FILE2}"
180
+ _rm_test_img "${TEST_IMG_FILE2}"
181
}
182
trap "_cleanup; exit \$status" 0 1 2 3 15
183
184
diff --git a/tests/qemu-iotests/050 b/tests/qemu-iotests/050
185
index XXXXXXX..XXXXXXX 100755
186
--- a/tests/qemu-iotests/050
187
+++ b/tests/qemu-iotests/050
188
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
189
_cleanup()
190
{
191
_cleanup_test_img
192
- rm -f "$TEST_IMG.old"
193
- rm -f "$TEST_IMG.new"
194
+ _rm_test_img "$TEST_IMG.old"
195
+ _rm_test_img "$TEST_IMG.new"
196
}
197
trap "_cleanup; exit \$status" 0 1 2 3 15
198
199
diff --git a/tests/qemu-iotests/053 b/tests/qemu-iotests/053
200
index XXXXXXX..XXXXXXX 100755
201
--- a/tests/qemu-iotests/053
202
+++ b/tests/qemu-iotests/053
203
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
204
205
_cleanup()
206
{
207
-    rm -f "$TEST_IMG.orig"
208
-    _cleanup_test_img
209
+ _rm_test_img "$TEST_IMG.orig"
210
+ _cleanup_test_img
211
}
212
trap "_cleanup; exit \$status" 0 1 2 3 15
213
214
diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058
215
index XXXXXXX..XXXXXXX 100755
216
--- a/tests/qemu-iotests/058
217
+++ b/tests/qemu-iotests/058
218
@@ -XXX,XX +XXX,XX @@ _cleanup()
219
{
220
nbd_server_stop
221
_cleanup_test_img
222
- rm -f "$converted_image"
223
+ _rm_test_img "$converted_image"
224
}
225
trap "_cleanup; exit \$status" 0 1 2 3 15
226
227
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
228
index XXXXXXX..XXXXXXX 100755
229
--- a/tests/qemu-iotests/059
230
+++ b/tests/qemu-iotests/059
231
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
232
_cleanup()
233
{
234
_cleanup_test_img
235
- rm -f "$TEST_IMG.qcow2"
236
+ IMGFMT=qcow2 _rm_test_img "$TEST_IMG.qcow2"
237
}
238
trap "_cleanup; exit \$status" 0 1 2 3 15
239
240
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
241
index XXXXXXX..XXXXXXX 100755
242
--- a/tests/qemu-iotests/061
243
+++ b/tests/qemu-iotests/061
244
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
245
_cleanup()
246
{
247
_cleanup_test_img
248
- rm -f $TEST_IMG.data
249
+ _rm_test_img "$TEST_IMG.data"
250
}
251
trap "_cleanup; exit \$status" 0 1 2 3 15
252
253
diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063
254
index XXXXXXX..XXXXXXX 100755
255
--- a/tests/qemu-iotests/063
256
+++ b/tests/qemu-iotests/063
257
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
258
259
_cleanup()
260
{
261
-    _cleanup_test_img
262
-    rm -f "$TEST_IMG.orig" "$TEST_IMG.raw1" "$TEST_IMG.raw2"
263
+ _cleanup_test_img
264
+ for img in "$TEST_IMG".{orig,raw1,raw2,target}; do
265
+ _rm_test_img "$img"
266
+ done
267
}
268
trap "_cleanup; exit \$status" 0 1 2 3 15
269
270
diff --git a/tests/qemu-iotests/069 b/tests/qemu-iotests/069
271
index XXXXXXX..XXXXXXX 100755
272
--- a/tests/qemu-iotests/069
273
+++ b/tests/qemu-iotests/069
274
@@ -XXX,XX +XXX,XX @@ echo "=== Creating an image with a backing file and deleting that file ==="
275
echo
276
TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE
277
_make_test_img -b "$TEST_IMG.base" $IMG_SIZE
278
-rm -f "$TEST_IMG.base"
279
+_rm_test_img "$TEST_IMG.base"
280
# Just open the image and close it right again (this should print an error message)
281
$QEMU_IO -c quit "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
282
283
diff --git a/tests/qemu-iotests/074 b/tests/qemu-iotests/074
284
index XXXXXXX..XXXXXXX 100755
285
--- a/tests/qemu-iotests/074
286
+++ b/tests/qemu-iotests/074
287
@@ -XXX,XX +XXX,XX @@ _cleanup()
288
{
289
echo "Cleanup"
290
_cleanup_test_img
291
- rm "${TEST_IMG2}"
292
+ _rm_test_img "${TEST_IMG2}"
293
rm -f "$TEST_DIR/blkdebug.conf"
294
}
295
trap "_cleanup; exit \$status" 0 1 2 3 15
296
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
297
index XXXXXXX..XXXXXXX 100755
298
--- a/tests/qemu-iotests/080
299
+++ b/tests/qemu-iotests/080
300
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
301
302
_cleanup()
303
{
304
- rm -f $TEST_IMG.snap
305
+ _rm_test_img "$TEST_IMG.snap"
306
_cleanup_test_img
307
}
308
trap "_cleanup; exit \$status" 0 1 2 3 15
309
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
310
index XXXXXXX..XXXXXXX 100755
311
--- a/tests/qemu-iotests/081
312
+++ b/tests/qemu-iotests/081
313
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
314
315
_cleanup()
316
{
317
- rm -rf $TEST_DIR/1.raw
318
- rm -rf $TEST_DIR/2.raw
319
- rm -rf $TEST_DIR/3.raw
320
+ _rm_test_img "$TEST_DIR/1.raw"
321
+ _rm_test_img "$TEST_DIR/2.raw"
322
+ _rm_test_img "$TEST_DIR/3.raw"
323
}
324
trap "_cleanup; exit \$status" 0 1 2 3 15
325
326
diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085
327
index XXXXXXX..XXXXXXX 100755
328
--- a/tests/qemu-iotests/085
329
+++ b/tests/qemu-iotests/085
330
@@ -XXX,XX +XXX,XX @@ _cleanup()
331
_cleanup_qemu
332
for i in $(seq 1 ${SNAPSHOTS})
333
do
334
- rm -f "${TEST_DIR}/${i}-${snapshot_virt0}"
335
- rm -f "${TEST_DIR}/${i}-${snapshot_virt1}"
336
+ _rm_test_img "${TEST_DIR}/${i}-${snapshot_virt0}"
337
+ _rm_test_img "${TEST_DIR}/${i}-${snapshot_virt1}"
338
+ done
339
+ for img in "${TEST_IMG}".{1,2,base}
340
+ do
341
+ _rm_test_img "$img"
342
done
343
- rm -f "${TEST_IMG}" "${TEST_IMG}.1" "${TEST_IMG}.2" "${TEST_IMG}.base"
344
345
}
346
trap "_cleanup; exit \$status" 0 1 2 3 15
347
diff --git a/tests/qemu-iotests/088 b/tests/qemu-iotests/088
348
index XXXXXXX..XXXXXXX 100755
349
--- a/tests/qemu-iotests/088
350
+++ b/tests/qemu-iotests/088
351
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
352
353
_cleanup()
354
{
355
- rm -f $TEST_IMG.snap
356
+ _rm_test_img "$TEST_IMG.snap"
357
_cleanup_test_img
358
}
359
trap "_cleanup; exit \$status" 0 1 2 3 15
360
diff --git a/tests/qemu-iotests/092 b/tests/qemu-iotests/092
361
index XXXXXXX..XXXXXXX 100755
362
--- a/tests/qemu-iotests/092
363
+++ b/tests/qemu-iotests/092
364
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
365
366
_cleanup()
367
{
368
- rm -f $TEST_IMG.snap
369
+ _rm_test_img "$TEST_IMG.snap"
370
_cleanup_test_img
371
}
372
trap "_cleanup; exit \$status" 0 1 2 3 15
373
diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094
374
index XXXXXXX..XXXXXXX 100755
375
--- a/tests/qemu-iotests/094
376
+++ b/tests/qemu-iotests/094
377
@@ -XXX,XX +XXX,XX @@ _cleanup()
378
{
379
_cleanup_qemu
380
_cleanup_test_img
381
- rm -f "$TEST_DIR/source.$IMGFMT"
382
+ _rm_test_img "$TEST_DIR/source.$IMGFMT"
383
}
384
385
trap "_cleanup; exit \$status" 0 1 2 3 15
386
diff --git a/tests/qemu-iotests/095 b/tests/qemu-iotests/095
387
index XXXXXXX..XXXXXXX 100755
388
--- a/tests/qemu-iotests/095
389
+++ b/tests/qemu-iotests/095
390
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
391
_cleanup()
392
{
393
_cleanup_qemu
394
- rm -f "${TEST_IMG}.base" "${TEST_IMG}.snp1"
395
-    _cleanup_test_img
396
+ _rm_test_img "${TEST_IMG}.base"
397
+ _rm_test_img "${TEST_IMG}.snp1"
398
+ _cleanup_test_img
399
}
400
trap "_cleanup; exit \$status" 0 1 2 3 15
401
402
diff --git a/tests/qemu-iotests/099 b/tests/qemu-iotests/099
403
index XXXXXXX..XXXXXXX 100755
404
--- a/tests/qemu-iotests/099
405
+++ b/tests/qemu-iotests/099
406
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
407
408
_cleanup()
409
{
410
-    _cleanup_test_img
411
+ _cleanup_test_img
412
+ _rm_test_img "$TEST_IMG.compare"
413
+ rm -f "$TEST_DIR/blkdebug.conf"
414
+
35
+
415
}
36
+void qtest_server_inproc_recv(void *dummy, const char *buf)
416
trap "_cleanup; exit \$status" 0 1 2 3 15
37
+{
417
38
+ static GString *gstr;
418
@@ -XXX,XX +XXX,XX @@ echo
39
+ if (!gstr) {
419
test_qemu "file.driver=blkdebug,file.image.filename=$TEST_IMG"
40
+ gstr = g_string_new(NULL);
420
41
+ }
421
42
+ g_string_append(gstr, buf);
422
-rm -f "$TEST_IMG.compare" "$TEST_DIR/blkdebug.conf"
43
+ if (gstr->str[gstr->len - 1] == '\n') {
423
-
44
+ qtest_process_inbuf(NULL, gstr);
424
# success, all done
45
+ g_string_truncate(gstr, 0);
425
echo "*** done"
46
+ }
426
rm -f $seq.full
47
+}
427
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
428
index XXXXXXX..XXXXXXX 100755
429
--- a/tests/qemu-iotests/109
430
+++ b/tests/qemu-iotests/109
431
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
432
_cleanup()
433
{
434
_cleanup_qemu
435
- rm -f $TEST_IMG.src
436
-    _cleanup_test_img
437
+ _rm_test_img "$TEST_IMG.src"
438
+ _cleanup_test_img
439
}
440
trap "_cleanup; exit \$status" 0 1 2 3 15
441
442
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
443
index XXXXXXX..XXXXXXX 100755
444
--- a/tests/qemu-iotests/110
445
+++ b/tests/qemu-iotests/110
446
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
447
448
_cleanup()
449
{
450
-    _cleanup_test_img
451
- rm -f "$TEST_IMG.copy"
452
+ _cleanup_test_img
453
+ _rm_test_img "$TEST_IMG.copy"
454
}
455
trap "_cleanup; exit \$status" 0 1 2 3 15
456
457
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
458
index XXXXXXX..XXXXXXX 100755
459
--- a/tests/qemu-iotests/122
460
+++ b/tests/qemu-iotests/122
461
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
462
463
_cleanup()
464
{
465
- rm -f "$TEST_IMG".[123]
466
-    _cleanup_test_img
467
+ for img in "$TEST_IMG".[123]; do
468
+ _rm_test_img "$img"
469
+ done
470
+ _cleanup_test_img
471
}
472
trap "_cleanup; exit \$status" 0 1 2 3 15
473
474
diff --git a/tests/qemu-iotests/123 b/tests/qemu-iotests/123
475
index XXXXXXX..XXXXXXX 100755
476
--- a/tests/qemu-iotests/123
477
+++ b/tests/qemu-iotests/123
478
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
479
_cleanup()
480
{
481
_cleanup_test_img
482
- rm -f "$SRC_IMG"
483
+ _rm_test_img "$SRC_IMG"
484
}
485
trap "_cleanup; exit \$status" 0 1 2 3 15
486
487
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
488
index XXXXXXX..XXXXXXX 100755
489
--- a/tests/qemu-iotests/141
490
+++ b/tests/qemu-iotests/141
491
@@ -XXX,XX +XXX,XX @@ _cleanup()
492
{
493
_cleanup_qemu
494
_cleanup_test_img
495
- rm -f "$TEST_DIR"/{b,m,o}.$IMGFMT
496
+ for img in "$TEST_DIR"/{b,m,o}.$IMGFMT; do
497
+ _rm_test_img "$img"
498
+ done
499
}
500
trap "_cleanup; exit \$status" 0 1 2 3 15
501
502
diff --git a/tests/qemu-iotests/142 b/tests/qemu-iotests/142
503
index XXXXXXX..XXXXXXX 100755
504
--- a/tests/qemu-iotests/142
505
+++ b/tests/qemu-iotests/142
506
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
507
_cleanup()
508
{
509
_cleanup_test_img
510
- rm -f $TEST_IMG.snap
511
+ _rm_test_img "$TEST_IMG.snap"
512
}
513
trap "_cleanup; exit \$status" 0 1 2 3 15
514
515
diff --git a/tests/qemu-iotests/144 b/tests/qemu-iotests/144
516
index XXXXXXX..XXXXXXX 100755
517
--- a/tests/qemu-iotests/144
518
+++ b/tests/qemu-iotests/144
519
@@ -XXX,XX +XXX,XX @@ TMP_SNAP2=${TEST_DIR}/tmp2.qcow2
520
_cleanup()
521
{
522
_cleanup_qemu
523
- rm -f "${TEST_IMG}" "${TMP_SNAP1}" "${TMP_SNAP2}"
524
+ for img in "${TEST_IMG}" "${TMP_SNAP1}" "${TMP_SNAP2}"; do
525
+ _rm_test_img "$img"
526
+ done
527
}
528
529
trap "_cleanup; exit \$status" 0 1 2 3 15
530
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
531
index XXXXXXX..XXXXXXX 100755
532
--- a/tests/qemu-iotests/153
533
+++ b/tests/qemu-iotests/153
534
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
535
_cleanup()
536
{
537
_cleanup_test_img
538
- rm -f "${TEST_IMG}.base"
539
- rm -f "${TEST_IMG}.overlay"
540
- rm -f "${TEST_IMG}.convert"
541
- rm -f "${TEST_IMG}.a"
542
- rm -f "${TEST_IMG}.b"
543
- rm -f "${TEST_IMG}.c"
544
- rm -f "${TEST_IMG}.lnk"
545
+ for img in "${TEST_IMG}".{base,overlay,convert,a,b,c,lnk}; do
546
+ _rm_test_img "$img"
547
+ done
548
}
549
trap "_cleanup; exit \$status" 0 1 2 3 15
550
551
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
552
index XXXXXXX..XXXXXXX 100755
553
--- a/tests/qemu-iotests/156
554
+++ b/tests/qemu-iotests/156
555
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
556
_cleanup()
557
{
558
_cleanup_qemu
559
- rm -f "$TEST_IMG"{,.target}{,.backing,.overlay}
560
+ for img in "$TEST_IMG"{,.target}{,.backing,.overlay}; do
561
+ _rm_test_img "$img"
562
+ done
563
}
564
trap "_cleanup; exit \$status" 0 1 2 3 15
565
566
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE \
567
'"status": "null"'
568
569
# Remove the source images
570
-rm -f "$TEST_IMG{,.backing,.overlay}"
571
+for img in "$TEST_IMG{,.backing,.overlay}"; do
572
+ _rm_test_img "$img"
573
+done
574
575
echo
576
577
diff --git a/tests/qemu-iotests/159 b/tests/qemu-iotests/159
578
index XXXXXXX..XXXXXXX 100755
579
--- a/tests/qemu-iotests/159
580
+++ b/tests/qemu-iotests/159
581
@@ -XXX,XX +XXX,XX @@ status=1
582
_cleanup()
583
{
584
_cleanup_test_img
585
- rm -f "$TEST_IMG.out"
586
+ _rm_test_img "$TEST_IMG.out"
587
}
588
trap "_cleanup; exit \$status" 0 1 2 3 15
589
590
diff --git a/tests/qemu-iotests/160 b/tests/qemu-iotests/160
591
index XXXXXXX..XXXXXXX 100755
592
--- a/tests/qemu-iotests/160
593
+++ b/tests/qemu-iotests/160
594
@@ -XXX,XX +XXX,XX @@ status=1
595
_cleanup()
596
{
597
_cleanup_test_img
598
- rm -f "$TEST_IMG.out" "$TEST_IMG.out.dd"
599
+ _rm_test_img "$TEST_IMG.out"
600
+ _rm_test_img "$TEST_IMG.out.dd"
601
}
602
trap "_cleanup; exit \$status" 0 1 2 3 15
603
604
diff --git a/tests/qemu-iotests/161 b/tests/qemu-iotests/161
605
index XXXXXXX..XXXXXXX 100755
606
--- a/tests/qemu-iotests/161
607
+++ b/tests/qemu-iotests/161
608
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
609
_cleanup()
610
{
611
_cleanup_test_img
612
- rm -f "$TEST_IMG.base"
613
- rm -f "$TEST_IMG.int"
614
+ _rm_test_img "$TEST_IMG.base"
615
+ _rm_test_img "$TEST_IMG.int"
616
}
617
trap "_cleanup; exit \$status" 0 1 2 3 15
618
619
diff --git a/tests/qemu-iotests/170 b/tests/qemu-iotests/170
620
index XXXXXXX..XXXXXXX 100755
621
--- a/tests/qemu-iotests/170
622
+++ b/tests/qemu-iotests/170
623
@@ -XXX,XX +XXX,XX @@ status=1
624
_cleanup()
625
{
626
_cleanup_test_img
627
- rm -f "$TEST_IMG.out"
628
+ _rm_test_img "$TEST_IMG.out"
629
}
630
trap "_cleanup; exit \$status" 0 1 2 3 15
631
632
diff --git a/tests/qemu-iotests/172 b/tests/qemu-iotests/172
633
index XXXXXXX..XXXXXXX 100755
634
--- a/tests/qemu-iotests/172
635
+++ b/tests/qemu-iotests/172
636
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
637
638
_cleanup()
639
{
640
-    _cleanup_test_img
641
- rm -f "$TEST_IMG.2"
642
- rm -f "$TEST_IMG.3"
643
+ _cleanup_test_img
644
+ _rm_test_img "$TEST_IMG.2"
645
+ _rm_test_img "$TEST_IMG.3"
646
}
647
trap "_cleanup; exit \$status" 0 1 2 3 15
648
649
diff --git a/tests/qemu-iotests/173 b/tests/qemu-iotests/173
650
index XXXXXXX..XXXXXXX 100755
651
--- a/tests/qemu-iotests/173
652
+++ b/tests/qemu-iotests/173
653
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
654
_cleanup()
655
{
656
_cleanup_qemu
657
- rm -f "${QEMU_TEST_DIR}/image.base" "${QEMU_TEST_DIR}/image.snp1"
658
+ _rm_test_img "${TEST_DIR}/image.base"
659
+ _rm_test_img "${TEST_DIR}/image.snp1"
660
_cleanup_test_img
661
}
662
trap "_cleanup; exit \$status" 0 1 2 3 15
663
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
664
index XXXXXXX..XXXXXXX 100755
665
--- a/tests/qemu-iotests/178
666
+++ b/tests/qemu-iotests/178
667
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
668
_cleanup()
669
{
670
_cleanup_test_img
671
- rm -f "$TEST_IMG.converted"
672
+ _rm_test_img "$TEST_IMG.converted"
673
}
674
trap "_cleanup; exit \$status" 0 1 2 3 15
675
676
diff --git a/tests/qemu-iotests/182 b/tests/qemu-iotests/182
677
index XXXXXXX..XXXXXXX 100755
678
--- a/tests/qemu-iotests/182
679
+++ b/tests/qemu-iotests/182
680
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
681
_cleanup()
682
{
683
_cleanup_test_img
684
- rm -f "$TEST_IMG.overlay"
685
+ _rm_test_img "$TEST_IMG.overlay"
686
rm -f "$SOCK_DIR/nbd.socket"
687
}
688
trap "_cleanup; exit \$status" 0 1 2 3 15
689
diff --git a/tests/qemu-iotests/183 b/tests/qemu-iotests/183
690
index XXXXXXX..XXXXXXX 100755
691
--- a/tests/qemu-iotests/183
692
+++ b/tests/qemu-iotests/183
693
@@ -XXX,XX +XXX,XX @@ MIG_SOCKET="${SOCK_DIR}/migrate"
694
_cleanup()
695
{
696
rm -f "${MIG_SOCKET}"
697
- rm -f "${TEST_IMG}.dest"
698
+ _rm_test_img "${TEST_IMG}.dest"
699
_cleanup_test_img
700
_cleanup_qemu
701
}
702
diff --git a/tests/qemu-iotests/185 b/tests/qemu-iotests/185
703
index XXXXXXX..XXXXXXX 100755
704
--- a/tests/qemu-iotests/185
705
+++ b/tests/qemu-iotests/185
706
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
707
708
_cleanup()
709
{
710
- rm -f "${TEST_IMG}.mid"
711
- rm -f "${TEST_IMG}.copy"
712
+ _rm_test_img "${TEST_IMG}.mid"
713
+ _rm_test_img "${TEST_IMG}.copy"
714
_cleanup_test_img
715
_cleanup_qemu
716
}
717
diff --git a/tests/qemu-iotests/187 b/tests/qemu-iotests/187
718
index XXXXXXX..XXXXXXX 100755
719
--- a/tests/qemu-iotests/187
720
+++ b/tests/qemu-iotests/187
721
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
722
723
_cleanup()
724
{
725
-    _cleanup_test_img
726
- rm -f "$TEST_IMG.2"
727
- rm -f "$TEST_IMG.3"
728
+ _cleanup_test_img
729
+ _rm_test_img "$TEST_IMG.2"
730
+ _rm_test_img "$TEST_IMG.3"
731
}
732
trap "_cleanup; exit \$status" 0 1 2 3 15
733
734
diff --git a/tests/qemu-iotests/190 b/tests/qemu-iotests/190
735
index XXXXXXX..XXXXXXX 100755
736
--- a/tests/qemu-iotests/190
737
+++ b/tests/qemu-iotests/190
738
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
739
_cleanup()
740
{
741
_cleanup_test_img
742
- rm -f "$TEST_IMG.converted"
743
+ _rm_test_img "$TEST_IMG.converted"
744
}
745
trap "_cleanup; exit \$status" 0 1 2 3 15
746
747
diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191
748
index XXXXXXX..XXXXXXX 100755
749
--- a/tests/qemu-iotests/191
750
+++ b/tests/qemu-iotests/191
751
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
752
753
_cleanup()
754
{
755
- rm -f "${TEST_IMG}.mid"
756
- rm -f "${TEST_IMG}.ovl2"
757
- rm -f "${TEST_IMG}.ovl3"
758
+ _rm_test_img "${TEST_IMG}.mid"
759
+ _rm_test_img "${TEST_IMG}.ovl2"
760
+ _rm_test_img "${TEST_IMG}.ovl3"
761
_cleanup_test_img
762
_cleanup_qemu
763
}
764
diff --git a/tests/qemu-iotests/195 b/tests/qemu-iotests/195
765
index XXXXXXX..XXXXXXX 100755
766
--- a/tests/qemu-iotests/195
767
+++ b/tests/qemu-iotests/195
768
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
769
_cleanup()
770
{
771
_cleanup_test_img
772
- rm -f "$TEST_IMG.mid"
773
+ _rm_test_img "$TEST_IMG.mid"
774
}
775
trap "_cleanup; exit \$status" 0 1 2 3 15
776
777
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
778
index XXXXXXX..XXXXXXX 100755
779
--- a/tests/qemu-iotests/197
780
+++ b/tests/qemu-iotests/197
781
@@ -XXX,XX +XXX,XX @@ esac
782
_cleanup()
783
{
784
_cleanup_test_img
785
- rm -f "$TEST_WRAP"
786
+ _rm_test_img "$TEST_WRAP"
787
rm -f "$BLKDBG_CONF"
788
}
789
trap "_cleanup; exit \$status" 0 1 2 3 15
790
diff --git a/tests/qemu-iotests/200 b/tests/qemu-iotests/200
791
index XXXXXXX..XXXXXXX 100755
792
--- a/tests/qemu-iotests/200
793
+++ b/tests/qemu-iotests/200
794
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
795
_cleanup()
796
{
797
_cleanup_qemu
798
- rm -f "${TEST_IMG}" "${BACKING_IMG}"
799
+ _rm_test_img "${TEST_IMG}"
800
+ _rm_test_img "${BACKING_IMG}"
801
}
802
trap "_cleanup; exit \$status" 0 1 2 3 15
803
804
diff --git a/tests/qemu-iotests/215 b/tests/qemu-iotests/215
805
index XXXXXXX..XXXXXXX 100755
806
--- a/tests/qemu-iotests/215
807
+++ b/tests/qemu-iotests/215
808
@@ -XXX,XX +XXX,XX @@ esac
809
_cleanup()
810
{
811
_cleanup_test_img
812
- rm -f "$TEST_WRAP"
813
+ _rm_test_img "$TEST_WRAP"
814
rm -f "$BLKDBG_CONF"
815
}
816
trap "_cleanup; exit \$status" 0 1 2 3 15
817
diff --git a/tests/qemu-iotests/225 b/tests/qemu-iotests/225
818
index XXXXXXX..XXXXXXX 100755
819
--- a/tests/qemu-iotests/225
820
+++ b/tests/qemu-iotests/225
821
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
822
_cleanup()
823
{
824
_cleanup_test_img
825
- rm -f "$TEST_IMG.not_base"
826
+ _rm_test_img "$TEST_IMG.not_base"
827
}
828
trap "_cleanup; exit \$status" 0 1 2 3 15
829
830
diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229
831
index XXXXXXX..XXXXXXX 100755
832
--- a/tests/qemu-iotests/229
833
+++ b/tests/qemu-iotests/229
834
@@ -XXX,XX +XXX,XX @@ _cleanup()
835
{
836
_cleanup_qemu
837
_cleanup_test_img
838
- rm -f "$TEST_IMG" "$DEST_IMG"
839
+ _rm_test_img "$TEST_IMG"
840
+ _rm_test_img "$DEST_IMG"
841
}
842
trap "_cleanup; exit \$status" 0 1 2 3 15
843
844
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
845
index XXXXXXX..XXXXXXX 100755
846
--- a/tests/qemu-iotests/232
847
+++ b/tests/qemu-iotests/232
848
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
849
_cleanup()
850
{
851
_cleanup_test_img
852
- rm -f $TEST_IMG.[01234]
853
+ for img in "$TEST_IMG".[01234]; do
854
+ _rm_test_img "$img"
855
+ done
856
}
857
trap "_cleanup; exit \$status" 0 1 2 3 15
858
859
diff --git a/tests/qemu-iotests/243 b/tests/qemu-iotests/243
860
index XXXXXXX..XXXXXXX 100755
861
--- a/tests/qemu-iotests/243
862
+++ b/tests/qemu-iotests/243
863
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
864
_cleanup()
865
{
866
_cleanup_test_img
867
- rm -f $TEST_IMG.data
868
+ _rm_test_img "$TEST_IMG.data"
869
}
870
trap "_cleanup; exit \$status" 0 1 2 3 15
871
872
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
873
index XXXXXXX..XXXXXXX 100755
874
--- a/tests/qemu-iotests/244
875
+++ b/tests/qemu-iotests/244
876
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
877
_cleanup()
878
{
879
_cleanup_test_img
880
- rm -f $TEST_IMG.data
881
- rm -f $TEST_IMG.src
882
+ _rm_test_img "$TEST_IMG.data"
883
+ _rm_test_img "$TEST_IMG.src"
884
}
885
trap "_cleanup; exit \$status" 0 1 2 3 15
886
887
diff --git a/tests/qemu-iotests/247 b/tests/qemu-iotests/247
888
index XXXXXXX..XXXXXXX 100755
889
--- a/tests/qemu-iotests/247
890
+++ b/tests/qemu-iotests/247
891
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
892
_cleanup()
893
{
894
_cleanup_test_img
895
- rm -f $TEST_IMG.[01234]
896
+ for img in "$TEST_IMG".[01234]; do
897
+ _rm_test_img "$img"
898
+ done
899
}
900
trap "_cleanup; exit \$status" 0 1 2 3 15
901
902
diff --git a/tests/qemu-iotests/249 b/tests/qemu-iotests/249
903
index XXXXXXX..XXXXXXX 100755
904
--- a/tests/qemu-iotests/249
905
+++ b/tests/qemu-iotests/249
906
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
907
_cleanup()
908
{
909
_cleanup_test_img
910
- rm -f "$TEST_IMG.base"
911
- rm -f "$TEST_IMG.int"
912
+ _rm_test_img "$TEST_IMG.base"
913
+ _rm_test_img "$TEST_IMG.int"
914
}
915
trap "_cleanup; exit \$status" 0 1 2 3 15
916
917
diff --git a/tests/qemu-iotests/252 b/tests/qemu-iotests/252
918
index XXXXXXX..XXXXXXX 100755
919
--- a/tests/qemu-iotests/252
920
+++ b/tests/qemu-iotests/252
921
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
922
_cleanup()
923
{
924
_cleanup_test_img
925
- rm -f "$TEST_IMG.base_new"
926
+ _rm_test_img "$TEST_IMG.base_new"
927
}
928
trap "_cleanup; exit \$status" 0 1 2 3 15
929
930
--
48
--
931
2.24.1
49
2.24.1
932
50
933
diff view generated by jsdifflib
1
Use _make_test_img whenever possible. This way, we will not ignore
1
From: Alexander Bulekov <alxndr@bu.edu>
2
user-specified image options.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
The names i2c_send and i2c_recv collide with functions defined in
5
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
hw/i2c/core.c. This causes an error when linking against libqos and
6
Message-id: 20191107163708.833192-15-mreitz@redhat.com
5
softmmu simultaneously (for example when using qtest inproc). Rename the
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
libqos functions to avoid this.
7
8
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
11
Acked-by: Thomas Huth <thuth@redhat.com>
12
Message-id: 20200220041118.23264-10-alxndr@bu.edu
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
14
---
9
tests/qemu-iotests/094 | 2 +-
15
tests/qtest/libqos/i2c.c | 10 +++++-----
10
tests/qemu-iotests/111 | 3 +--
16
tests/qtest/libqos/i2c.h | 4 ++--
11
tests/qemu-iotests/123 | 2 +-
17
tests/qtest/pca9552-test.c | 10 +++++-----
12
tests/qemu-iotests/153 | 2 +-
18
3 files changed, 12 insertions(+), 12 deletions(-)
13
tests/qemu-iotests/200 | 4 ++--
14
5 files changed, 6 insertions(+), 7 deletions(-)
15
19
16
diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094
20
diff --git a/tests/qtest/libqos/i2c.c b/tests/qtest/libqos/i2c.c
17
index XXXXXXX..XXXXXXX 100755
21
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/094
22
--- a/tests/qtest/libqos/i2c.c
19
+++ b/tests/qemu-iotests/094
23
+++ b/tests/qtest/libqos/i2c.c
20
@@ -XXX,XX +XXX,XX @@ _supported_proto nbd
24
@@ -XXX,XX +XXX,XX @@
21
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
25
#include "libqos/i2c.h"
22
26
#include "libqtest.h"
23
_make_test_img 64M
27
24
-$QEMU_IMG create -f $IMGFMT "$TEST_DIR/source.$IMGFMT" 64M | _filter_img_create
28
-void i2c_send(QI2CDevice *i2cdev, const uint8_t *buf, uint16_t len)
25
+TEST_IMG_FILE="$TEST_DIR/source.$IMGFMT" IMGPROTO=file _make_test_img 64M
29
+void qi2c_send(QI2CDevice *i2cdev, const uint8_t *buf, uint16_t len)
26
30
{
27
_launch_qemu -drive if=none,id=src,file="$TEST_DIR/source.$IMGFMT",format=raw \
31
i2cdev->bus->send(i2cdev->bus, i2cdev->addr, buf, len);
28
-nodefaults
32
}
29
diff --git a/tests/qemu-iotests/111 b/tests/qemu-iotests/111
33
30
index XXXXXXX..XXXXXXX 100755
34
-void i2c_recv(QI2CDevice *i2cdev, uint8_t *buf, uint16_t len)
31
--- a/tests/qemu-iotests/111
35
+void qi2c_recv(QI2CDevice *i2cdev, uint8_t *buf, uint16_t len)
32
+++ b/tests/qemu-iotests/111
36
{
33
@@ -XXX,XX +XXX,XX @@ _supported_fmt qed qcow qcow2 vmdk
37
i2cdev->bus->recv(i2cdev->bus, i2cdev->addr, buf, len);
34
_supported_proto file
38
}
35
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
39
@@ -XXX,XX +XXX,XX @@ void i2c_recv(QI2CDevice *i2cdev, uint8_t *buf, uint16_t len)
36
40
void i2c_read_block(QI2CDevice *i2cdev, uint8_t reg,
37
-$QEMU_IMG create -f $IMGFMT -b "$TEST_IMG.inexistent" "$TEST_IMG" 2>&1 \
41
uint8_t *buf, uint16_t len)
38
- | _filter_testdir | _filter_imgfmt
42
{
39
+_make_test_img -b "$TEST_IMG.inexistent"
43
- i2c_send(i2cdev, &reg, 1);
40
44
- i2c_recv(i2cdev, buf, len);
41
# success, all done
45
+ qi2c_send(i2cdev, &reg, 1);
42
echo '*** done'
46
+ qi2c_recv(i2cdev, buf, len);
43
diff --git a/tests/qemu-iotests/123 b/tests/qemu-iotests/123
47
}
44
index XXXXXXX..XXXXXXX 100755
48
45
--- a/tests/qemu-iotests/123
49
void i2c_write_block(QI2CDevice *i2cdev, uint8_t reg,
46
+++ b/tests/qemu-iotests/123
50
@@ -XXX,XX +XXX,XX @@ void i2c_write_block(QI2CDevice *i2cdev, uint8_t reg,
47
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
51
uint8_t *cmd = g_malloc(len + 1);
48
SRC_IMG="$TEST_DIR/source.$IMGFMT"
52
cmd[0] = reg;
49
53
memcpy(&cmd[1], buf, len);
50
_make_test_img 1M
54
- i2c_send(i2cdev, cmd, len + 1);
51
-$QEMU_IMG create -f $IMGFMT "$SRC_IMG" 1M | _filter_img_create
55
+ qi2c_send(i2cdev, cmd, len + 1);
52
+TEST_IMG_FILE=$SRC_IMG IMGPROTO=file _make_test_img 1M
56
g_free(cmd);
53
57
}
54
$QEMU_IO -c 'write -P 42 0 1M' "$SRC_IMG" | _filter_qemu_io
58
55
59
diff --git a/tests/qtest/libqos/i2c.h b/tests/qtest/libqos/i2c.h
56
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
60
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100755
61
--- a/tests/qtest/libqos/i2c.h
58
--- a/tests/qemu-iotests/153
62
+++ b/tests/qtest/libqos/i2c.h
59
+++ b/tests/qemu-iotests/153
63
@@ -XXX,XX +XXX,XX @@ struct QI2CDevice {
60
@@ -XXX,XX +XXX,XX @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do
64
void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr);
61
65
void add_qi2c_address(QOSGraphEdgeOptions *opts, QI2CAddress *addr);
62
echo
66
63
echo "== Creating test image =="
67
-void i2c_send(QI2CDevice *dev, const uint8_t *buf, uint16_t len);
64
- $QEMU_IMG create -f $IMGFMT "${TEST_IMG}" -b ${TEST_IMG}.base | _filter_img_create
68
-void i2c_recv(QI2CDevice *dev, uint8_t *buf, uint16_t len);
65
+ _make_test_img -b "${TEST_IMG}.base"
69
+void qi2c_send(QI2CDevice *dev, const uint8_t *buf, uint16_t len);
66
70
+void qi2c_recv(QI2CDevice *dev, uint8_t *buf, uint16_t len);
67
echo
71
68
echo "== Launching QEMU, opts: '$opts1' =="
72
void i2c_read_block(QI2CDevice *dev, uint8_t reg,
69
diff --git a/tests/qemu-iotests/200 b/tests/qemu-iotests/200
73
uint8_t *buf, uint16_t len);
70
index XXXXXXX..XXXXXXX 100755
74
diff --git a/tests/qtest/pca9552-test.c b/tests/qtest/pca9552-test.c
71
--- a/tests/qemu-iotests/200
75
index XXXXXXX..XXXXXXX 100644
72
+++ b/tests/qemu-iotests/200
76
--- a/tests/qtest/pca9552-test.c
73
@@ -XXX,XX +XXX,XX @@ _supported_proto file
77
+++ b/tests/qtest/pca9552-test.c
74
BACKING_IMG="${TEST_DIR}/backing.img"
78
@@ -XXX,XX +XXX,XX @@ static void receive_autoinc(void *obj, void *data, QGuestAllocator *alloc)
75
TEST_IMG="${TEST_DIR}/test.img"
79
76
80
pca9552_init(i2cdev);
77
-${QEMU_IMG} create -f $IMGFMT "${BACKING_IMG}" 512M | _filter_img_create
81
78
-${QEMU_IMG} create -f $IMGFMT -F $IMGFMT "${TEST_IMG}" -b "${BACKING_IMG}" 512M | _filter_img_create
82
- i2c_send(i2cdev, &reg, 1);
79
+TEST_IMG="$BACKING_IMG" _make_test_img 512M
83
+ qi2c_send(i2cdev, &reg, 1);
80
+_make_test_img -F $IMGFMT -b "$BACKING_IMG" 512M
84
81
85
/* PCA9552_LS0 */
82
${QEMU_IO} -c "write -P 0xa5 512 300M" "${BACKING_IMG}" | _filter_qemu_io
86
- i2c_recv(i2cdev, &resp, 1);
87
+ qi2c_recv(i2cdev, &resp, 1);
88
g_assert_cmphex(resp, ==, 0x54);
89
90
/* PCA9552_LS1 */
91
- i2c_recv(i2cdev, &resp, 1);
92
+ qi2c_recv(i2cdev, &resp, 1);
93
g_assert_cmphex(resp, ==, 0x55);
94
95
/* PCA9552_LS2 */
96
- i2c_recv(i2cdev, &resp, 1);
97
+ qi2c_recv(i2cdev, &resp, 1);
98
g_assert_cmphex(resp, ==, 0x55);
99
100
/* PCA9552_LS3 */
101
- i2c_recv(i2cdev, &resp, 1);
102
+ qi2c_recv(i2cdev, &resp, 1);
103
g_assert_cmphex(resp, ==, 0x54);
104
}
83
105
84
--
106
--
85
2.24.1
107
2.24.1
86
108
87
diff view generated by jsdifflib
1
It did not matter before, but now that _make_test_img understands -o, we
1
From: Alexander Bulekov <alxndr@bu.edu>
2
should use it properly here.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Most qos-related objects were specified in the qos-test-obj-y variable.
5
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
qos-test-obj-y also included qos-test.o which defines a main().
6
Message-id: 20191107163708.833192-11-mreitz@redhat.com
5
This made it difficult to repurpose qos-test-obj-y to link anything
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
beside tests/qos-test against libqos. This change separates objects that
7
are libqos-specific and ones that are qos-test specific into different
8
variables.
9
10
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
11
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Message-id: 20200220041118.23264-11-alxndr@bu.edu
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
16
---
9
tests/qemu-iotests/051 | 2 +-
17
tests/qtest/Makefile.include | 71 ++++++++++++++++++------------------
10
1 file changed, 1 insertion(+), 1 deletion(-)
18
1 file changed, 36 insertions(+), 35 deletions(-)
11
19
12
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
20
diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include
13
index XXXXXXX..XXXXXXX 100755
21
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/qemu-iotests/051
22
--- a/tests/qtest/Makefile.include
15
+++ b/tests/qemu-iotests/051
23
+++ b/tests/qtest/Makefile.include
16
@@ -XXX,XX +XXX,XX @@ echo
24
@@ -XXX,XX +XXX,XX @@ check-qtest-s390x-y += migration-test
17
echo === With version 2 images enabling lazy refcounts must fail ===
25
# libqos / qgraph :
18
echo
26
libqgraph-obj-y = tests/qtest/libqos/qgraph.o
19
27
20
-_make_test_img -ocompat=0.10 $size
28
-libqos-obj-y = $(libqgraph-obj-y) tests/qtest/libqos/pci.o tests/qtest/libqos/fw_cfg.o
21
+_make_test_img -o compat=0.10 $size
29
-libqos-obj-y += tests/qtest/libqos/malloc.o
22
30
-libqos-obj-y += tests/qtest/libqos/libqos.o
23
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=on
31
-libqos-spapr-obj-y = $(libqos-obj-y) tests/qtest/libqos/malloc-spapr.o
24
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=off
32
+libqos-core-obj-y = $(libqgraph-obj-y) tests/qtest/libqos/pci.o tests/qtest/libqos/fw_cfg.o
33
+libqos-core-obj-y += tests/qtest/libqos/malloc.o
34
+libqos-core-obj-y += tests/qtest/libqos/libqos.o
35
+libqos-spapr-obj-y = $(libqos-core-obj-y) tests/qtest/libqos/malloc-spapr.o
36
libqos-spapr-obj-y += tests/qtest/libqos/libqos-spapr.o
37
libqos-spapr-obj-y += tests/qtest/libqos/rtas.o
38
libqos-spapr-obj-y += tests/qtest/libqos/pci-spapr.o
39
-libqos-pc-obj-y = $(libqos-obj-y) tests/qtest/libqos/pci-pc.o
40
+libqos-pc-obj-y = $(libqos-core-obj-y) tests/qtest/libqos/pci-pc.o
41
libqos-pc-obj-y += tests/qtest/libqos/malloc-pc.o tests/qtest/libqos/libqos-pc.o
42
libqos-pc-obj-y += tests/qtest/libqos/ahci.o
43
libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/qtest/libqos/usb.o
44
45
# qos devices:
46
-qos-test-obj-y = tests/qtest/qos-test.o $(libqgraph-obj-y)
47
-qos-test-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y)
48
-qos-test-obj-y += tests/qtest/libqos/e1000e.o
49
-qos-test-obj-y += tests/qtest/libqos/i2c.o
50
-qos-test-obj-y += tests/qtest/libqos/i2c-imx.o
51
-qos-test-obj-y += tests/qtest/libqos/i2c-omap.o
52
-qos-test-obj-y += tests/qtest/libqos/sdhci.o
53
-qos-test-obj-y += tests/qtest/libqos/tpci200.o
54
-qos-test-obj-y += tests/qtest/libqos/virtio.o
55
-qos-test-obj-$(CONFIG_VIRTFS) += tests/qtest/libqos/virtio-9p.o
56
-qos-test-obj-y += tests/qtest/libqos/virtio-balloon.o
57
-qos-test-obj-y += tests/qtest/libqos/virtio-blk.o
58
-qos-test-obj-y += tests/qtest/libqos/virtio-mmio.o
59
-qos-test-obj-y += tests/qtest/libqos/virtio-net.o
60
-qos-test-obj-y += tests/qtest/libqos/virtio-pci.o
61
-qos-test-obj-y += tests/qtest/libqos/virtio-pci-modern.o
62
-qos-test-obj-y += tests/qtest/libqos/virtio-rng.o
63
-qos-test-obj-y += tests/qtest/libqos/virtio-scsi.o
64
-qos-test-obj-y += tests/qtest/libqos/virtio-serial.o
65
+libqos-obj-y = $(libqgraph-obj-y)
66
+libqos-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y)
67
+libqos-obj-y += tests/qtest/libqos/e1000e.o
68
+libqos-obj-y += tests/qtest/libqos/i2c.o
69
+libqos-obj-y += tests/qtest/libqos/i2c-imx.o
70
+libqos-obj-y += tests/qtest/libqos/i2c-omap.o
71
+libqos-obj-y += tests/qtest/libqos/sdhci.o
72
+libqos-obj-y += tests/qtest/libqos/tpci200.o
73
+libqos-obj-y += tests/qtest/libqos/virtio.o
74
+libqos-obj-$(CONFIG_VIRTFS) += tests/qtest/libqos/virtio-9p.o
75
+libqos-obj-y += tests/qtest/libqos/virtio-balloon.o
76
+libqos-obj-y += tests/qtest/libqos/virtio-blk.o
77
+libqos-obj-y += tests/qtest/libqos/virtio-mmio.o
78
+libqos-obj-y += tests/qtest/libqos/virtio-net.o
79
+libqos-obj-y += tests/qtest/libqos/virtio-pci.o
80
+libqos-obj-y += tests/qtest/libqos/virtio-pci-modern.o
81
+libqos-obj-y += tests/qtest/libqos/virtio-rng.o
82
+libqos-obj-y += tests/qtest/libqos/virtio-scsi.o
83
+libqos-obj-y += tests/qtest/libqos/virtio-serial.o
84
85
# qos machines:
86
-qos-test-obj-y += tests/qtest/libqos/aarch64-xlnx-zcu102-machine.o
87
-qos-test-obj-y += tests/qtest/libqos/arm-imx25-pdk-machine.o
88
-qos-test-obj-y += tests/qtest/libqos/arm-n800-machine.o
89
-qos-test-obj-y += tests/qtest/libqos/arm-raspi2-machine.o
90
-qos-test-obj-y += tests/qtest/libqos/arm-sabrelite-machine.o
91
-qos-test-obj-y += tests/qtest/libqos/arm-smdkc210-machine.o
92
-qos-test-obj-y += tests/qtest/libqos/arm-virt-machine.o
93
-qos-test-obj-y += tests/qtest/libqos/arm-xilinx-zynq-a9-machine.o
94
-qos-test-obj-y += tests/qtest/libqos/ppc64_pseries-machine.o
95
-qos-test-obj-y += tests/qtest/libqos/x86_64_pc-machine.o
96
+libqos-obj-y += tests/qtest/libqos/aarch64-xlnx-zcu102-machine.o
97
+libqos-obj-y += tests/qtest/libqos/arm-imx25-pdk-machine.o
98
+libqos-obj-y += tests/qtest/libqos/arm-n800-machine.o
99
+libqos-obj-y += tests/qtest/libqos/arm-raspi2-machine.o
100
+libqos-obj-y += tests/qtest/libqos/arm-sabrelite-machine.o
101
+libqos-obj-y += tests/qtest/libqos/arm-smdkc210-machine.o
102
+libqos-obj-y += tests/qtest/libqos/arm-virt-machine.o
103
+libqos-obj-y += tests/qtest/libqos/arm-xilinx-zynq-a9-machine.o
104
+libqos-obj-y += tests/qtest/libqos/ppc64_pseries-machine.o
105
+libqos-obj-y += tests/qtest/libqos/x86_64_pc-machine.o
106
107
# qos tests:
108
+qos-test-obj-y += tests/qtest/qos-test.o
109
qos-test-obj-y += tests/qtest/ac97-test.o
110
qos-test-obj-y += tests/qtest/ds1338-test.o
111
qos-test-obj-y += tests/qtest/e1000-test.o
112
@@ -XXX,XX +XXX,XX @@ check-unit-y += tests/test-qgraph$(EXESUF)
113
tests/test-qgraph$(EXESUF): tests/test-qgraph.o $(libqgraph-obj-y)
114
115
check-qtest-generic-y += qos-test
116
-tests/qtest/qos-test$(EXESUF): $(qos-test-obj-y)
117
+tests/qtest/qos-test$(EXESUF): $(qos-test-obj-y) $(libqos-obj-y)
118
119
# QTest dependencies:
120
tests/qtest/qmp-test$(EXESUF): tests/qtest/qmp-test.o
25
--
121
--
26
2.24.1
122
2.24.1
27
123
28
diff view generated by jsdifflib
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
From: Alexander Bulekov <alxndr@bu.edu>
2
2
3
QEMU currently supports writing compressed data of the size equal to
3
The moved functions are not specific to qos-test and might be useful
4
one cluster. This patch allows writing QCOW2 compressed data that
4
elsewhere. For example the virtual-device fuzzer makes use of them for
5
exceed one cluster. Now, we split buffered data into separate clusters
5
qos-assisted fuzz-targets.
6
and write them compressed using the block/aio_task API.
7
6
8
Suggested-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
7
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
9
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 20200220041118.23264-12-alxndr@bu.edu
13
Message-id: 1575288906-551879-3-git-send-email-andrey.shinkevich@virtuozzo.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
13
---
16
block/qcow2.c | 102 +++++++++++++++++++++++++++++++++++++-------------
14
tests/qtest/Makefile.include | 1 +
17
1 file changed, 75 insertions(+), 27 deletions(-)
15
tests/qtest/libqos/qos_external.c | 168 ++++++++++++++++++++++++++++++
16
tests/qtest/libqos/qos_external.h | 28 +++++
17
tests/qtest/qos-test.c | 132 +----------------------
18
4 files changed, 198 insertions(+), 131 deletions(-)
19
create mode 100644 tests/qtest/libqos/qos_external.c
20
create mode 100644 tests/qtest/libqos/qos_external.h
18
21
19
diff --git a/block/qcow2.c b/block/qcow2.c
22
diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
24
--- a/tests/qtest/Makefile.include
22
+++ b/block/qcow2.c
25
+++ b/tests/qtest/Makefile.include
23
@@ -XXX,XX +XXX,XX @@ fail:
26
@@ -XXX,XX +XXX,XX @@ libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/qtest/libqos/u
24
return ret;
27
# qos devices:
25
}
28
libqos-obj-y = $(libqgraph-obj-y)
26
29
libqos-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y)
27
-/* XXX: put compressed sectors first, then all the cluster aligned
30
+libqos-obj-y += tests/qtest/libqos/qos_external.o
28
- tables to avoid losing bytes in alignment */
31
libqos-obj-y += tests/qtest/libqos/e1000e.o
29
static coroutine_fn int
32
libqos-obj-y += tests/qtest/libqos/i2c.o
30
-qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
33
libqos-obj-y += tests/qtest/libqos/i2c-imx.o
31
+qcow2_co_pwritev_compressed_task(BlockDriverState *bs,
34
diff --git a/tests/qtest/libqos/qos_external.c b/tests/qtest/libqos/qos_external.c
32
uint64_t offset, uint64_t bytes,
35
new file mode 100644
33
QEMUIOVector *qiov, size_t qiov_offset)
36
index XXXXXXX..XXXXXXX
34
{
37
--- /dev/null
35
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
38
+++ b/tests/qtest/libqos/qos_external.c
36
uint8_t *buf, *out_buf;
39
@@ -XXX,XX +XXX,XX @@
37
uint64_t cluster_offset;
40
+/*
38
41
+ * libqos driver framework
39
- if (has_data_file(bs)) {
42
+ *
40
- return -ENOTSUP;
43
+ * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
41
- }
44
+ *
42
-
45
+ * This library is free software; you can redistribute it and/or
43
- if (bytes == 0) {
46
+ * modify it under the terms of the GNU Lesser General Public
44
- /* align end of file to a sector boundary to ease reading with
47
+ * License version 2 as published by the Free Software Foundation.
45
- sector based I/Os */
48
+ *
46
- int64_t len = bdrv_getlength(bs->file->bs);
49
+ * This library is distributed in the hope that it will be useful,
47
- if (len < 0) {
50
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
48
- return len;
51
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
49
- }
52
+ * Lesser General Public License for more details.
50
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
53
+ *
51
- }
54
+ * You should have received a copy of the GNU Lesser General Public
52
-
55
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
53
- if (offset_into_cluster(s, offset)) {
56
+ */
54
- return -EINVAL;
57
+
55
- }
58
+#include "qemu/osdep.h"
56
+ assert(bytes == s->cluster_size || (bytes < s->cluster_size &&
59
+#include <getopt.h>
57
+ (offset + bytes == bs->total_sectors << BDRV_SECTOR_BITS)));
60
+#include "libqtest.h"
58
61
+#include "qapi/qmp/qdict.h"
59
buf = qemu_blockalign(bs, s->cluster_size);
62
+#include "qapi/qmp/qbool.h"
60
- if (bytes != s->cluster_size) {
63
+#include "qapi/qmp/qstring.h"
61
- if (bytes > s->cluster_size ||
64
+#include "qemu/module.h"
62
- offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)
65
+#include "qapi/qmp/qlist.h"
63
- {
66
+#include "libqos/malloc.h"
64
- qemu_vfree(buf);
67
+#include "libqos/qgraph.h"
65
- return -EINVAL;
68
+#include "libqos/qgraph_internal.h"
66
- }
69
+#include "libqos/qos_external.h"
67
+ if (bytes < s->cluster_size) {
70
+
68
/* Zero-pad last write if image size is not cluster aligned */
71
+
69
memset(buf + bytes, 0, s->cluster_size - bytes);
72
+
70
}
73
+void apply_to_node(const char *name, bool is_machine, bool is_abstract)
71
@@ -XXX,XX +XXX,XX @@ fail:
72
return ret;
73
}
74
75
+static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
76
+{
74
+{
77
+ Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
75
+ char *machine_name = NULL;
78
+
76
+ if (is_machine) {
79
+ assert(!t->cluster_type && !t->l2meta);
77
+ const char *arch = qtest_get_arch();
80
+
78
+ machine_name = g_strconcat(arch, "/", name, NULL);
81
+ return qcow2_co_pwritev_compressed_task(t->bs, t->offset, t->bytes, t->qiov,
79
+ name = machine_name;
82
+ t->qiov_offset);
80
+ }
81
+ qos_graph_node_set_availability(name, true);
82
+ if (is_abstract) {
83
+ qos_delete_cmd_line(name);
84
+ }
85
+ g_free(machine_name);
83
+}
86
+}
84
+
87
+
85
+/*
88
+/**
86
+ * XXX: put compressed sectors first, then all the cluster aligned
89
+ * apply_to_qlist(): using QMP queries QEMU for a list of
87
+ * tables to avoid losing bytes in alignment
90
+ * machines and devices available, and sets the respective node
91
+ * as true. If a node is found, also all its produced and contained
92
+ * child are marked available.
93
+ *
94
+ * See qos_graph_node_set_availability() for more info
88
+ */
95
+ */
89
+static coroutine_fn int
96
+void apply_to_qlist(QList *list, bool is_machine)
90
+qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
91
+ uint64_t offset, uint64_t bytes,
92
+ QEMUIOVector *qiov, size_t qiov_offset)
93
+{
97
+{
94
+ BDRVQcow2State *s = bs->opaque;
98
+ const QListEntry *p;
95
+ AioTaskPool *aio = NULL;
99
+ const char *name;
96
+ int ret = 0;
100
+ bool abstract;
97
+
101
+ QDict *minfo;
98
+ if (has_data_file(bs)) {
102
+ QObject *qobj;
99
+ return -ENOTSUP;
103
+ QString *qstr;
104
+ QBool *qbool;
105
+
106
+ for (p = qlist_first(list); p; p = qlist_next(p)) {
107
+ minfo = qobject_to(QDict, qlist_entry_obj(p));
108
+ qobj = qdict_get(minfo, "name");
109
+ qstr = qobject_to(QString, qobj);
110
+ name = qstring_get_str(qstr);
111
+
112
+ qobj = qdict_get(minfo, "abstract");
113
+ if (qobj) {
114
+ qbool = qobject_to(QBool, qobj);
115
+ abstract = qbool_get_bool(qbool);
116
+ } else {
117
+ abstract = false;
118
+ }
119
+
120
+ apply_to_node(name, is_machine, abstract);
121
+ qobj = qdict_get(minfo, "alias");
122
+ if (qobj) {
123
+ qstr = qobject_to(QString, qobj);
124
+ name = qstring_get_str(qstr);
125
+ apply_to_node(name, is_machine, abstract);
126
+ }
100
+ }
127
+ }
101
+
128
+}
102
+ if (bytes == 0) {
129
+
103
+ /*
130
+QGuestAllocator *get_machine_allocator(QOSGraphObject *obj)
104
+ * align end of file to a sector boundary to ease reading with
131
+{
105
+ * sector based I/Os
132
+ return obj->get_driver(obj, "memory");
106
+ */
133
+}
107
+ int64_t len = bdrv_getlength(bs->file->bs);
134
+
108
+ if (len < 0) {
135
+/**
109
+ return len;
136
+ * allocate_objects(): given an array of nodes @arg,
137
+ * walks the path invoking all constructors and
138
+ * passing the corresponding parameter in order to
139
+ * continue the objects allocation.
140
+ * Once the test is reached, return the object it consumes.
141
+ *
142
+ * Since the machine and QEDGE_CONSUMED_BY nodes allocate
143
+ * memory in the constructor, g_test_queue_destroy is used so
144
+ * that after execution they can be safely free'd. (The test's
145
+ * ->before callback is also welcome to use g_test_queue_destroy).
146
+ *
147
+ * Note: as specified in walk_path() too, @arg is an array of
148
+ * char *, where arg[0] is a pointer to the command line
149
+ * string that will be used to properly start QEMU when executing
150
+ * the test, and the remaining elements represent the actual objects
151
+ * that will be allocated.
152
+ */
153
+void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc)
154
+{
155
+ int current = 0;
156
+ QGuestAllocator *alloc;
157
+ QOSGraphObject *parent = NULL;
158
+ QOSGraphEdge *edge;
159
+ QOSGraphNode *node;
160
+ void *edge_arg;
161
+ void *obj;
162
+
163
+ node = qos_graph_get_node(path[current]);
164
+ g_assert(node->type == QNODE_MACHINE);
165
+
166
+ obj = qos_machine_new(node, qts);
167
+ qos_object_queue_destroy(obj);
168
+
169
+ alloc = get_machine_allocator(obj);
170
+ if (p_alloc) {
171
+ *p_alloc = alloc;
172
+ }
173
+
174
+ for (;;) {
175
+ if (node->type != QNODE_INTERFACE) {
176
+ qos_object_start_hw(obj);
177
+ parent = obj;
110
+ }
178
+ }
111
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
179
+
112
+ }
180
+ /* follow edge and get object for next node constructor */
113
+
181
+ current++;
114
+ if (offset_into_cluster(s, offset)) {
182
+ edge = qos_graph_get_edge(path[current - 1], path[current]);
115
+ return -EINVAL;
183
+ node = qos_graph_get_node(path[current]);
116
+ }
184
+
117
+
185
+ if (node->type == QNODE_TEST) {
118
+ while (bytes && aio_task_pool_status(aio) == 0) {
186
+ g_assert(qos_graph_edge_get_type(edge) == QEDGE_CONSUMED_BY);
119
+ uint64_t chunk_size = MIN(bytes, s->cluster_size);
187
+ return obj;
120
+
121
+ if (!aio && chunk_size != bytes) {
122
+ aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
123
+ }
188
+ }
124
+
189
+
125
+ ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_compressed_task_entry,
190
+ switch (qos_graph_edge_get_type(edge)) {
126
+ 0, 0, offset, chunk_size, qiov, qiov_offset, NULL);
191
+ case QEDGE_PRODUCES:
127
+ if (ret < 0) {
192
+ obj = parent->get_driver(parent, path[current]);
193
+ break;
194
+
195
+ case QEDGE_CONSUMED_BY:
196
+ edge_arg = qos_graph_edge_get_arg(edge);
197
+ obj = qos_driver_new(node, obj, alloc, edge_arg);
198
+ qos_object_queue_destroy(obj);
199
+ break;
200
+
201
+ case QEDGE_CONTAINS:
202
+ obj = parent->get_device(parent, path[current]);
128
+ break;
203
+ break;
129
+ }
204
+ }
130
+ qiov_offset += chunk_size;
131
+ offset += chunk_size;
132
+ bytes -= chunk_size;
133
+ }
205
+ }
134
+
135
+ if (aio) {
136
+ aio_task_pool_wait_all(aio);
137
+ if (ret == 0) {
138
+ ret = aio_task_pool_status(aio);
139
+ }
140
+ g_free(aio);
141
+ }
142
+
143
+ return ret;
144
+}
206
+}
145
+
207
+
146
static int coroutine_fn
208
diff --git a/tests/qtest/libqos/qos_external.h b/tests/qtest/libqos/qos_external.h
147
qcow2_co_preadv_compressed(BlockDriverState *bs,
209
new file mode 100644
148
uint64_t file_cluster_offset,
210
index XXXXXXX..XXXXXXX
211
--- /dev/null
212
+++ b/tests/qtest/libqos/qos_external.h
213
@@ -XXX,XX +XXX,XX @@
214
+/*
215
+ * libqos driver framework
216
+ *
217
+ * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
218
+ *
219
+ * This library is free software; you can redistribute it and/or
220
+ * modify it under the terms of the GNU Lesser General Public
221
+ * License version 2 as published by the Free Software Foundation.
222
+ *
223
+ * This library is distributed in the hope that it will be useful,
224
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
225
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
226
+ * Lesser General Public License for more details.
227
+ *
228
+ * You should have received a copy of the GNU Lesser General Public
229
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
230
+ */
231
+
232
+#ifndef QOS_EXTERNAL_H
233
+#define QOS_EXTERNAL_H
234
+#include "libqos/qgraph.h"
235
+
236
+void apply_to_node(const char *name, bool is_machine, bool is_abstract);
237
+void apply_to_qlist(QList *list, bool is_machine);
238
+QGuestAllocator *get_machine_allocator(QOSGraphObject *obj);
239
+void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc);
240
+
241
+#endif
242
diff --git a/tests/qtest/qos-test.c b/tests/qtest/qos-test.c
243
index XXXXXXX..XXXXXXX 100644
244
--- a/tests/qtest/qos-test.c
245
+++ b/tests/qtest/qos-test.c
246
@@ -XXX,XX +XXX,XX @@
247
#include "libqos/malloc.h"
248
#include "libqos/qgraph.h"
249
#include "libqos/qgraph_internal.h"
250
+#include "libqos/qos_external.h"
251
252
static char *old_path;
253
254
-static void apply_to_node(const char *name, bool is_machine, bool is_abstract)
255
-{
256
- char *machine_name = NULL;
257
- if (is_machine) {
258
- const char *arch = qtest_get_arch();
259
- machine_name = g_strconcat(arch, "/", name, NULL);
260
- name = machine_name;
261
- }
262
- qos_graph_node_set_availability(name, true);
263
- if (is_abstract) {
264
- qos_delete_cmd_line(name);
265
- }
266
- g_free(machine_name);
267
-}
268
269
-/**
270
- * apply_to_qlist(): using QMP queries QEMU for a list of
271
- * machines and devices available, and sets the respective node
272
- * as true. If a node is found, also all its produced and contained
273
- * child are marked available.
274
- *
275
- * See qos_graph_node_set_availability() for more info
276
- */
277
-static void apply_to_qlist(QList *list, bool is_machine)
278
-{
279
- const QListEntry *p;
280
- const char *name;
281
- bool abstract;
282
- QDict *minfo;
283
- QObject *qobj;
284
- QString *qstr;
285
- QBool *qbool;
286
-
287
- for (p = qlist_first(list); p; p = qlist_next(p)) {
288
- minfo = qobject_to(QDict, qlist_entry_obj(p));
289
- qobj = qdict_get(minfo, "name");
290
- qstr = qobject_to(QString, qobj);
291
- name = qstring_get_str(qstr);
292
-
293
- qobj = qdict_get(minfo, "abstract");
294
- if (qobj) {
295
- qbool = qobject_to(QBool, qobj);
296
- abstract = qbool_get_bool(qbool);
297
- } else {
298
- abstract = false;
299
- }
300
-
301
- apply_to_node(name, is_machine, abstract);
302
- qobj = qdict_get(minfo, "alias");
303
- if (qobj) {
304
- qstr = qobject_to(QString, qobj);
305
- name = qstring_get_str(qstr);
306
- apply_to_node(name, is_machine, abstract);
307
- }
308
- }
309
-}
310
311
/**
312
* qos_set_machines_devices_available(): sets availability of qgraph
313
@@ -XXX,XX +XXX,XX @@ static void qos_set_machines_devices_available(void)
314
qobject_unref(response);
315
}
316
317
-static QGuestAllocator *get_machine_allocator(QOSGraphObject *obj)
318
-{
319
- return obj->get_driver(obj, "memory");
320
-}
321
322
static void restart_qemu_or_continue(char *path)
323
{
324
@@ -XXX,XX +XXX,XX @@ void qos_invalidate_command_line(void)
325
old_path = NULL;
326
}
327
328
-/**
329
- * allocate_objects(): given an array of nodes @arg,
330
- * walks the path invoking all constructors and
331
- * passing the corresponding parameter in order to
332
- * continue the objects allocation.
333
- * Once the test is reached, return the object it consumes.
334
- *
335
- * Since the machine and QEDGE_CONSUMED_BY nodes allocate
336
- * memory in the constructor, g_test_queue_destroy is used so
337
- * that after execution they can be safely free'd. (The test's
338
- * ->before callback is also welcome to use g_test_queue_destroy).
339
- *
340
- * Note: as specified in walk_path() too, @arg is an array of
341
- * char *, where arg[0] is a pointer to the command line
342
- * string that will be used to properly start QEMU when executing
343
- * the test, and the remaining elements represent the actual objects
344
- * that will be allocated.
345
- */
346
-static void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc)
347
-{
348
- int current = 0;
349
- QGuestAllocator *alloc;
350
- QOSGraphObject *parent = NULL;
351
- QOSGraphEdge *edge;
352
- QOSGraphNode *node;
353
- void *edge_arg;
354
- void *obj;
355
-
356
- node = qos_graph_get_node(path[current]);
357
- g_assert(node->type == QNODE_MACHINE);
358
-
359
- obj = qos_machine_new(node, qts);
360
- qos_object_queue_destroy(obj);
361
-
362
- alloc = get_machine_allocator(obj);
363
- if (p_alloc) {
364
- *p_alloc = alloc;
365
- }
366
-
367
- for (;;) {
368
- if (node->type != QNODE_INTERFACE) {
369
- qos_object_start_hw(obj);
370
- parent = obj;
371
- }
372
-
373
- /* follow edge and get object for next node constructor */
374
- current++;
375
- edge = qos_graph_get_edge(path[current - 1], path[current]);
376
- node = qos_graph_get_node(path[current]);
377
-
378
- if (node->type == QNODE_TEST) {
379
- g_assert(qos_graph_edge_get_type(edge) == QEDGE_CONSUMED_BY);
380
- return obj;
381
- }
382
-
383
- switch (qos_graph_edge_get_type(edge)) {
384
- case QEDGE_PRODUCES:
385
- obj = parent->get_driver(parent, path[current]);
386
- break;
387
-
388
- case QEDGE_CONSUMED_BY:
389
- edge_arg = qos_graph_edge_get_arg(edge);
390
- obj = qos_driver_new(node, obj, alloc, edge_arg);
391
- qos_object_queue_destroy(obj);
392
- break;
393
-
394
- case QEDGE_CONTAINS:
395
- obj = parent->get_device(parent, path[current]);
396
- break;
397
- }
398
- }
399
-}
400
401
/* The argument to run_one_test, which is the test function that is registered
402
* with GTest, is a vector of strings. The first item is the initial command
149
--
403
--
150
2.24.1
404
2.24.1
151
405
152
diff view generated by jsdifflib
1
Blindly overriding IMGOPTS is suboptimal as this discards user-specified
1
From: Alexander Bulekov <alxndr@bu.edu>
2
options. Whatever options the test needs should simply be appended.
3
2
4
Some tests do this (with IMGOPTS=$(_optstr_add "$IMGOPTS" "...")), but
3
tests/fuzz/fuzz.c serves as the entry point for the virtual-device
5
that is cumbersome. It’s simpler to just give _make_test_img an -o
4
fuzzer. Namely, libfuzzer invokes the LLVMFuzzerInitialize and
6
parameter with which tests can add options.
5
LLVMFuzzerTestOneInput functions, both of which are defined in this
6
file. This change adds a "FuzzTarget" struct, along with the
7
fuzz_add_target function, which should be used to define new fuzz
8
targets.
7
9
8
Some tests actually must override the user-specified options, though,
10
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
9
for example when creating an image in a different format than the test
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
$IMGFMT. For such cases, --no-opts allows clearing the current option
12
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
11
list.
13
Message-id: 20200220041118.23264-13-alxndr@bu.edu
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
---
16
MAINTAINERS | 8 ++
17
tests/qtest/fuzz/Makefile.include | 6 +
18
tests/qtest/fuzz/fuzz.c | 179 ++++++++++++++++++++++++++++++
19
tests/qtest/fuzz/fuzz.h | 95 ++++++++++++++++
20
4 files changed, 288 insertions(+)
21
create mode 100644 tests/qtest/fuzz/Makefile.include
22
create mode 100644 tests/qtest/fuzz/fuzz.c
23
create mode 100644 tests/qtest/fuzz/fuzz.h
12
24
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
diff --git a/MAINTAINERS b/MAINTAINERS
14
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
15
Message-id: 20191107163708.833192-10-mreitz@redhat.com
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
tests/qemu-iotests/common.rc | 13 +++++++++++++
19
1 file changed, 13 insertions(+)
20
21
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
22
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
23
--- a/tests/qemu-iotests/common.rc
27
--- a/MAINTAINERS
24
+++ b/tests/qemu-iotests/common.rc
28
+++ b/MAINTAINERS
25
@@ -XXX,XX +XXX,XX @@ _make_test_img()
29
@@ -XXX,XX +XXX,XX @@ F: qtest.c
26
local use_backing=0
30
F: accel/qtest.c
27
local backing_file=""
31
F: tests/qtest/
28
local object_options=""
32
29
+ local opts_param=false
33
+Device Fuzzing
30
local misc_params=()
34
+M: Alexander Bulekov <alxndr@bu.edu>
31
35
+R: Paolo Bonzini <pbonzini@redhat.com>
32
if [ -n "$TEST_IMG_FILE" ]; then
36
+R: Bandan Das <bsd@redhat.com>
33
@@ -XXX,XX +XXX,XX @@ _make_test_img()
37
+R: Stefan Hajnoczi <stefanha@redhat.com>
34
if [ "$use_backing" = "1" -a -z "$backing_file" ]; then
38
+S: Maintained
35
backing_file=$param
39
+F: tests/qtest/fuzz/
36
continue
40
+
37
+ elif $opts_param; then
41
Register API
38
+ optstr=$(_optstr_add "$optstr" "$param")
42
M: Alistair Francis <alistair@alistair23.me>
39
+ opts_param=false
43
S: Maintained
40
+ continue
44
diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include
41
fi
45
new file mode 100644
42
46
index XXXXXXX..XXXXXXX
43
case "$param" in
47
--- /dev/null
44
@@ -XXX,XX +XXX,XX @@ _make_test_img()
48
+++ b/tests/qtest/fuzz/Makefile.include
45
use_backing=1
49
@@ -XXX,XX +XXX,XX @@
46
;;
50
+QEMU_PROG_FUZZ=qemu-fuzz-$(TARGET_NAME)$(EXESUF)
47
51
+
48
+ -o)
52
+fuzz-obj-y += tests/qtest/libqtest.o
49
+ opts_param=true
53
+fuzz-obj-y += tests/qtest/fuzz/fuzz.o # Fuzzer skeleton
50
+ ;;
54
+
51
+
55
+FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
52
+ --no-opts)
56
diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
53
+ optstr=""
57
new file mode 100644
54
+ ;;
58
index XXXXXXX..XXXXXXX
55
+
59
--- /dev/null
56
*)
60
+++ b/tests/qtest/fuzz/fuzz.c
57
misc_params=("${misc_params[@]}" "$param")
61
@@ -XXX,XX +XXX,XX @@
58
;;
62
+/*
63
+ * fuzzing driver
64
+ *
65
+ * Copyright Red Hat Inc., 2019
66
+ *
67
+ * Authors:
68
+ * Alexander Bulekov <alxndr@bu.edu>
69
+ *
70
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
71
+ * See the COPYING file in the top-level directory.
72
+ *
73
+ */
74
+
75
+#include "qemu/osdep.h"
76
+
77
+#include <wordexp.h>
78
+
79
+#include "sysemu/qtest.h"
80
+#include "sysemu/runstate.h"
81
+#include "sysemu/sysemu.h"
82
+#include "qemu/main-loop.h"
83
+#include "tests/qtest/libqtest.h"
84
+#include "tests/qtest/libqos/qgraph.h"
85
+#include "fuzz.h"
86
+
87
+#define MAX_EVENT_LOOPS 10
88
+
89
+typedef struct FuzzTargetState {
90
+ FuzzTarget *target;
91
+ QSLIST_ENTRY(FuzzTargetState) target_list;
92
+} FuzzTargetState;
93
+
94
+typedef QSLIST_HEAD(, FuzzTargetState) FuzzTargetList;
95
+
96
+static const char *fuzz_arch = TARGET_NAME;
97
+
98
+static FuzzTargetList *fuzz_target_list;
99
+static FuzzTarget *fuzz_target;
100
+static QTestState *fuzz_qts;
101
+
102
+
103
+
104
+void flush_events(QTestState *s)
105
+{
106
+ int i = MAX_EVENT_LOOPS;
107
+ while (g_main_context_pending(NULL) && i-- > 0) {
108
+ main_loop_wait(false);
109
+ }
110
+}
111
+
112
+static QTestState *qtest_setup(void)
113
+{
114
+ qtest_server_set_send_handler(&qtest_client_inproc_recv, &fuzz_qts);
115
+ return qtest_inproc_init(&fuzz_qts, false, fuzz_arch,
116
+ &qtest_server_inproc_recv);
117
+}
118
+
119
+void fuzz_add_target(const FuzzTarget *target)
120
+{
121
+ FuzzTargetState *tmp;
122
+ FuzzTargetState *target_state;
123
+ if (!fuzz_target_list) {
124
+ fuzz_target_list = g_new0(FuzzTargetList, 1);
125
+ }
126
+
127
+ QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
128
+ if (g_strcmp0(tmp->target->name, target->name) == 0) {
129
+ fprintf(stderr, "Error: Fuzz target name %s already in use\n",
130
+ target->name);
131
+ abort();
132
+ }
133
+ }
134
+ target_state = g_new0(FuzzTargetState, 1);
135
+ target_state->target = g_new0(FuzzTarget, 1);
136
+ *(target_state->target) = *target;
137
+ QSLIST_INSERT_HEAD(fuzz_target_list, target_state, target_list);
138
+}
139
+
140
+
141
+
142
+static void usage(char *path)
143
+{
144
+ printf("Usage: %s --fuzz-target=FUZZ_TARGET [LIBFUZZER ARGUMENTS]\n", path);
145
+ printf("where FUZZ_TARGET is one of:\n");
146
+ FuzzTargetState *tmp;
147
+ if (!fuzz_target_list) {
148
+ fprintf(stderr, "Fuzz target list not initialized\n");
149
+ abort();
150
+ }
151
+ QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
152
+ printf(" * %s : %s\n", tmp->target->name,
153
+ tmp->target->description);
154
+ }
155
+ exit(0);
156
+}
157
+
158
+static FuzzTarget *fuzz_get_target(char* name)
159
+{
160
+ FuzzTargetState *tmp;
161
+ if (!fuzz_target_list) {
162
+ fprintf(stderr, "Fuzz target list not initialized\n");
163
+ abort();
164
+ }
165
+
166
+ QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
167
+ if (strcmp(tmp->target->name, name) == 0) {
168
+ return tmp->target;
169
+ }
170
+ }
171
+ return NULL;
172
+}
173
+
174
+
175
+/* Executed for each fuzzing-input */
176
+int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size)
177
+{
178
+ /*
179
+ * Do the pre-fuzz-initialization before the first fuzzing iteration,
180
+ * instead of before the actual fuzz loop. This is needed since libfuzzer
181
+ * may fork off additional workers, prior to the fuzzing loop, and if
182
+ * pre_fuzz() sets up e.g. shared memory, this should be done for the
183
+ * individual worker processes
184
+ */
185
+ static int pre_fuzz_done;
186
+ if (!pre_fuzz_done && fuzz_target->pre_fuzz) {
187
+ fuzz_target->pre_fuzz(fuzz_qts);
188
+ pre_fuzz_done = true;
189
+ }
190
+
191
+ fuzz_target->fuzz(fuzz_qts, Data, Size);
192
+ return 0;
193
+}
194
+
195
+/* Executed once, prior to fuzzing */
196
+int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
197
+{
198
+
199
+ char *target_name;
200
+
201
+ /* Initialize qgraph and modules */
202
+ qos_graph_init();
203
+ module_call_init(MODULE_INIT_FUZZ_TARGET);
204
+ module_call_init(MODULE_INIT_QOM);
205
+ module_call_init(MODULE_INIT_LIBQOS);
206
+
207
+ if (*argc <= 1) {
208
+ usage(**argv);
209
+ }
210
+
211
+ /* Identify the fuzz target */
212
+ target_name = (*argv)[1];
213
+ if (!strstr(target_name, "--fuzz-target=")) {
214
+ usage(**argv);
215
+ }
216
+
217
+ target_name += strlen("--fuzz-target=");
218
+
219
+ fuzz_target = fuzz_get_target(target_name);
220
+ if (!fuzz_target) {
221
+ usage(**argv);
222
+ }
223
+
224
+ fuzz_qts = qtest_setup();
225
+
226
+ if (fuzz_target->pre_vm_init) {
227
+ fuzz_target->pre_vm_init();
228
+ }
229
+
230
+ /* Run QEMU's softmmu main with the fuzz-target dependent arguments */
231
+ const char *init_cmdline = fuzz_target->get_init_cmdline(fuzz_target);
232
+
233
+ /* Split the runcmd into an argv and argc */
234
+ wordexp_t result;
235
+ wordexp(init_cmdline, &result, 0);
236
+
237
+ qemu_init(result.we_wordc, result.we_wordv, NULL);
238
+
239
+ return 0;
240
+}
241
diff --git a/tests/qtest/fuzz/fuzz.h b/tests/qtest/fuzz/fuzz.h
242
new file mode 100644
243
index XXXXXXX..XXXXXXX
244
--- /dev/null
245
+++ b/tests/qtest/fuzz/fuzz.h
246
@@ -XXX,XX +XXX,XX @@
247
+/*
248
+ * fuzzing driver
249
+ *
250
+ * Copyright Red Hat Inc., 2019
251
+ *
252
+ * Authors:
253
+ * Alexander Bulekov <alxndr@bu.edu>
254
+ *
255
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
256
+ * See the COPYING file in the top-level directory.
257
+ *
258
+ */
259
+
260
+#ifndef FUZZER_H_
261
+#define FUZZER_H_
262
+
263
+#include "qemu/osdep.h"
264
+#include "qemu/units.h"
265
+#include "qapi/error.h"
266
+
267
+#include "tests/qtest/libqtest.h"
268
+
269
+/**
270
+ * A libfuzzer fuzzing target
271
+ *
272
+ * The QEMU fuzzing binary is built with all available targets, each
273
+ * with a unique @name that can be specified on the command-line to
274
+ * select which target should run.
275
+ *
276
+ * A target must implement ->fuzz() to process a random input. If QEMU
277
+ * crashes in ->fuzz() then libfuzzer will record a failure.
278
+ *
279
+ * Fuzzing targets are registered with fuzz_add_target():
280
+ *
281
+ * static const FuzzTarget fuzz_target = {
282
+ * .name = "my-device-fifo",
283
+ * .description = "Fuzz the FIFO buffer registers of my-device",
284
+ * ...
285
+ * };
286
+ *
287
+ * static void register_fuzz_target(void)
288
+ * {
289
+ * fuzz_add_target(&fuzz_target);
290
+ * }
291
+ * fuzz_target_init(register_fuzz_target);
292
+ */
293
+typedef struct FuzzTarget {
294
+ const char *name; /* target identifier (passed to --fuzz-target=)*/
295
+ const char *description; /* help text */
296
+
297
+
298
+ /*
299
+ * returns the arg-list that is passed to qemu/softmmu init()
300
+ * Cannot be NULL
301
+ */
302
+ const char* (*get_init_cmdline)(struct FuzzTarget *);
303
+
304
+ /*
305
+ * will run once, prior to running qemu/softmmu init.
306
+ * eg: set up shared-memory for communication with the child-process
307
+ * Can be NULL
308
+ */
309
+ void(*pre_vm_init)(void);
310
+
311
+ /*
312
+ * will run once, after QEMU has been initialized, prior to the fuzz-loop.
313
+ * eg: detect the memory map
314
+ * Can be NULL
315
+ */
316
+ void(*pre_fuzz)(QTestState *);
317
+
318
+ /*
319
+ * accepts and executes an input from libfuzzer. this is repeatedly
320
+ * executed during the fuzzing loop. Its should handle setup, input
321
+ * execution and cleanup.
322
+ * Cannot be NULL
323
+ */
324
+ void(*fuzz)(QTestState *, const unsigned char *, size_t);
325
+
326
+} FuzzTarget;
327
+
328
+void flush_events(QTestState *);
329
+void reboot(QTestState *);
330
+
331
+/*
332
+ * makes a copy of *target and adds it to the target-list.
333
+ * i.e. fine to set up target on the caller's stack
334
+ */
335
+void fuzz_add_target(const FuzzTarget *target);
336
+
337
+int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size);
338
+int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp);
339
+
340
+#endif
341
+
59
--
342
--
60
2.24.1
343
2.24.1
61
344
62
diff view generated by jsdifflib
1
From: PanNengyuan <pannengyuan@huawei.com>
1
From: Alexander Bulekov <alxndr@bu.edu>
2
2
3
This avoid a memory leak when qom-set is called to set throttle_group
3
Ram blocks were marked MADV_DONTFORK breaking fuzzing-tests which
4
limits, here is an easy way to reproduce:
4
execute each test-input in a forked process.
5
5
6
1. run qemu-iotests as follow and check the result with asan:
6
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
7
./check -qcow2 184
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
9
Message-id: 20200220041118.23264-14-alxndr@bu.edu
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
exec.c | 12 ++++++++++--
13
1 file changed, 10 insertions(+), 2 deletions(-)
8
14
9
Following is the asan output backtrack:
15
diff --git a/exec.c b/exec.c
10
Direct leak of 912 byte(s) in 3 object(s) allocated from:
11
#0 0xffff8d7ab3c3 in __interceptor_calloc (/lib64/libasan.so.4+0xd33c3)
12
#1 0xffff8d4c31cb in g_malloc0 (/lib64/libglib-2.0.so.0+0x571cb)
13
#2 0x190c857 in qobject_input_start_struct /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qapi/qobject-input-visitor.c:295
14
#3 0x19070df in visit_start_struct /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qapi/qapi-visit-core.c:49
15
#4 0x1948b87 in visit_type_ThrottleLimits qapi/qapi-visit-block-core.c:3759
16
#5 0x17e4aa3 in throttle_group_set_limits /mnt/sdc/qemu-master/qemu-4.2.0-rc0/block/throttle-groups.c:900
17
#6 0x1650eff in object_property_set /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qom/object.c:1272
18
#7 0x1658517 in object_property_set_qobject /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qom/qom-qobject.c:26
19
#8 0x15880bb in qmp_qom_set /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qom/qom-qmp-cmds.c:74
20
#9 0x157e3e3 in qmp_marshal_qom_set qapi/qapi-commands-qom.c:154
21
22
Reported-by: Euler Robot <euler.robot@huawei.com>
23
Signed-off-by: PanNengyuan <pannengyuan@huawei.com>
24
Message-id: 1574835614-42028-1-git-send-email-pannengyuan@huawei.com
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
---
27
block/throttle-groups.c | 4 ++--
28
1 file changed, 2 insertions(+), 2 deletions(-)
29
30
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
31
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
32
--- a/block/throttle-groups.c
17
--- a/exec.c
33
+++ b/block/throttle-groups.c
18
+++ b/exec.c
34
@@ -XXX,XX +XXX,XX @@ static void throttle_group_set_limits(Object *obj, Visitor *v,
19
@@ -XXX,XX +XXX,XX @@
35
{
20
#include "sysemu/kvm.h"
36
ThrottleGroup *tg = THROTTLE_GROUP(obj);
21
#include "sysemu/sysemu.h"
37
ThrottleConfig cfg;
22
#include "sysemu/tcg.h"
38
- ThrottleLimits arg = { 0 };
23
+#include "sysemu/qtest.h"
39
- ThrottleLimits *argp = &arg;
24
#include "qemu/timer.h"
40
+ ThrottleLimits *argp;
25
#include "qemu/config-file.h"
41
Error *local_err = NULL;
26
#include "qemu/error-report.h"
42
27
@@ -XXX,XX +XXX,XX @@ static void ram_block_add(RAMBlock *new_block, Error **errp, bool shared)
43
visit_type_ThrottleLimits(v, name, &argp, &local_err);
28
if (new_block->host) {
44
@@ -XXX,XX +XXX,XX @@ static void throttle_group_set_limits(Object *obj, Visitor *v,
29
qemu_ram_setup_dump(new_block->host, new_block->max_length);
45
unlock:
30
qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_HUGEPAGE);
46
qemu_mutex_unlock(&tg->lock);
31
- /* MADV_DONTFORK is also needed by KVM in absence of synchronous MMU */
47
ret:
32
- qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_DONTFORK);
48
+ qapi_free_ThrottleLimits(argp);
33
+ /*
49
error_propagate(errp, local_err);
34
+ * MADV_DONTFORK is also needed by KVM in absence of synchronous MMU
50
return;
35
+ * Configure it unless the machine is a qtest server, in which case
36
+ * KVM is not used and it may be forked (eg for fuzzing purposes).
37
+ */
38
+ if (!qtest_enabled()) {
39
+ qemu_madvise(new_block->host, new_block->max_length,
40
+ QEMU_MADV_DONTFORK);
41
+ }
42
ram_block_notify_add(new_block->host, new_block->max_length);
43
}
51
}
44
}
52
--
45
--
53
2.24.1
46
2.24.1
54
47
55
diff view generated by jsdifflib
1
This will allow us to add more options than just -b.
1
From: Alexander Bulekov <alxndr@bu.edu>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
The qtest-based fuzzer makes use of forking to reset-state between
4
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
tests. Keep the callback enabled, so the call_rcu thread gets created
5
Message-id: 20191107163708.833192-9-mreitz@redhat.com
5
within the child process.
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
7
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
8
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
9
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-id: 20200220041118.23264-15-alxndr@bu.edu
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
---
12
---
8
tests/qemu-iotests/common.rc | 28 ++++++++++++++++++++--------
13
softmmu/vl.c | 12 +++++++++++-
9
1 file changed, 20 insertions(+), 8 deletions(-)
14
1 file changed, 11 insertions(+), 1 deletion(-)
10
15
11
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
16
diff --git a/softmmu/vl.c b/softmmu/vl.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qemu-iotests/common.rc
18
--- a/softmmu/vl.c
14
+++ b/tests/qemu-iotests/common.rc
19
+++ b/softmmu/vl.c
15
@@ -XXX,XX +XXX,XX @@ _make_test_img()
20
@@ -XXX,XX +XXX,XX @@ void qemu_init(int argc, char **argv, char **envp)
16
# extra qemu-img options can be added by tests
21
set_memory_options(&ram_slots, &maxram_size, machine_class);
17
# at least one argument (the image size) needs to be added
22
18
local extra_img_options=""
23
os_daemonize();
19
- local image_size=$*
24
- rcu_disable_atfork();
20
local optstr=""
21
local img_name=""
22
local use_backing=0
23
local backing_file=""
24
local object_options=""
25
+ local misc_params=()
26
27
if [ -n "$TEST_IMG_FILE" ]; then
28
img_name=$TEST_IMG_FILE
29
@@ -XXX,XX +XXX,XX @@ _make_test_img()
30
optstr=$(_optstr_add "$optstr" "key-secret=keysec0")
31
fi
32
33
- if [ "$1" = "-b" ]; then
34
- use_backing=1
35
- backing_file=$2
36
- image_size=$3
37
- fi
38
+ for param; do
39
+ if [ "$use_backing" = "1" -a -z "$backing_file" ]; then
40
+ backing_file=$param
41
+ continue
42
+ fi
43
+
25
+
44
+ case "$param" in
26
+ /*
45
+ -b)
27
+ * If QTest is enabled, keep the rcu_atfork enabled, since system processes
46
+ use_backing=1
28
+ * may be forked testing purposes (e.g. fork-server based fuzzing) The fork
47
+ ;;
29
+ * should happen before a signle cpu instruction is executed, to prevent
48
+
30
+ * deadlocks. See commit 73c6e40, rcu: "completely disable pthread_atfork
49
+ *)
31
+ * callbacks as soon as possible"
50
+ misc_params=("${misc_params[@]}" "$param")
32
+ */
51
+ ;;
33
+ if (!qtest_enabled()) {
52
+ esac
34
+ rcu_disable_atfork();
53
+ done
35
+ }
54
+
36
55
if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then
37
if (pid_file && !qemu_write_pidfile(pid_file, &err)) {
56
optstr=$(_optstr_add "$optstr" "cluster_size=$CLUSTER_SIZE")
38
error_reportf_err(err, "cannot create PID file: ");
57
fi
58
@@ -XXX,XX +XXX,XX @@ _make_test_img()
59
# XXX(hch): have global image options?
60
(
61
if [ $use_backing = 1 ]; then
62
- $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1
63
+ $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" "${misc_params[@]}" 2>&1
64
else
65
- $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1
66
+ $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" "${misc_params[@]}" 2>&1
67
fi
68
) | _filter_img_create
69
70
--
39
--
71
2.24.1
40
2.24.1
72
41
73
diff view generated by jsdifflib
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
1
From: Alexander Bulekov <alxndr@bu.edu>
2
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
2
3
Message-id: 20191107163708.833192-5-mreitz@redhat.com
3
fork() is a simple way to ensure that state does not leak in between
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
fuzzing runs. Unfortunately, the fuzzer mutation engine relies on
5
bitmaps which contain coverage information for each fuzzing run, and
6
these bitmaps should be copied from the child to the parent(where the
7
mutation occurs). These bitmaps are created through compile-time
8
instrumentation and they are not shared with fork()-ed processes, by
9
default. To address this, we create a shared memory region, adjust its
10
size and map it _over_ the counter region. Furthermore, libfuzzer
11
doesn't generally expose the globals that specify the location of the
12
counters/coverage bitmap. As a workaround, we rely on a custom linker
13
script which forces all of the bitmaps we care about to be placed in a
14
contiguous region, which is easy to locate and mmap over.
15
16
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
17
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
18
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
19
Message-id: 20200220041118.23264-16-alxndr@bu.edu
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
---
21
---
6
tests/qemu-iotests/common.filter | 24 ++++++++++++++++++++++++
22
tests/qtest/fuzz/Makefile.include | 5 +++
7
1 file changed, 24 insertions(+)
23
tests/qtest/fuzz/fork_fuzz.c | 55 +++++++++++++++++++++++++++++++
24
tests/qtest/fuzz/fork_fuzz.h | 23 +++++++++++++
25
tests/qtest/fuzz/fork_fuzz.ld | 37 +++++++++++++++++++++
26
4 files changed, 120 insertions(+)
27
create mode 100644 tests/qtest/fuzz/fork_fuzz.c
28
create mode 100644 tests/qtest/fuzz/fork_fuzz.h
29
create mode 100644 tests/qtest/fuzz/fork_fuzz.ld
8
30
9
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
31
diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include
10
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
11
--- a/tests/qemu-iotests/common.filter
33
--- a/tests/qtest/fuzz/Makefile.include
12
+++ b/tests/qemu-iotests/common.filter
34
+++ b/tests/qtest/fuzz/Makefile.include
13
@@ -XXX,XX +XXX,XX @@ _filter_qmp_empty_return()
35
@@ -XXX,XX +XXX,XX @@ QEMU_PROG_FUZZ=qemu-fuzz-$(TARGET_NAME)$(EXESUF)
14
grep -v '{"return": {}}'
36
15
}
37
fuzz-obj-y += tests/qtest/libqtest.o
16
38
fuzz-obj-y += tests/qtest/fuzz/fuzz.o # Fuzzer skeleton
17
+_filter_json_filename()
39
+fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o
40
41
FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
42
+
43
+# Linker Script to force coverage-counters into known regions which we can mark
44
+# shared
45
+FUZZ_LDFLAGS += -Xlinker -T$(SRC_PATH)/tests/qtest/fuzz/fork_fuzz.ld
46
diff --git a/tests/qtest/fuzz/fork_fuzz.c b/tests/qtest/fuzz/fork_fuzz.c
47
new file mode 100644
48
index XXXXXXX..XXXXXXX
49
--- /dev/null
50
+++ b/tests/qtest/fuzz/fork_fuzz.c
51
@@ -XXX,XX +XXX,XX @@
52
+/*
53
+ * Fork-based fuzzing helpers
54
+ *
55
+ * Copyright Red Hat Inc., 2019
56
+ *
57
+ * Authors:
58
+ * Alexander Bulekov <alxndr@bu.edu>
59
+ *
60
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
61
+ * See the COPYING file in the top-level directory.
62
+ *
63
+ */
64
+
65
+#include "qemu/osdep.h"
66
+#include "fork_fuzz.h"
67
+
68
+
69
+void counter_shm_init(void)
18
+{
70
+{
19
+ $PYTHON -c 'import sys
71
+ char *shm_path = g_strdup_printf("/qemu-fuzz-cntrs.%d", getpid());
20
+result, *fnames = sys.stdin.read().split("json:{")
72
+ int fd = shm_open(shm_path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
21
+depth = 0
73
+ g_free(shm_path);
22
+for fname in fnames:
23
+ depth += 1 # For the opening brace in the split separator
24
+ for chr_i, chr in enumerate(fname):
25
+ if chr == "{":
26
+ depth += 1
27
+ elif chr == "}":
28
+ depth -= 1
29
+ if depth == 0:
30
+ break
31
+
74
+
32
+ # json:{} filenames may be nested; filter out everything from
75
+ if (fd == -1) {
33
+ # inside the outermost one
76
+ perror("Error: ");
34
+ if depth == 0:
77
+ exit(1);
35
+ chr_i += 1 # First character past the filename
78
+ }
36
+ result += "json:{ /* filtered */ }" + fname[chr_i:]
79
+ if (ftruncate(fd, &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START) == -1) {
80
+ perror("Error: ");
81
+ exit(1);
82
+ }
83
+ /* Copy what's in the counter region to the shm.. */
84
+ void *rptr = mmap(NULL ,
85
+ &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START,
86
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
87
+ memcpy(rptr,
88
+ &__FUZZ_COUNTERS_START,
89
+ &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START);
37
+
90
+
38
+sys.stdout.write(result)'
91
+ munmap(rptr, &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START);
92
+
93
+ /* And map the shm over the counter region */
94
+ rptr = mmap(&__FUZZ_COUNTERS_START,
95
+ &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START,
96
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0);
97
+
98
+ close(fd);
99
+
100
+ if (!rptr) {
101
+ perror("Error: ");
102
+ exit(1);
103
+ }
39
+}
104
+}
40
+
105
+
41
# make sure this script returns success
106
+
42
true
107
diff --git a/tests/qtest/fuzz/fork_fuzz.h b/tests/qtest/fuzz/fork_fuzz.h
108
new file mode 100644
109
index XXXXXXX..XXXXXXX
110
--- /dev/null
111
+++ b/tests/qtest/fuzz/fork_fuzz.h
112
@@ -XXX,XX +XXX,XX @@
113
+/*
114
+ * Fork-based fuzzing helpers
115
+ *
116
+ * Copyright Red Hat Inc., 2019
117
+ *
118
+ * Authors:
119
+ * Alexander Bulekov <alxndr@bu.edu>
120
+ *
121
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
122
+ * See the COPYING file in the top-level directory.
123
+ *
124
+ */
125
+
126
+#ifndef FORK_FUZZ_H
127
+#define FORK_FUZZ_H
128
+
129
+extern uint8_t __FUZZ_COUNTERS_START;
130
+extern uint8_t __FUZZ_COUNTERS_END;
131
+
132
+void counter_shm_init(void);
133
+
134
+#endif
135
+
136
diff --git a/tests/qtest/fuzz/fork_fuzz.ld b/tests/qtest/fuzz/fork_fuzz.ld
137
new file mode 100644
138
index XXXXXXX..XXXXXXX
139
--- /dev/null
140
+++ b/tests/qtest/fuzz/fork_fuzz.ld
141
@@ -XXX,XX +XXX,XX @@
142
+/* We adjust linker script modification to place all of the stuff that needs to
143
+ * persist across fuzzing runs into a contiguous seciton of memory. Then, it is
144
+ * easy to re-map the counter-related memory as shared.
145
+*/
146
+
147
+SECTIONS
148
+{
149
+ .data.fuzz_start : ALIGN(4K)
150
+ {
151
+ __FUZZ_COUNTERS_START = .;
152
+ __start___sancov_cntrs = .;
153
+ *(_*sancov_cntrs);
154
+ __stop___sancov_cntrs = .;
155
+
156
+ /* Lowest stack counter */
157
+ *(__sancov_lowest_stack);
158
+ }
159
+ .data.fuzz_ordered :
160
+ {
161
+ /* Coverage counters. They're not necessary for fuzzing, but are useful
162
+ * for analyzing the fuzzing performance
163
+ */
164
+ __start___llvm_prf_cnts = .;
165
+ *(*llvm_prf_cnts);
166
+ __stop___llvm_prf_cnts = .;
167
+
168
+ /* Internal Libfuzzer TracePC object which contains the ValueProfileMap */
169
+ FuzzerTracePC*(.bss*);
170
+ }
171
+ .data.fuzz_end : ALIGN(4K)
172
+ {
173
+ __FUZZ_COUNTERS_END = .;
174
+ }
175
+}
176
+/* Dont overwrite the SECTIONS in the default linker script. Instead insert the
177
+ * above into the default script */
178
+INSERT AFTER .data;
43
--
179
--
44
2.24.1
180
2.24.1
45
181
46
diff view generated by jsdifflib
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
From: Alexander Bulekov <alxndr@bu.edu>
2
2
3
Allow writing all the data compressed through the filter driver.
3
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
4
The written data will be aligned by the cluster size.
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Based on the QEMU current implementation, that data can be written to
5
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
6
unallocated clusters only. May be used for a backup job.
6
Message-id: 20200220041118.23264-17-alxndr@bu.edu
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
tests/qtest/fuzz/Makefile.include | 2 +
10
tests/qtest/fuzz/qos_fuzz.c | 234 ++++++++++++++++++++++++++++++
11
tests/qtest/fuzz/qos_fuzz.h | 33 +++++
12
3 files changed, 269 insertions(+)
13
create mode 100644 tests/qtest/fuzz/qos_fuzz.c
14
create mode 100644 tests/qtest/fuzz/qos_fuzz.h
7
15
8
Suggested-by: Max Reitz <mreitz@redhat.com>
16
diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include
9
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-id: 1575288906-551879-2-git-send-email-andrey.shinkevich@virtuozzo.com
12
[mreitz: Replace NULL bdrv_get_format_name() by "(no format)"]
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
block/Makefile.objs | 1 +
16
block/filter-compress.c | 168 ++++++++++++++++++++++++++++++++++++++++
17
qapi/block-core.json | 10 ++-
18
3 files changed, 175 insertions(+), 4 deletions(-)
19
create mode 100644 block/filter-compress.c
20
21
diff --git a/block/Makefile.objs b/block/Makefile.objs
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/block/Makefile.objs
18
--- a/tests/qtest/fuzz/Makefile.include
24
+++ b/block/Makefile.objs
19
+++ b/tests/qtest/fuzz/Makefile.include
25
@@ -XXX,XX +XXX,XX @@ block-obj-y += crypto.o
20
@@ -XXX,XX +XXX,XX @@
26
21
QEMU_PROG_FUZZ=qemu-fuzz-$(TARGET_NAME)$(EXESUF)
27
block-obj-y += aio_task.o
22
28
block-obj-y += backup-top.o
23
fuzz-obj-y += tests/qtest/libqtest.o
29
+block-obj-y += filter-compress.o
24
+fuzz-obj-y += $(libqos-obj-y)
30
25
fuzz-obj-y += tests/qtest/fuzz/fuzz.o # Fuzzer skeleton
31
common-obj-y += stream.o
26
fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o
32
27
+fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
33
diff --git a/block/filter-compress.c b/block/filter-compress.c
28
29
FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
30
31
diff --git a/tests/qtest/fuzz/qos_fuzz.c b/tests/qtest/fuzz/qos_fuzz.c
34
new file mode 100644
32
new file mode 100644
35
index XXXXXXX..XXXXXXX
33
index XXXXXXX..XXXXXXX
36
--- /dev/null
34
--- /dev/null
37
+++ b/block/filter-compress.c
35
+++ b/tests/qtest/fuzz/qos_fuzz.c
38
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@
39
+/*
37
+/*
40
+ * Compress filter block driver
38
+ * QOS-assisted fuzzing helpers
41
+ *
39
+ *
42
+ * Copyright (c) 2019 Virtuozzo International GmbH
40
+ * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
43
+ *
41
+ *
44
+ * Author:
42
+ * This library is free software; you can redistribute it and/or
45
+ * Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
43
+ * modify it under the terms of the GNU Lesser General Public
46
+ * (based on block/copy-on-read.c by Max Reitz)
44
+ * License version 2 as published by the Free Software Foundation.
47
+ *
45
+ *
48
+ * This program is free software; you can redistribute it and/or
46
+ * This library is distributed in the hope that it will be useful,
49
+ * modify it under the terms of the GNU General Public License as
50
+ * published by the Free Software Foundation; either version 2 or
51
+ * (at your option) any later version of the License.
52
+ *
53
+ * This program is distributed in the hope that it will be useful,
54
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
47
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
55
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
56
+ * GNU General Public License for more details.
49
+ * Lesser General Public License for more details.
57
+ *
50
+ *
58
+ * You should have received a copy of the GNU General Public License
51
+ * You should have received a copy of the GNU Lesser General Public
59
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
52
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
60
+ */
53
+ */
61
+
54
+
62
+#include "qemu/osdep.h"
55
+#include "qemu/osdep.h"
63
+#include "block/block_int.h"
56
+#include "qemu/units.h"
64
+#include "qemu/module.h"
65
+#include "qapi/error.h"
57
+#include "qapi/error.h"
66
+
58
+#include "qemu-common.h"
67
+
59
+#include "exec/memory.h"
68
+static int compress_open(BlockDriverState *bs, QDict *options, int flags,
60
+#include "exec/address-spaces.h"
69
+ Error **errp)
61
+#include "sysemu/sysemu.h"
70
+{
62
+#include "qemu/main-loop.h"
71
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
63
+
72
+ errp);
64
+#include "tests/qtest/libqtest.h"
73
+ if (!bs->file) {
65
+#include "tests/qtest/libqos/malloc.h"
74
+ return -EINVAL;
66
+#include "tests/qtest/libqos/qgraph.h"
67
+#include "tests/qtest/libqos/qgraph_internal.h"
68
+#include "tests/qtest/libqos/qos_external.h"
69
+
70
+#include "fuzz.h"
71
+#include "qos_fuzz.h"
72
+
73
+#include "qapi/qapi-commands-machine.h"
74
+#include "qapi/qapi-commands-qom.h"
75
+#include "qapi/qmp/qlist.h"
76
+
77
+
78
+void *fuzz_qos_obj;
79
+QGuestAllocator *fuzz_qos_alloc;
80
+
81
+static const char *fuzz_target_name;
82
+static char **fuzz_path_vec;
83
+
84
+/*
85
+ * Replaced the qmp commands with direct qmp_marshal calls.
86
+ * Probably there is a better way to do this
87
+ */
88
+static void qos_set_machines_devices_available(void)
89
+{
90
+ QDict *req = qdict_new();
91
+ QObject *response;
92
+ QDict *args = qdict_new();
93
+ QList *lst;
94
+ Error *err = NULL;
95
+
96
+ qmp_marshal_query_machines(NULL, &response, &err);
97
+ assert(!err);
98
+ lst = qobject_to(QList, response);
99
+ apply_to_qlist(lst, true);
100
+
101
+ qobject_unref(response);
102
+
103
+
104
+ qdict_put_str(req, "execute", "qom-list-types");
105
+ qdict_put_str(args, "implements", "device");
106
+ qdict_put_bool(args, "abstract", true);
107
+ qdict_put_obj(req, "arguments", (QObject *) args);
108
+
109
+ qmp_marshal_qom_list_types(args, &response, &err);
110
+ assert(!err);
111
+ lst = qobject_to(QList, response);
112
+ apply_to_qlist(lst, false);
113
+ qobject_unref(response);
114
+ qobject_unref(req);
115
+}
116
+
117
+static char **current_path;
118
+
119
+void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc)
120
+{
121
+ return allocate_objects(qts, current_path + 1, p_alloc);
122
+}
123
+
124
+static const char *qos_build_main_args(void)
125
+{
126
+ char **path = fuzz_path_vec;
127
+ QOSGraphNode *test_node;
128
+ GString *cmd_line = g_string_new(path[0]);
129
+ void *test_arg;
130
+
131
+ if (!path) {
132
+ fprintf(stderr, "QOS Path not found\n");
133
+ abort();
75
+ }
134
+ }
76
+
135
+
77
+ if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) {
136
+ /* Before test */
78
+ error_setg(errp,
137
+ current_path = path;
79
+ "Compression is not supported for underlying format: %s",
138
+ test_node = qos_graph_get_node(path[(g_strv_length(path) - 1)]);
80
+ bdrv_get_format_name(bs->file->bs) ?: "(no format)");
139
+ test_arg = test_node->u.test.arg;
81
+
140
+ if (test_node->u.test.before) {
82
+ return -ENOTSUP;
141
+ test_arg = test_node->u.test.before(cmd_line, test_arg);
83
+ }
142
+ }
84
+
143
+ /* Prepend the arguments that we need */
85
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
144
+ g_string_prepend(cmd_line,
86
+ (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
145
+ TARGET_NAME " -display none -machine accel=qtest -m 64 ");
87
+
146
+ return cmd_line->str;
88
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
147
+}
89
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
148
+
90
+ bs->file->bs->supported_zero_flags);
149
+/*
91
+
150
+ * This function is largely a copy of qos-test.c:walk_path. Since walk_path
92
+ return 0;
151
+ * is itself a callback, its a little annoying to add another argument/layer of
93
+}
152
+ * indirection
94
+
153
+ */
95
+
154
+static void walk_path(QOSGraphNode *orig_path, int len)
96
+static int64_t compress_getlength(BlockDriverState *bs)
155
+{
97
+{
156
+ QOSGraphNode *path;
98
+ return bdrv_getlength(bs->file->bs);
157
+ QOSGraphEdge *edge;
99
+}
158
+
100
+
159
+ /* etype set to QEDGE_CONSUMED_BY so that machine can add to the command line */
101
+
160
+ QOSEdgeType etype = QEDGE_CONSUMED_BY;
102
+static int coroutine_fn compress_co_preadv_part(BlockDriverState *bs,
161
+
103
+ uint64_t offset, uint64_t bytes,
162
+ /* twice QOS_PATH_MAX_ELEMENT_SIZE since each edge can have its arg */
104
+ QEMUIOVector *qiov,
163
+ char **path_vec = g_new0(char *, (QOS_PATH_MAX_ELEMENT_SIZE * 2));
105
+ size_t qiov_offset,
164
+ int path_vec_size = 0;
106
+ int flags)
165
+
107
+{
166
+ char *after_cmd, *before_cmd, *after_device;
108
+ return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
167
+ GString *after_device_str = g_string_new("");
109
+ flags);
168
+ char *node_name = orig_path->name, *path_str;
110
+}
169
+
111
+
170
+ GString *cmd_line = g_string_new("");
112
+
171
+ GString *cmd_line2 = g_string_new("");
113
+static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
172
+
114
+ uint64_t offset,
173
+ path = qos_graph_get_node(node_name); /* root */
115
+ uint64_t bytes,
174
+ node_name = qos_graph_edge_get_dest(path->path_edge); /* machine name */
116
+ QEMUIOVector *qiov,
175
+
117
+ size_t qiov_offset, int flags)
176
+ path_vec[path_vec_size++] = node_name;
118
+{
177
+ path_vec[path_vec_size++] = qos_get_machine_type(node_name);
119
+ return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
178
+
120
+ flags | BDRV_REQ_WRITE_COMPRESSED);
179
+ for (;;) {
121
+}
180
+ path = qos_graph_get_node(node_name);
122
+
181
+ if (!path->path_edge) {
123
+
182
+ break;
124
+static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs,
183
+ }
125
+ int64_t offset, int bytes,
184
+
126
+ BdrvRequestFlags flags)
185
+ node_name = qos_graph_edge_get_dest(path->path_edge);
127
+{
186
+
128
+ return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
187
+ /* append node command line + previous edge command line */
129
+}
188
+ if (path->command_line && etype == QEDGE_CONSUMED_BY) {
130
+
189
+ g_string_append(cmd_line, path->command_line);
131
+
190
+ g_string_append(cmd_line, after_device_str->str);
132
+static int coroutine_fn compress_co_pdiscard(BlockDriverState *bs,
191
+ g_string_truncate(after_device_str, 0);
133
+ int64_t offset, int bytes)
192
+ }
134
+{
193
+
135
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
194
+ path_vec[path_vec_size++] = qos_graph_edge_get_name(path->path_edge);
136
+}
195
+ /* detect if edge has command line args */
137
+
196
+ after_cmd = qos_graph_edge_get_after_cmd_line(path->path_edge);
138
+
197
+ after_device = qos_graph_edge_get_extra_device_opts(path->path_edge);
139
+static void compress_refresh_limits(BlockDriverState *bs, Error **errp)
198
+ before_cmd = qos_graph_edge_get_before_cmd_line(path->path_edge);
140
+{
199
+ edge = qos_graph_get_edge(path->name, node_name);
141
+ BlockDriverInfo bdi;
200
+ etype = qos_graph_edge_get_type(edge);
142
+ int ret;
201
+
143
+
202
+ if (before_cmd) {
144
+ if (!bs->file) {
203
+ g_string_append(cmd_line, before_cmd);
145
+ return;
204
+ }
205
+ if (after_cmd) {
206
+ g_string_append(cmd_line2, after_cmd);
207
+ }
208
+ if (after_device) {
209
+ g_string_append(after_device_str, after_device);
210
+ }
146
+ }
211
+ }
147
+
212
+
148
+ ret = bdrv_get_info(bs->file->bs, &bdi);
213
+ path_vec[path_vec_size++] = NULL;
149
+ if (ret < 0 || bdi.cluster_size == 0) {
214
+ g_string_append(cmd_line, after_device_str->str);
150
+ return;
215
+ g_string_free(after_device_str, true);
216
+
217
+ g_string_append(cmd_line, cmd_line2->str);
218
+ g_string_free(cmd_line2, true);
219
+
220
+ /*
221
+ * here position 0 has <arch>/<machine>, position 1 has <machine>.
222
+ * The path must not have the <arch>, qtest_add_data_func adds it.
223
+ */
224
+ path_str = g_strjoinv("/", path_vec + 1);
225
+
226
+ /* Check that this is the test we care about: */
227
+ char *test_name = strrchr(path_str, '/') + 1;
228
+ if (strcmp(test_name, fuzz_target_name) == 0) {
229
+ /*
230
+ * put arch/machine in position 1 so run_one_test can do its work
231
+ * and add the command line at position 0.
232
+ */
233
+ path_vec[1] = path_vec[0];
234
+ path_vec[0] = g_string_free(cmd_line, false);
235
+
236
+ fuzz_path_vec = path_vec;
237
+ } else {
238
+ g_free(path_vec);
151
+ }
239
+ }
152
+
240
+
153
+ bs->bl.request_alignment = bdi.cluster_size;
241
+ g_free(path_str);
154
+}
242
+}
155
+
243
+
156
+
244
+static const char *qos_get_cmdline(FuzzTarget *t)
157
+static void compress_eject(BlockDriverState *bs, bool eject_flag)
245
+{
158
+{
246
+ /*
159
+ bdrv_eject(bs->file->bs, eject_flag);
247
+ * Set a global variable that we use to identify the qos_path for our
160
+}
248
+ * fuzz_target
161
+
249
+ */
162
+
250
+ fuzz_target_name = t->name;
163
+static void compress_lock_medium(BlockDriverState *bs, bool locked)
251
+ qos_set_machines_devices_available();
164
+{
252
+ qos_graph_foreach_test_path(walk_path);
165
+ bdrv_lock_medium(bs->file->bs, locked);
253
+ return qos_build_main_args();
166
+}
254
+}
167
+
255
+
168
+
256
+void fuzz_add_qos_target(
169
+static bool compress_recurse_is_first_non_filter(BlockDriverState *bs,
257
+ FuzzTarget *fuzz_opts,
170
+ BlockDriverState *candidate)
258
+ const char *interface,
171
+{
259
+ QOSGraphTestOptions *opts
172
+ return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
260
+ )
173
+}
261
+{
174
+
262
+ qos_add_test(fuzz_opts->name, interface, NULL, opts);
175
+
263
+ fuzz_opts->get_init_cmdline = qos_get_cmdline;
176
+static BlockDriver bdrv_compress = {
264
+ fuzz_add_target(fuzz_opts);
177
+ .format_name = "compress",
265
+}
178
+
266
+
179
+ .bdrv_open = compress_open,
267
+void qos_init_path(QTestState *s)
180
+ .bdrv_child_perm = bdrv_filter_default_perms,
268
+{
181
+
269
+ fuzz_qos_obj = qos_allocate_objects(s , &fuzz_qos_alloc);
182
+ .bdrv_getlength = compress_getlength,
270
+}
183
+
271
diff --git a/tests/qtest/fuzz/qos_fuzz.h b/tests/qtest/fuzz/qos_fuzz.h
184
+ .bdrv_co_preadv_part = compress_co_preadv_part,
272
new file mode 100644
185
+ .bdrv_co_pwritev_part = compress_co_pwritev_part,
273
index XXXXXXX..XXXXXXX
186
+ .bdrv_co_pwrite_zeroes = compress_co_pwrite_zeroes,
274
--- /dev/null
187
+ .bdrv_co_pdiscard = compress_co_pdiscard,
275
+++ b/tests/qtest/fuzz/qos_fuzz.h
188
+ .bdrv_refresh_limits = compress_refresh_limits,
189
+
190
+ .bdrv_eject = compress_eject,
191
+ .bdrv_lock_medium = compress_lock_medium,
192
+
193
+ .bdrv_co_block_status = bdrv_co_block_status_from_file,
194
+
195
+ .bdrv_recurse_is_first_non_filter = compress_recurse_is_first_non_filter,
196
+
197
+ .has_variable_length = true,
198
+ .is_filter = true,
199
+};
200
+
201
+static void bdrv_compress_init(void)
202
+{
203
+ bdrv_register(&bdrv_compress);
204
+}
205
+
206
+block_init(bdrv_compress_init);
207
diff --git a/qapi/block-core.json b/qapi/block-core.json
208
index XXXXXXX..XXXXXXX 100644
209
--- a/qapi/block-core.json
210
+++ b/qapi/block-core.json
211
@@ -XXX,XX +XXX,XX @@
276
@@ -XXX,XX +XXX,XX @@
212
# @copy-on-read: Since 3.0
277
+/*
213
# @blklogwrites: Since 3.0
278
+ * QOS-assisted fuzzing helpers
214
# @blkreplay: Since 4.2
279
+ *
215
+# @compress: Since 5.0
280
+ * Copyright Red Hat Inc., 2019
216
#
281
+ *
217
# Since: 2.9
282
+ * Authors:
218
##
283
+ * Alexander Bulekov <alxndr@bu.edu>
219
{ 'enum': 'BlockdevDriver',
284
+ *
220
'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
285
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
221
- 'cloop', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
286
+ * See the COPYING file in the top-level directory.
222
- 'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks',
287
+ */
223
- 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow',
288
+
224
- 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
289
+#ifndef _QOS_FUZZ_H_
225
+ 'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps',
290
+#define _QOS_FUZZ_H_
226
+ 'gluster', 'host_cdrom', 'host_device', 'http', 'https', 'iscsi',
291
+
227
+ 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels',
292
+#include "tests/qtest/fuzz/fuzz.h"
228
+ 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
293
+#include "tests/qtest/libqos/qgraph.h"
229
{ 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
294
+
230
'sheepdog',
295
+int qos_fuzz(const unsigned char *Data, size_t Size);
231
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
296
+void qos_setup(void);
232
@@ -XXX,XX +XXX,XX @@
297
+
233
'blkreplay': 'BlockdevOptionsBlkreplay',
298
+extern void *fuzz_qos_obj;
234
'bochs': 'BlockdevOptionsGenericFormat',
299
+extern QGuestAllocator *fuzz_qos_alloc;
235
'cloop': 'BlockdevOptionsGenericFormat',
300
+
236
+ 'compress': 'BlockdevOptionsGenericFormat',
301
+void fuzz_add_qos_target(
237
'copy-on-read':'BlockdevOptionsGenericFormat',
302
+ FuzzTarget *fuzz_opts,
238
'dmg': 'BlockdevOptionsGenericFormat',
303
+ const char *interface,
239
'file': 'BlockdevOptionsFile',
304
+ QOSGraphTestOptions *opts
305
+ );
306
+
307
+void qos_init_path(QTestState *);
308
+
309
+#endif
240
--
310
--
241
2.24.1
311
2.24.1
242
312
243
diff view generated by jsdifflib
1
IMGOPTS can never be empty for qcow2, because the check scripts adds
1
From: Alexander Bulekov <alxndr@bu.edu>
2
compat=1.1 unless the user specified any compat option themselves.
3
Thus, this block does not do anything and can be dropped.
4
2
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
6
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
7
Message-id: 20191107163708.833192-8-mreitz@redhat.com
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Message-id: 20200220041118.23264-18-alxndr@bu.edu
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
8
---
10
tests/qemu-iotests/050 | 4 ----
9
Makefile | 15 ++++++++++++++-
11
1 file changed, 4 deletions(-)
10
Makefile.target | 16 ++++++++++++++++
11
2 files changed, 30 insertions(+), 1 deletion(-)
12
12
13
diff --git a/tests/qemu-iotests/050 b/tests/qemu-iotests/050
13
diff --git a/Makefile b/Makefile
14
index XXXXXXX..XXXXXXX 100755
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/050
15
--- a/Makefile
16
+++ b/tests/qemu-iotests/050
16
+++ b/Makefile
17
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
17
@@ -XXX,XX +XXX,XX @@ config-host.h-timestamp: config-host.mak
18
_supported_fmt qcow2 qed
18
qemu-options.def: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
19
_supported_proto file
19
    $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$@")
20
20
21
-if test "$IMGFMT" = qcow2 && test $IMGOPTS = ""; then
21
-TARGET_DIRS_RULES := $(foreach t, all clean install, $(addsuffix /$(t), $(TARGET_DIRS)))
22
- IMGOPTS=compat=1.1
22
+TARGET_DIRS_RULES := $(foreach t, all fuzz clean install, $(addsuffix /$(t), $(TARGET_DIRS)))
23
-fi
23
24
-
24
SOFTMMU_ALL_RULES=$(filter %-softmmu/all, $(TARGET_DIRS_RULES))
25
echo
25
$(SOFTMMU_ALL_RULES): $(authz-obj-y)
26
echo "== Creating images =="
26
@@ -XXX,XX +XXX,XX @@ ifdef DECOMPRESS_EDK2_BLOBS
27
27
$(SOFTMMU_ALL_RULES): $(edk2-decompressed)
28
endif
29
30
+SOFTMMU_FUZZ_RULES=$(filter %-softmmu/fuzz, $(TARGET_DIRS_RULES))
31
+$(SOFTMMU_FUZZ_RULES): $(authz-obj-y)
32
+$(SOFTMMU_FUZZ_RULES): $(block-obj-y)
33
+$(SOFTMMU_FUZZ_RULES): $(chardev-obj-y)
34
+$(SOFTMMU_FUZZ_RULES): $(crypto-obj-y)
35
+$(SOFTMMU_FUZZ_RULES): $(io-obj-y)
36
+$(SOFTMMU_FUZZ_RULES): config-all-devices.mak
37
+$(SOFTMMU_FUZZ_RULES): $(edk2-decompressed)
38
+
39
.PHONY: $(TARGET_DIRS_RULES)
40
# The $(TARGET_DIRS_RULES) are of the form SUBDIR/GOAL, so that
41
# $(dir $@) yields the sub-directory, and $(notdir $@) yields the sub-goal
42
@@ -XXX,XX +XXX,XX @@ subdir-slirp: slirp/all
43
$(filter %/all, $(TARGET_DIRS_RULES)): libqemuutil.a $(common-obj-y) \
44
    $(qom-obj-y)
45
46
+$(filter %/fuzz, $(TARGET_DIRS_RULES)): libqemuutil.a $(common-obj-y) \
47
+    $(qom-obj-y) $(crypto-user-obj-$(CONFIG_USER_ONLY))
48
+
49
ROM_DIRS = $(addprefix pc-bios/, $(ROMS))
50
ROM_DIRS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROM_DIRS)))
51
# Only keep -O and -g cflags
52
@@ -XXX,XX +XXX,XX @@ $(ROM_DIRS_RULES):
53
54
.PHONY: recurse-all recurse-clean recurse-install
55
recurse-all: $(addsuffix /all, $(TARGET_DIRS) $(ROM_DIRS))
56
+recurse-fuzz: $(addsuffix /fuzz, $(TARGET_DIRS) $(ROM_DIRS))
57
recurse-clean: $(addsuffix /clean, $(TARGET_DIRS) $(ROM_DIRS))
58
recurse-install: $(addsuffix /install, $(TARGET_DIRS))
59
$(addsuffix /install, $(TARGET_DIRS)): all
60
diff --git a/Makefile.target b/Makefile.target
61
index XXXXXXX..XXXXXXX 100644
62
--- a/Makefile.target
63
+++ b/Makefile.target
64
@@ -XXX,XX +XXX,XX @@ ifdef CONFIG_TRACE_SYSTEMTAP
65
    rm -f *.stp
66
endif
67
68
+ifdef CONFIG_FUZZ
69
+include $(SRC_PATH)/tests/qtest/fuzz/Makefile.include
70
+include $(SRC_PATH)/tests/qtest/Makefile.include
71
+
72
+fuzz: fuzz-vars
73
+fuzz-vars: QEMU_CFLAGS := $(FUZZ_CFLAGS) $(QEMU_CFLAGS)
74
+fuzz-vars: QEMU_LDFLAGS := $(FUZZ_LDFLAGS) $(QEMU_LDFLAGS)
75
+fuzz-vars: $(QEMU_PROG_FUZZ)
76
+dummy := $(call unnest-vars,, fuzz-obj-y)
77
+
78
+
79
+$(QEMU_PROG_FUZZ): config-devices.mak $(all-obj-y) $(COMMON_LDADDS) $(fuzz-obj-y)
80
+    $(call LINK, $(filter-out %.mak, $^))
81
+
82
+endif
83
+
84
install: all
85
ifneq ($(PROGS),)
86
    $(call install-prog,$(PROGS),$(DESTDIR)$(bindir))
28
--
87
--
29
2.24.1
88
2.24.1
30
89
31
diff view generated by jsdifflib
1
We need some way to correlate QAPI BlockPermission values with
1
From: Alexander Bulekov <alxndr@bu.edu>
2
BLK_PERM_* flags. We could:
3
2
4
(1) have the same order in the QAPI definition as the the BLK_PERM_*
3
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
5
flags are in LSb-first order. However, then there is no guarantee
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
that they actually match (e.g. when someone modifies the QAPI schema
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
without thinking of the BLK_PERM_* definitions).
6
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
8
We could add static assertions, but these would break what’s good
7
Message-id: 20200220041118.23264-19-alxndr@bu.edu
9
about this solution, namely its simplicity.
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
configure | 39 +++++++++++++++++++++++++++++++++++++++
11
1 file changed, 39 insertions(+)
10
12
11
(2) define the BLK_PERM_* flags based on the BlockPermission values.
13
diff --git a/configure b/configure
12
But this way whenever someone were to modify the QAPI order
14
index XXXXXXX..XXXXXXX 100755
13
(perfectly sensible in theory), the BLK_PERM_* values would change.
15
--- a/configure
14
Because these values are used for file locking, this might break
16
+++ b/configure
15
file locking between different qemu versions.
17
@@ -XXX,XX +XXX,XX @@ debug_mutex="no"
16
18
libpmem=""
17
Therefore, go the slightly more cumbersome way: Add a function to
19
default_devices="yes"
18
translate from the QAPI constants to the BLK_PERM_* flags.
20
plugins="no"
19
21
+fuzzing="no"
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
21
Message-id: 20191108123455.39445-2-mreitz@redhat.com
23
supported_cpu="no"
22
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
24
supported_os="no"
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
@@ -XXX,XX +XXX,XX @@ int main(void) { return 0; }
24
---
26
EOF
25
block.c | 18 ++++++++++++++++++
26
include/block/block.h | 1 +
27
2 files changed, 19 insertions(+)
28
29
diff --git a/block.c b/block.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block.c
32
+++ b/block.c
33
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
34
*nshared = shared;
35
}
27
}
36
28
37
+uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
29
+write_c_fuzzer_skeleton() {
38
+{
30
+ cat > $TMPC <<EOF
39
+ static const uint64_t permissions[] = {
31
+#include <stdint.h>
40
+ [BLOCK_PERMISSION_CONSISTENT_READ] = BLK_PERM_CONSISTENT_READ,
32
+#include <sys/types.h>
41
+ [BLOCK_PERMISSION_WRITE] = BLK_PERM_WRITE,
33
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
42
+ [BLOCK_PERMISSION_WRITE_UNCHANGED] = BLK_PERM_WRITE_UNCHANGED,
34
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; }
43
+ [BLOCK_PERMISSION_RESIZE] = BLK_PERM_RESIZE,
35
+EOF
44
+ [BLOCK_PERMISSION_GRAPH_MOD] = BLK_PERM_GRAPH_MOD,
45
+ };
46
+
47
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(permissions) != BLOCK_PERMISSION__MAX);
48
+ QEMU_BUILD_BUG_ON(1UL << ARRAY_SIZE(permissions) != BLK_PERM_ALL + 1);
49
+
50
+ assert(qapi_perm < BLOCK_PERMISSION__MAX);
51
+
52
+ return permissions[qapi_perm];
53
+}
36
+}
54
+
37
+
55
static void bdrv_replace_child_noperm(BdrvChild *child,
38
if check_define __linux__ ; then
56
BlockDriverState *new_bs)
39
targetos="Linux"
57
{
40
elif check_define _WIN32 ; then
58
diff --git a/include/block/block.h b/include/block/block.h
41
@@ -XXX,XX +XXX,XX @@ for opt do
59
index XXXXXXX..XXXXXXX 100644
42
;;
60
--- a/include/block/block.h
43
--disable-containers) use_containers="no"
61
+++ b/include/block/block.h
44
;;
62
@@ -XXX,XX +XXX,XX @@ enum {
45
+ --enable-fuzzing) fuzzing=yes
63
};
46
+ ;;
64
47
+ --disable-fuzzing) fuzzing=no
65
char *bdrv_perm_names(uint64_t perm);
48
+ ;;
66
+uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm);
49
*)
67
50
echo "ERROR: unknown option $opt"
68
/* disk I/O throttling */
51
echo "Try '$0 --help' for more information"
69
void bdrv_init(void);
52
@@ -XXX,XX +XXX,XX @@ EOF
53
fi
54
fi
55
56
+##########################################
57
+# checks for fuzzer
58
+if test "$fuzzing" = "yes" ; then
59
+ write_c_fuzzer_skeleton
60
+ if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address,fuzzer" ""; then
61
+ have_fuzzer=yes
62
+ fi
63
+fi
64
+
65
##########################################
66
# check for libpmem
67
68
@@ -XXX,XX +XXX,XX @@ echo "libpmem support $libpmem"
69
echo "libudev $libudev"
70
echo "default devices $default_devices"
71
echo "plugin support $plugins"
72
+echo "fuzzing support $fuzzing"
73
74
if test "$supported_cpu" = "no"; then
75
echo
76
@@ -XXX,XX +XXX,XX @@ fi
77
if test "$sheepdog" = "yes" ; then
78
echo "CONFIG_SHEEPDOG=y" >> $config_host_mak
79
fi
80
+if test "$fuzzing" = "yes" ; then
81
+ if test "$have_fuzzer" = "yes"; then
82
+ FUZZ_LDFLAGS=" -fsanitize=address,fuzzer"
83
+ FUZZ_CFLAGS=" -fsanitize=address,fuzzer"
84
+ CFLAGS=" -fsanitize=address,fuzzer-no-link"
85
+ else
86
+ error_exit "Your compiler doesn't support -fsanitize=address,fuzzer"
87
+ exit 1
88
+ fi
89
+fi
90
91
if test "$plugins" = "yes" ; then
92
echo "CONFIG_PLUGIN=y" >> $config_host_mak
93
@@ -XXX,XX +XXX,XX @@ if test "$libudev" != "no"; then
94
echo "CONFIG_LIBUDEV=y" >> $config_host_mak
95
echo "LIBUDEV_LIBS=$libudev_libs" >> $config_host_mak
96
fi
97
+if test "$fuzzing" != "no"; then
98
+ echo "CONFIG_FUZZ=y" >> $config_host_mak
99
+ echo "FUZZ_CFLAGS=$FUZZ_CFLAGS" >> $config_host_mak
100
+ echo "FUZZ_LDFLAGS=$FUZZ_LDFLAGS" >> $config_host_mak
101
+fi
102
103
if test "$edk2_blobs" = "yes" ; then
104
echo "DECOMPRESS_EDK2_BLOBS=y" >> $config_host_mak
70
--
105
--
71
2.24.1
106
2.24.1
72
107
73
diff view generated by jsdifflib
Deleted patch
1
Callers can use this new parameter to expect failure during the
2
completion process.
3
1
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-id: 20191108123455.39445-5-mreitz@redhat.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/iotests.py | 18 ++++++++++++------
11
1 file changed, 12 insertions(+), 6 deletions(-)
12
13
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/iotests.py
16
+++ b/tests/qemu-iotests/iotests.py
17
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
18
self.assert_no_active_block_jobs()
19
return result
20
21
- def wait_until_completed(self, drive='drive0', check_offset=True, wait=60.0):
22
+ def wait_until_completed(self, drive='drive0', check_offset=True, wait=60.0,
23
+ error=None):
24
'''Wait for a block job to finish, returning the event'''
25
while True:
26
for event in self.vm.get_qmp_events(wait=wait):
27
if event['event'] == 'BLOCK_JOB_COMPLETED':
28
self.assert_qmp(event, 'data/device', drive)
29
- self.assert_qmp_absent(event, 'data/error')
30
- if check_offset:
31
- self.assert_qmp(event, 'data/offset', event['data']['len'])
32
+ if error is None:
33
+ self.assert_qmp_absent(event, 'data/error')
34
+ if check_offset:
35
+ self.assert_qmp(event, 'data/offset',
36
+ event['data']['len'])
37
+ else:
38
+ self.assert_qmp(event, 'data/error', error)
39
self.assert_no_active_block_jobs()
40
return event
41
elif event['event'] == 'JOB_STATUS_CHANGE':
42
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
43
self.assert_qmp(event, 'data/type', 'mirror')
44
self.assert_qmp(event, 'data/offset', event['data']['len'])
45
46
- def complete_and_wait(self, drive='drive0', wait_ready=True):
47
+ def complete_and_wait(self, drive='drive0', wait_ready=True,
48
+ completion_error=None):
49
'''Complete a block job and wait for it to finish'''
50
if wait_ready:
51
self.wait_ready(drive=drive)
52
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
53
result = self.vm.qmp('block-job-complete', device=drive)
54
self.assert_qmp(result, 'return', {})
55
56
- event = self.wait_until_completed(drive=drive)
57
+ event = self.wait_until_completed(drive=drive, error=completion_error)
58
self.assert_qmp(event, 'data/type', 'mirror')
59
60
def pause_wait(self, job_id='job0'):
61
--
62
2.24.1
63
64
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
2
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
3
Tested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Reviewed-by: John Snow <jsnow@redhat.com>
5
Message-id: 20191108123455.39445-6-mreitz@redhat.com
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/041 | 44 ++++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/041.out | 4 ++--
10
2 files changed, 46 insertions(+), 2 deletions(-)
11
1
12
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/041
15
+++ b/tests/qemu-iotests/041
16
@@ -XXX,XX +XXX,XX @@ class TestOrphanedSource(iotests.QMPTestCase):
17
target='dest-ro')
18
self.assert_qmp(result, 'error/class', 'GenericError')
19
20
+ def test_failing_permission_in_complete(self):
21
+ self.assert_no_active_block_jobs()
22
+
23
+ # Unshare consistent-read on the target
24
+ # (The mirror job does not care)
25
+ result = self.vm.qmp('blockdev-add',
26
+ driver='blkdebug',
27
+ node_name='dest-perm',
28
+ image='dest',
29
+ unshare_child_perms=['consistent-read'])
30
+ self.assert_qmp(result, 'return', {})
31
+
32
+ result = self.vm.qmp('blockdev-mirror', job_id='job', device='src',
33
+ sync='full', target='dest',
34
+ filter_node_name='mirror-filter')
35
+ self.assert_qmp(result, 'return', {})
36
+
37
+ # Require consistent-read on the source
38
+ # (We can only add this node once the job has started, or it
39
+ # will complain that it does not want to run on non-root nodes)
40
+ result = self.vm.qmp('blockdev-add',
41
+ driver='blkdebug',
42
+ node_name='src-perm',
43
+ image='src',
44
+ take_child_perms=['consistent-read'])
45
+ self.assert_qmp(result, 'return', {})
46
+
47
+ # While completing, mirror will attempt to replace src by
48
+ # dest, which must fail because src-perm requires
49
+ # consistent-read but dest-perm does not share it; thus
50
+ # aborting the job when it is supposed to complete
51
+ self.complete_and_wait('job',
52
+ completion_error='Operation not permitted')
53
+
54
+ # Assert that all of our nodes are still there (except for the
55
+ # mirror filter, which should be gone despite the failure)
56
+ nodes = self.vm.qmp('query-named-block-nodes')['return']
57
+ nodes = [node['node-name'] for node in nodes]
58
+
59
+ for expect in ('src', 'src-perm', 'dest', 'dest-perm'):
60
+ self.assertTrue(expect in nodes, '%s disappeared' % expect)
61
+ self.assertFalse('mirror-filter' in nodes,
62
+ 'Mirror filter node did not disappear')
63
+
64
if __name__ == '__main__':
65
iotests.main(supported_fmts=['qcow2', 'qed'],
66
supported_protocols=['file'])
67
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
68
index XXXXXXX..XXXXXXX 100644
69
--- a/tests/qemu-iotests/041.out
70
+++ b/tests/qemu-iotests/041.out
71
@@ -XXX,XX +XXX,XX @@
72
-..........................................................................................
73
+...........................................................................................
74
----------------------------------------------------------------------
75
-Ran 90 tests
76
+Ran 91 tests
77
78
OK
79
--
80
2.24.1
81
82
diff view generated by jsdifflib
Deleted patch
1
Probably due to blind copy-pasting, we have several instances of "qocw2"
2
in our iotests. Fix them.
3
1
4
Reported-by: Maxim Levitsky <mlevitsk@redhat.com>
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Message-id: 20191107163708.833192-2-mreitz@redhat.com
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/060 | 2 +-
12
tests/qemu-iotests/061 | 2 +-
13
tests/qemu-iotests/062 | 2 +-
14
tests/qemu-iotests/066 | 2 +-
15
tests/qemu-iotests/068 | 2 +-
16
tests/qemu-iotests/108 | 2 +-
17
tests/qemu-iotests/138 | 2 +-
18
tests/qemu-iotests/261 | 2 +-
19
8 files changed, 8 insertions(+), 8 deletions(-)
20
21
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
22
index XXXXXXX..XXXXXXX 100755
23
--- a/tests/qemu-iotests/060
24
+++ b/tests/qemu-iotests/060
25
@@ -XXX,XX +XXX,XX @@ _filter_io_error()
26
. ./common.rc
27
. ./common.filter
28
29
-# This tests qocw2-specific low-level functionality
30
+# This tests qcow2-specific low-level functionality
31
_supported_fmt qcow2
32
_supported_proto file
33
_supported_os Linux
34
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
35
index XXXXXXX..XXXXXXX 100755
36
--- a/tests/qemu-iotests/061
37
+++ b/tests/qemu-iotests/061
38
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
39
. ./common.rc
40
. ./common.filter
41
42
-# This tests qocw2-specific low-level functionality
43
+# This tests qcow2-specific low-level functionality
44
_supported_fmt qcow2
45
_supported_proto file
46
_supported_os Linux
47
diff --git a/tests/qemu-iotests/062 b/tests/qemu-iotests/062
48
index XXXXXXX..XXXXXXX 100755
49
--- a/tests/qemu-iotests/062
50
+++ b/tests/qemu-iotests/062
51
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
52
. ./common.rc
53
. ./common.filter
54
55
-# This tests qocw2-specific low-level functionality
56
+# This tests qcow2-specific low-level functionality
57
_supported_fmt qcow2
58
_supported_proto generic
59
60
diff --git a/tests/qemu-iotests/066 b/tests/qemu-iotests/066
61
index XXXXXXX..XXXXXXX 100755
62
--- a/tests/qemu-iotests/066
63
+++ b/tests/qemu-iotests/066
64
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
65
. ./common.rc
66
. ./common.filter
67
68
-# This tests qocw2-specific low-level functionality
69
+# This tests qcow2-specific low-level functionality
70
_supported_fmt qcow2
71
_supported_proto generic
72
73
diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068
74
index XXXXXXX..XXXXXXX 100755
75
--- a/tests/qemu-iotests/068
76
+++ b/tests/qemu-iotests/068
77
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
78
. ./common.rc
79
. ./common.filter
80
81
-# This tests qocw2-specific low-level functionality
82
+# This tests qcow2-specific low-level functionality
83
_supported_fmt qcow2
84
_supported_proto generic
85
86
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
87
index XXXXXXX..XXXXXXX 100755
88
--- a/tests/qemu-iotests/108
89
+++ b/tests/qemu-iotests/108
90
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
91
. ./common.rc
92
. ./common.filter
93
94
-# This tests qocw2-specific low-level functionality
95
+# This tests qcow2-specific low-level functionality
96
_supported_fmt qcow2
97
_supported_proto file
98
_supported_os Linux
99
diff --git a/tests/qemu-iotests/138 b/tests/qemu-iotests/138
100
index XXXXXXX..XXXXXXX 100755
101
--- a/tests/qemu-iotests/138
102
+++ b/tests/qemu-iotests/138
103
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
104
. ./common.rc
105
. ./common.filter
106
107
-# This tests qocw2-specific low-level functionality
108
+# This tests qcow2-specific low-level functionality
109
_supported_fmt qcow2
110
_supported_proto file
111
_supported_os Linux
112
diff --git a/tests/qemu-iotests/261 b/tests/qemu-iotests/261
113
index XXXXXXX..XXXXXXX 100755
114
--- a/tests/qemu-iotests/261
115
+++ b/tests/qemu-iotests/261
116
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
117
. ./common.rc
118
. ./common.filter
119
120
-# This tests qocw2-specific low-level functionality
121
+# This tests qcow2-specific low-level functionality
122
_supported_fmt qcow2
123
_supported_proto file
124
_supported_os Linux
125
--
126
2.24.1
127
128
diff view generated by jsdifflib
1
Some tests require compat=1.1 and thus set IMGOPTS='compat=1.1'
1
From: Alexander Bulekov <alxndr@bu.edu>
2
globally. That is not how it should be done; instead, they should
2
3
simply set _unsupported_imgopts to compat=0.10 (compat=1.1 is the
3
These three targets should simply fuzz reads/writes to a couple ioports,
4
default anyway).
4
but they mostly serve as examples of different ways to write targets.
5
5
They demonstrate using qtest and qos for fuzzing, as well as using
6
This makes the tests heed user-specified $IMGOPTS. Some do not work
6
rebooting and forking to reset state, or not resetting it at all.
7
with all image options, though, so we need to disable them accordingly.
7
8
8
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Maxim Levitsky <mlevitsky@redhat.com>
10
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
11
Message-id: 20191107163708.833192-7-mreitz@redhat.com
11
Message-id: 20200220041118.23264-20-alxndr@bu.edu
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
13
---
14
tests/qemu-iotests/036 | 3 +--
14
tests/qtest/fuzz/Makefile.include | 3 +
15
tests/qemu-iotests/060 | 4 ++--
15
tests/qtest/fuzz/i440fx_fuzz.c | 193 ++++++++++++++++++++++++++++++
16
tests/qemu-iotests/062 | 3 ++-
16
2 files changed, 196 insertions(+)
17
tests/qemu-iotests/066 | 3 ++-
17
create mode 100644 tests/qtest/fuzz/i440fx_fuzz.c
18
tests/qemu-iotests/068 | 3 ++-
18
19
tests/qemu-iotests/098 | 4 ++--
19
diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include
20
6 files changed, 11 insertions(+), 9 deletions(-)
20
index XXXXXXX..XXXXXXX 100644
21
21
--- a/tests/qtest/fuzz/Makefile.include
22
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
22
+++ b/tests/qtest/fuzz/Makefile.include
23
index XXXXXXX..XXXXXXX 100755
23
@@ -XXX,XX +XXX,XX @@ fuzz-obj-y += tests/qtest/fuzz/fuzz.o # Fuzzer skeleton
24
--- a/tests/qemu-iotests/036
24
fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o
25
+++ b/tests/qemu-iotests/036
25
fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
26
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
26
27
# This tests qcow2-specific low-level functionality
27
+# Targets
28
_supported_fmt qcow2
28
+fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o
29
_supported_proto file
29
+
30
-
30
FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
31
# Only qcow2v3 and later supports feature bits
31
32
-IMGOPTS="compat=1.1"
32
# Linker Script to force coverage-counters into known regions which we can mark
33
+_unsupported_imgopts 'compat=0.10'
33
diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c
34
34
new file mode 100644
35
echo
35
index XXXXXXX..XXXXXXX
36
echo === Image with unknown incompatible feature bit ===
36
--- /dev/null
37
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
37
+++ b/tests/qtest/fuzz/i440fx_fuzz.c
38
index XXXXXXX..XXXXXXX 100755
38
@@ -XXX,XX +XXX,XX @@
39
--- a/tests/qemu-iotests/060
39
+/*
40
+++ b/tests/qemu-iotests/060
40
+ * I440FX Fuzzing Target
41
@@ -XXX,XX +XXX,XX @@ _filter_io_error()
41
+ *
42
_supported_fmt qcow2
42
+ * Copyright Red Hat Inc., 2019
43
_supported_proto file
43
+ *
44
_supported_os Linux
44
+ * Authors:
45
+# These tests only work for compat=1.1 images with refcount_bits=16
45
+ * Alexander Bulekov <alxndr@bu.edu>
46
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
46
+ *
47
47
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
48
# The repair process will create a large file - so check for availability first
48
+ * See the COPYING file in the top-level directory.
49
_require_large_file 64G
49
+ */
50
@@ -XXX,XX +XXX,XX @@ l1_offset=196608 # 0x30000 (XXX: just an assumption)
50
+
51
l2_offset=262144 # 0x40000 (XXX: just an assumption)
51
+#include "qemu/osdep.h"
52
l2_offset_after_snapshot=524288 # 0x80000 (XXX: just an assumption)
52
+
53
53
+#include "qemu/main-loop.h"
54
-IMGOPTS="compat=1.1"
54
+#include "tests/qtest/libqtest.h"
55
-
55
+#include "tests/qtest/libqos/pci.h"
56
OPEN_RW="open -o overlap-check=all $TEST_IMG"
56
+#include "tests/qtest/libqos/pci-pc.h"
57
# Overlap checks are done before write operations only, therefore opening an
57
+#include "fuzz.h"
58
# image read-only makes the overlap-check option irrelevant
58
+#include "fuzz/qos_fuzz.h"
59
diff --git a/tests/qemu-iotests/062 b/tests/qemu-iotests/062
59
+#include "fuzz/fork_fuzz.h"
60
index XXXXXXX..XXXXXXX 100755
60
+
61
--- a/tests/qemu-iotests/062
61
+
62
+++ b/tests/qemu-iotests/062
62
+#define I440FX_PCI_HOST_BRIDGE_CFG 0xcf8
63
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
63
+#define I440FX_PCI_HOST_BRIDGE_DATA 0xcfc
64
# This tests qcow2-specific low-level functionality
64
+
65
_supported_fmt qcow2
65
+/*
66
_supported_proto generic
66
+ * the input to the fuzzing functions below is a buffer of random bytes. we
67
+# We need zero clusters and snapshots
67
+ * want to convert these bytes into a sequence of qtest or qos calls. to do
68
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
68
+ * this we define some opcodes:
69
69
+ */
70
-IMGOPTS="compat=1.1"
70
+enum action_id {
71
IMG_SIZE=64M
71
+ WRITEB,
72
72
+ WRITEW,
73
echo
73
+ WRITEL,
74
diff --git a/tests/qemu-iotests/066 b/tests/qemu-iotests/066
74
+ READB,
75
index XXXXXXX..XXXXXXX 100755
75
+ READW,
76
--- a/tests/qemu-iotests/066
76
+ READL,
77
+++ b/tests/qemu-iotests/066
77
+ ACTION_MAX
78
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
78
+};
79
# This tests qcow2-specific low-level functionality
79
+
80
_supported_fmt qcow2
80
+static void i440fx_fuzz_qtest(QTestState *s,
81
_supported_proto generic
81
+ const unsigned char *Data, size_t Size) {
82
+# We need zero clusters and snapshots
82
+ /*
83
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
83
+ * loop over the Data, breaking it up into actions. each action has an
84
84
+ * opcode, address offset and value
85
# Intentionally create an unaligned image
85
+ */
86
-IMGOPTS="compat=1.1"
86
+ typedef struct QTestFuzzAction {
87
IMG_SIZE=$((64 * 1024 * 1024 + 512))
87
+ uint8_t opcode;
88
88
+ uint8_t addr;
89
echo
89
+ uint32_t value;
90
diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068
90
+ } QTestFuzzAction;
91
index XXXXXXX..XXXXXXX 100755
91
+ QTestFuzzAction a;
92
--- a/tests/qemu-iotests/068
92
+
93
+++ b/tests/qemu-iotests/068
93
+ while (Size >= sizeof(a)) {
94
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
94
+ /* make a copy of the action so we can normalize the values in-place */
95
# This tests qcow2-specific low-level functionality
95
+ memcpy(&a, Data, sizeof(a));
96
_supported_fmt qcow2
96
+ /* select between two i440fx Port IO addresses */
97
_supported_proto generic
97
+ uint16_t addr = a.addr % 2 ? I440FX_PCI_HOST_BRIDGE_CFG :
98
+# Internal snapshots are (currently) impossible with refcount_bits=1
98
+ I440FX_PCI_HOST_BRIDGE_DATA;
99
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
99
+ switch (a.opcode % ACTION_MAX) {
100
100
+ case WRITEB:
101
-IMGOPTS="compat=1.1"
101
+ qtest_outb(s, addr, (uint8_t)a.value);
102
IMG_SIZE=128K
102
+ break;
103
103
+ case WRITEW:
104
case "$QEMU_DEFAULT_MACHINE" in
104
+ qtest_outw(s, addr, (uint16_t)a.value);
105
diff --git a/tests/qemu-iotests/098 b/tests/qemu-iotests/098
105
+ break;
106
index XXXXXXX..XXXXXXX 100755
106
+ case WRITEL:
107
--- a/tests/qemu-iotests/098
107
+ qtest_outl(s, addr, (uint32_t)a.value);
108
+++ b/tests/qemu-iotests/098
108
+ break;
109
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
109
+ case READB:
110
110
+ qtest_inb(s, addr);
111
_supported_fmt qcow2
111
+ break;
112
_supported_proto file
112
+ case READW:
113
-
113
+ qtest_inw(s, addr);
114
-IMGOPTS="compat=1.1"
114
+ break;
115
+# The code path we want to test here only works for compat=1.1 images
115
+ case READL:
116
+_unsupported_imgopts 'compat=0.10'
116
+ qtest_inl(s, addr);
117
117
+ break;
118
for event in l1_update empty_image_prepare reftable_update refblock_alloc; do
118
+ }
119
119
+ /* Move to the next operation */
120
+ Size -= sizeof(a);
121
+ Data += sizeof(a);
122
+ }
123
+ flush_events(s);
124
+}
125
+
126
+static void i440fx_fuzz_qos(QTestState *s,
127
+ const unsigned char *Data, size_t Size) {
128
+ /*
129
+ * Same as i440fx_fuzz_qtest, but using QOS. devfn is incorporated into the
130
+ * value written over Port IO
131
+ */
132
+ typedef struct QOSFuzzAction {
133
+ uint8_t opcode;
134
+ uint8_t offset;
135
+ int devfn;
136
+ uint32_t value;
137
+ } QOSFuzzAction;
138
+
139
+ static QPCIBus *bus;
140
+ if (!bus) {
141
+ bus = qpci_new_pc(s, fuzz_qos_alloc);
142
+ }
143
+
144
+ QOSFuzzAction a;
145
+ while (Size >= sizeof(a)) {
146
+ memcpy(&a, Data, sizeof(a));
147
+ switch (a.opcode % ACTION_MAX) {
148
+ case WRITEB:
149
+ bus->config_writeb(bus, a.devfn, a.offset, (uint8_t)a.value);
150
+ break;
151
+ case WRITEW:
152
+ bus->config_writew(bus, a.devfn, a.offset, (uint16_t)a.value);
153
+ break;
154
+ case WRITEL:
155
+ bus->config_writel(bus, a.devfn, a.offset, (uint32_t)a.value);
156
+ break;
157
+ case READB:
158
+ bus->config_readb(bus, a.devfn, a.offset);
159
+ break;
160
+ case READW:
161
+ bus->config_readw(bus, a.devfn, a.offset);
162
+ break;
163
+ case READL:
164
+ bus->config_readl(bus, a.devfn, a.offset);
165
+ break;
166
+ }
167
+ Size -= sizeof(a);
168
+ Data += sizeof(a);
169
+ }
170
+ flush_events(s);
171
+}
172
+
173
+static void i440fx_fuzz_qos_fork(QTestState *s,
174
+ const unsigned char *Data, size_t Size) {
175
+ if (fork() == 0) {
176
+ i440fx_fuzz_qos(s, Data, Size);
177
+ _Exit(0);
178
+ } else {
179
+ wait(NULL);
180
+ }
181
+}
182
+
183
+static const char *i440fx_qtest_argv = TARGET_NAME " -machine accel=qtest"
184
+ "-m 0 -display none";
185
+static const char *i440fx_argv(FuzzTarget *t)
186
+{
187
+ return i440fx_qtest_argv;
188
+}
189
+
190
+static void fork_init(void)
191
+{
192
+ counter_shm_init();
193
+}
194
+
195
+static void register_pci_fuzz_targets(void)
196
+{
197
+ /* Uses simple qtest commands and reboots to reset state */
198
+ fuzz_add_target(&(FuzzTarget){
199
+ .name = "i440fx-qtest-reboot-fuzz",
200
+ .description = "Fuzz the i440fx using raw qtest commands and"
201
+ "rebooting after each run",
202
+ .get_init_cmdline = i440fx_argv,
203
+ .fuzz = i440fx_fuzz_qtest});
204
+
205
+ /* Uses libqos and forks to prevent state leakage */
206
+ fuzz_add_qos_target(&(FuzzTarget){
207
+ .name = "i440fx-qos-fork-fuzz",
208
+ .description = "Fuzz the i440fx using raw qtest commands and"
209
+ "rebooting after each run",
210
+ .pre_vm_init = &fork_init,
211
+ .fuzz = i440fx_fuzz_qos_fork,},
212
+ "i440FX-pcihost",
213
+ &(QOSGraphTestOptions){}
214
+ );
215
+
216
+ /*
217
+ * Uses libqos. Doesn't do anything to reset state. Note that if we were to
218
+ * reboot after each run, we would also have to redo the qos-related
219
+ * initialization (qos_init_path)
220
+ */
221
+ fuzz_add_qos_target(&(FuzzTarget){
222
+ .name = "i440fx-qos-noreset-fuzz",
223
+ .description = "Fuzz the i440fx using raw qtest commands and"
224
+ "rebooting after each run",
225
+ .fuzz = i440fx_fuzz_qos,},
226
+ "i440FX-pcihost",
227
+ &(QOSGraphTestOptions){}
228
+ );
229
+}
230
+
231
+fuzz_target_init(register_pci_fuzz_targets);
120
--
232
--
121
2.24.1
233
2.24.1
122
234
123
diff view generated by jsdifflib
1
This test can run just fine with other values for refcount_bits, so we
1
From: Alexander Bulekov <alxndr@bu.edu>
2
should filter the value from qcow2.py's dump-header. In fact, we can
2
3
filter everything but the feature bits and header extensions, because
3
The virtio-net fuzz target feeds inputs to all three virtio-net
4
that is what the test is about.
4
virtqueues, and uses forking to avoid leaking state between fuzz runs.
5
5
6
(036 currently ignores user-specified image options, but that will be
6
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
7
fixed in the next patch.)
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
8
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20200220041118.23264-21-alxndr@bu.edu
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-id: 20191107163708.833192-6-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
11
---
14
tests/qemu-iotests/036 | 9 ++++---
12
tests/qtest/fuzz/Makefile.include | 1 +
15
tests/qemu-iotests/036.out | 48 --------------------------------------
13
tests/qtest/fuzz/virtio_net_fuzz.c | 198 +++++++++++++++++++++++++++++
16
2 files changed, 6 insertions(+), 51 deletions(-)
14
2 files changed, 199 insertions(+)
17
15
create mode 100644 tests/qtest/fuzz/virtio_net_fuzz.c
18
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
16
19
index XXXXXXX..XXXXXXX 100755
17
diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include
20
--- a/tests/qemu-iotests/036
21
+++ b/tests/qemu-iotests/036
22
@@ -XXX,XX +XXX,XX @@ $PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
23
24
# Without feature table
25
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
26
-$PYTHON qcow2.py "$TEST_IMG" dump-header
27
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep features
28
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
29
_img_info
30
31
# With feature table containing bit 63
32
@@ -XXX,XX +XXX,XX @@ echo === Create image with unknown autoclear feature bit ===
33
echo
34
_make_test_img 64M
35
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit autoclear 63
36
-$PYTHON qcow2.py "$TEST_IMG" dump-header
37
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep features
38
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
39
40
echo
41
echo === Repair image ===
42
echo
43
_check_test_img -r all
44
45
-$PYTHON qcow2.py "$TEST_IMG" dump-header
46
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep features
47
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
48
49
# success, all done
50
echo "*** done"
51
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
52
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
53
--- a/tests/qemu-iotests/036.out
19
--- a/tests/qtest/fuzz/Makefile.include
54
+++ b/tests/qemu-iotests/036.out
20
+++ b/tests/qtest/fuzz/Makefile.include
55
@@ -XXX,XX +XXX,XX @@ QA output created by 036
21
@@ -XXX,XX +XXX,XX @@ fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
56
=== Image with unknown incompatible feature bit ===
22
57
23
# Targets
58
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
24
fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o
59
-magic 0x514649fb
25
+fuzz-obj-y += tests/qtest/fuzz/virtio_net_fuzz.o
60
-version 3
26
61
-backing_file_offset 0x0
27
FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
62
-backing_file_size 0x0
28
63
-cluster_bits 16
29
diff --git a/tests/qtest/fuzz/virtio_net_fuzz.c b/tests/qtest/fuzz/virtio_net_fuzz.c
64
-size 67108864
30
new file mode 100644
65
-crypt_method 0
31
index XXXXXXX..XXXXXXX
66
-l1_size 1
32
--- /dev/null
67
-l1_table_offset 0x30000
33
+++ b/tests/qtest/fuzz/virtio_net_fuzz.c
68
-refcount_table_offset 0x10000
34
@@ -XXX,XX +XXX,XX @@
69
-refcount_table_clusters 1
35
+/*
70
-nb_snapshots 0
36
+ * virtio-net Fuzzing Target
71
-snapshot_offset 0x0
37
+ *
72
incompatible_features [63]
38
+ * Copyright Red Hat Inc., 2019
73
compatible_features []
39
+ *
74
autoclear_features []
40
+ * Authors:
75
-refcount_order 4
41
+ * Alexander Bulekov <alxndr@bu.edu>
76
-header_length 104
42
+ *
77
-
43
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
78
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Unknown incompatible feature: 8000000000000000
44
+ * See the COPYING file in the top-level directory.
79
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Test feature
45
+ */
80
46
+
81
@@ -XXX,XX +XXX,XX @@ qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): tes
47
+#include "qemu/osdep.h"
82
=== Create image with unknown autoclear feature bit ===
48
+
83
49
+#include "standard-headers/linux/virtio_config.h"
84
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
50
+#include "tests/qtest/libqtest.h"
85
-magic 0x514649fb
51
+#include "tests/qtest/libqos/virtio-net.h"
86
-version 3
52
+#include "fuzz.h"
87
-backing_file_offset 0x0
53
+#include "fork_fuzz.h"
88
-backing_file_size 0x0
54
+#include "qos_fuzz.h"
89
-cluster_bits 16
55
+
90
-size 67108864
56
+
91
-crypt_method 0
57
+#define QVIRTIO_NET_TIMEOUT_US (30 * 1000 * 1000)
92
-l1_size 1
58
+#define QVIRTIO_RX_VQ 0
93
-l1_table_offset 0x30000
59
+#define QVIRTIO_TX_VQ 1
94
-refcount_table_offset 0x10000
60
+#define QVIRTIO_CTRL_VQ 2
95
-refcount_table_clusters 1
61
+
96
-nb_snapshots 0
62
+static int sockfds[2];
97
-snapshot_offset 0x0
63
+static bool sockfds_initialized;
98
incompatible_features []
64
+
99
compatible_features []
65
+static void virtio_net_fuzz_multi(QTestState *s,
100
autoclear_features [63]
66
+ const unsigned char *Data, size_t Size, bool check_used)
101
-refcount_order 4
67
+{
102
-header_length 104
68
+ typedef struct vq_action {
103
-
69
+ uint8_t queue;
104
Header extension:
70
+ uint8_t length;
105
magic 0x6803f857
71
+ uint8_t write;
106
length 192
72
+ uint8_t next;
107
@@ -XXX,XX +XXX,XX @@ data <binary>
73
+ uint8_t rx;
108
=== Repair image ===
74
+ } vq_action;
109
75
+
110
No errors were found on the image.
76
+ uint32_t free_head = 0;
111
-magic 0x514649fb
77
+
112
-version 3
78
+ QGuestAllocator *t_alloc = fuzz_qos_alloc;
113
-backing_file_offset 0x0
79
+
114
-backing_file_size 0x0
80
+ QVirtioNet *net_if = fuzz_qos_obj;
115
-cluster_bits 16
81
+ QVirtioDevice *dev = net_if->vdev;
116
-size 67108864
82
+ QVirtQueue *q;
117
-crypt_method 0
83
+ vq_action vqa;
118
-l1_size 1
84
+ while (Size >= sizeof(vqa)) {
119
-l1_table_offset 0x30000
85
+ memcpy(&vqa, Data, sizeof(vqa));
120
-refcount_table_offset 0x10000
86
+ Data += sizeof(vqa);
121
-refcount_table_clusters 1
87
+ Size -= sizeof(vqa);
122
-nb_snapshots 0
88
+
123
-snapshot_offset 0x0
89
+ q = net_if->queues[vqa.queue % 3];
124
incompatible_features []
90
+
125
compatible_features []
91
+ vqa.length = vqa.length >= Size ? Size : vqa.length;
126
autoclear_features []
92
+
127
-refcount_order 4
93
+ /*
128
-header_length 104
94
+ * Only attempt to write incoming packets, when using the socket
129
-
95
+ * backend. Otherwise, always place the input on a virtqueue.
130
Header extension:
96
+ */
131
magic 0x6803f857
97
+ if (vqa.rx && sockfds_initialized) {
132
length 192
98
+ write(sockfds[0], Data, vqa.length);
99
+ } else {
100
+ vqa.rx = 0;
101
+ uint64_t req_addr = guest_alloc(t_alloc, vqa.length);
102
+ /*
103
+ * If checking used ring, ensure that the fuzzer doesn't trigger
104
+ * trivial asserion failure on zero-zied buffer
105
+ */
106
+ qtest_memwrite(s, req_addr, Data, vqa.length);
107
+
108
+
109
+ free_head = qvirtqueue_add(s, q, req_addr, vqa.length,
110
+ vqa.write, vqa.next);
111
+ qvirtqueue_add(s, q, req_addr, vqa.length, vqa.write , vqa.next);
112
+ qvirtqueue_kick(s, dev, q, free_head);
113
+ }
114
+
115
+ /* Run the main loop */
116
+ qtest_clock_step(s, 100);
117
+ flush_events(s);
118
+
119
+ /* Wait on used descriptors */
120
+ if (check_used && !vqa.rx) {
121
+ gint64 start_time = g_get_monotonic_time();
122
+ /*
123
+ * normally, we could just use qvirtio_wait_used_elem, but since we
124
+ * must manually run the main-loop for all the bhs to run, we use
125
+ * this hack with flush_events(), to run the main_loop
126
+ */
127
+ while (!vqa.rx && q != net_if->queues[QVIRTIO_RX_VQ]) {
128
+ uint32_t got_desc_idx;
129
+ /* Input led to a virtio_error */
130
+ if (dev->bus->get_status(dev) & VIRTIO_CONFIG_S_NEEDS_RESET) {
131
+ break;
132
+ }
133
+ if (dev->bus->get_queue_isr_status(dev, q) &&
134
+ qvirtqueue_get_buf(s, q, &got_desc_idx, NULL)) {
135
+ g_assert_cmpint(got_desc_idx, ==, free_head);
136
+ break;
137
+ }
138
+ g_assert(g_get_monotonic_time() - start_time
139
+ <= QVIRTIO_NET_TIMEOUT_US);
140
+
141
+ /* Run the main loop */
142
+ qtest_clock_step(s, 100);
143
+ flush_events(s);
144
+ }
145
+ }
146
+ Data += vqa.length;
147
+ Size -= vqa.length;
148
+ }
149
+}
150
+
151
+static void virtio_net_fork_fuzz(QTestState *s,
152
+ const unsigned char *Data, size_t Size)
153
+{
154
+ if (fork() == 0) {
155
+ virtio_net_fuzz_multi(s, Data, Size, false);
156
+ flush_events(s);
157
+ _Exit(0);
158
+ } else {
159
+ wait(NULL);
160
+ }
161
+}
162
+
163
+static void virtio_net_fork_fuzz_check_used(QTestState *s,
164
+ const unsigned char *Data, size_t Size)
165
+{
166
+ if (fork() == 0) {
167
+ virtio_net_fuzz_multi(s, Data, Size, true);
168
+ flush_events(s);
169
+ _Exit(0);
170
+ } else {
171
+ wait(NULL);
172
+ }
173
+}
174
+
175
+static void virtio_net_pre_fuzz(QTestState *s)
176
+{
177
+ qos_init_path(s);
178
+ counter_shm_init();
179
+}
180
+
181
+static void *virtio_net_test_setup_socket(GString *cmd_line, void *arg)
182
+{
183
+ int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sockfds);
184
+ g_assert_cmpint(ret, !=, -1);
185
+ fcntl(sockfds[0], F_SETFL, O_NONBLOCK);
186
+ sockfds_initialized = true;
187
+ g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ",
188
+ sockfds[1]);
189
+ return arg;
190
+}
191
+
192
+static void *virtio_net_test_setup_user(GString *cmd_line, void *arg)
193
+{
194
+ g_string_append_printf(cmd_line, " -netdev user,id=hs0 ");
195
+ return arg;
196
+}
197
+
198
+static void register_virtio_net_fuzz_targets(void)
199
+{
200
+ fuzz_add_qos_target(&(FuzzTarget){
201
+ .name = "virtio-net-socket",
202
+ .description = "Fuzz the virtio-net virtual queues. Fuzz incoming "
203
+ "traffic using the socket backend",
204
+ .pre_fuzz = &virtio_net_pre_fuzz,
205
+ .fuzz = virtio_net_fork_fuzz,},
206
+ "virtio-net",
207
+ &(QOSGraphTestOptions){.before = virtio_net_test_setup_socket}
208
+ );
209
+
210
+ fuzz_add_qos_target(&(FuzzTarget){
211
+ .name = "virtio-net-socket-check-used",
212
+ .description = "Fuzz the virtio-net virtual queues. Wait for the "
213
+ "descriptors to be used. Timeout may indicate improperly handled "
214
+ "input",
215
+ .pre_fuzz = &virtio_net_pre_fuzz,
216
+ .fuzz = virtio_net_fork_fuzz_check_used,},
217
+ "virtio-net",
218
+ &(QOSGraphTestOptions){.before = virtio_net_test_setup_socket}
219
+ );
220
+ fuzz_add_qos_target(&(FuzzTarget){
221
+ .name = "virtio-net-slirp",
222
+ .description = "Fuzz the virtio-net virtual queues with the slirp "
223
+ " backend. Warning: May result in network traffic emitted from the "
224
+ " process. Run in an isolated network environment.",
225
+ .pre_fuzz = &virtio_net_pre_fuzz,
226
+ .fuzz = virtio_net_fork_fuzz,},
227
+ "virtio-net",
228
+ &(QOSGraphTestOptions){.before = virtio_net_test_setup_user}
229
+ );
230
+}
231
+
232
+fuzz_target_init(register_virtio_net_fuzz_targets);
133
--
233
--
134
2.24.1
234
2.24.1
135
235
136
diff view generated by jsdifflib
1
Print the feature fields as a set of bits so that filtering is easier.
1
From: Alexander Bulekov <alxndr@bu.edu>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
The virtio-scsi fuzz target sets up and fuzzes the available virtio-scsi
4
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
queues. After an element is placed on a queue, the fuzzer can select
5
Message-id: 20191107163708.833192-4-mreitz@redhat.com
5
whether to perform a kick, or continue adding elements.
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
7
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
8
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
9
Message-id: 20200220041118.23264-22-alxndr@bu.edu
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
---
11
---
8
tests/qemu-iotests/031.out | 36 +++++++++----------
12
tests/qtest/fuzz/Makefile.include | 1 +
9
tests/qemu-iotests/036.out | 18 +++++-----
13
tests/qtest/fuzz/virtio_scsi_fuzz.c | 213 ++++++++++++++++++++++++++++
10
tests/qemu-iotests/039.out | 22 ++++++------
14
2 files changed, 214 insertions(+)
11
tests/qemu-iotests/060.out | 20 +++++------
15
create mode 100644 tests/qtest/fuzz/virtio_scsi_fuzz.c
12
tests/qemu-iotests/061.out | 72 ++++++++++++++++++-------------------
16
13
tests/qemu-iotests/137.out | 2 +-
17
diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include
14
tests/qemu-iotests/qcow2.py | 18 +++++++---
15
7 files changed, 99 insertions(+), 89 deletions(-)
16
17
diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/031.out
19
--- a/tests/qtest/fuzz/Makefile.include
20
+++ b/tests/qemu-iotests/031.out
20
+++ b/tests/qtest/fuzz/Makefile.include
21
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
21
@@ -XXX,XX +XXX,XX @@ fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
22
refcount_table_clusters 1
22
# Targets
23
nb_snapshots 0
23
fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o
24
snapshot_offset 0x0
24
fuzz-obj-y += tests/qtest/fuzz/virtio_net_fuzz.o
25
-incompatible_features 0x0
25
+fuzz-obj-y += tests/qtest/fuzz/virtio_scsi_fuzz.o
26
-compatible_features 0x0
26
27
-autoclear_features 0x0
27
FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
28
+incompatible_features []
28
29
+compatible_features []
29
diff --git a/tests/qtest/fuzz/virtio_scsi_fuzz.c b/tests/qtest/fuzz/virtio_scsi_fuzz.c
30
+autoclear_features []
30
new file mode 100644
31
refcount_order 4
31
index XXXXXXX..XXXXXXX
32
header_length 72
32
--- /dev/null
33
33
+++ b/tests/qtest/fuzz/virtio_scsi_fuzz.c
34
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
34
@@ -XXX,XX +XXX,XX @@
35
refcount_table_clusters 1
35
+/*
36
nb_snapshots 0
36
+ * virtio-serial Fuzzing Target
37
snapshot_offset 0x0
37
+ *
38
-incompatible_features 0x0
38
+ * Copyright Red Hat Inc., 2019
39
-compatible_features 0x0
39
+ *
40
-autoclear_features 0x0
40
+ * Authors:
41
+incompatible_features []
41
+ * Alexander Bulekov <alxndr@bu.edu>
42
+compatible_features []
42
+ *
43
+autoclear_features []
43
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
44
refcount_order 4
44
+ * See the COPYING file in the top-level directory.
45
header_length 72
45
+ */
46
46
+
47
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
47
+#include "qemu/osdep.h"
48
refcount_table_clusters 1
48
+
49
nb_snapshots 0
49
+#include "tests/qtest/libqtest.h"
50
snapshot_offset 0x0
50
+#include "libqos/virtio-scsi.h"
51
-incompatible_features 0x0
51
+#include "libqos/virtio.h"
52
-compatible_features 0x0
52
+#include "libqos/virtio-pci.h"
53
-autoclear_features 0x0
53
+#include "standard-headers/linux/virtio_ids.h"
54
+incompatible_features []
54
+#include "standard-headers/linux/virtio_pci.h"
55
+compatible_features []
55
+#include "standard-headers/linux/virtio_scsi.h"
56
+autoclear_features []
56
+#include "fuzz.h"
57
refcount_order 4
57
+#include "fork_fuzz.h"
58
header_length 72
58
+#include "qos_fuzz.h"
59
59
+
60
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
60
+#define PCI_SLOT 0x02
61
refcount_table_clusters 1
61
+#define PCI_FN 0x00
62
nb_snapshots 0
62
+#define QVIRTIO_SCSI_TIMEOUT_US (1 * 1000 * 1000)
63
snapshot_offset 0x0
63
+
64
-incompatible_features 0x0
64
+#define MAX_NUM_QUEUES 64
65
-compatible_features 0x0
65
+
66
-autoclear_features 0x0
66
+/* Based on tests/virtio-scsi-test.c */
67
+incompatible_features []
67
+typedef struct {
68
+compatible_features []
68
+ int num_queues;
69
+autoclear_features []
69
+ QVirtQueue *vq[MAX_NUM_QUEUES + 2];
70
refcount_order 4
70
+} QVirtioSCSIQueues;
71
header_length 104
71
+
72
72
+static QVirtioSCSIQueues *qvirtio_scsi_init(QVirtioDevice *dev, uint64_t mask)
73
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
73
+{
74
refcount_table_clusters 1
74
+ QVirtioSCSIQueues *vs;
75
nb_snapshots 0
75
+ uint64_t feat;
76
snapshot_offset 0x0
76
+ int i;
77
-incompatible_features 0x0
77
+
78
-compatible_features 0x0
78
+ vs = g_new0(QVirtioSCSIQueues, 1);
79
-autoclear_features 0x0
79
+
80
+incompatible_features []
80
+ feat = qvirtio_get_features(dev);
81
+compatible_features []
81
+ if (mask) {
82
+autoclear_features []
82
+ feat &= ~QVIRTIO_F_BAD_FEATURE | mask;
83
refcount_order 4
83
+ } else {
84
header_length 104
84
+ feat &= ~(QVIRTIO_F_BAD_FEATURE | (1ull << VIRTIO_RING_F_EVENT_IDX));
85
85
+ }
86
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
86
+ qvirtio_set_features(dev, feat);
87
refcount_table_clusters 1
87
+
88
nb_snapshots 0
88
+ vs->num_queues = qvirtio_config_readl(dev, 0);
89
snapshot_offset 0x0
89
+
90
-incompatible_features 0x0
90
+ for (i = 0; i < vs->num_queues + 2; i++) {
91
-compatible_features 0x0
91
+ vs->vq[i] = qvirtqueue_setup(dev, fuzz_qos_alloc, i);
92
-autoclear_features 0x0
92
+ }
93
+incompatible_features []
93
+
94
+compatible_features []
94
+ qvirtio_set_driver_ok(dev);
95
+autoclear_features []
95
+
96
refcount_order 4
96
+ return vs;
97
header_length 104
97
+}
98
98
+
99
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
99
+static void virtio_scsi_fuzz(QTestState *s, QVirtioSCSIQueues* queues,
100
index XXXXXXX..XXXXXXX 100644
100
+ const unsigned char *Data, size_t Size)
101
--- a/tests/qemu-iotests/036.out
101
+{
102
+++ b/tests/qemu-iotests/036.out
102
+ /*
103
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
103
+ * Data is a sequence of random bytes. We split them up into "actions",
104
refcount_table_clusters 1
104
+ * followed by data:
105
nb_snapshots 0
105
+ * [vqa][dddddddd][vqa][dddd][vqa][dddddddddddd] ...
106
snapshot_offset 0x0
106
+ * The length of the data is specified by the preceding vqa.length
107
-incompatible_features 0x8000000000000000
107
+ */
108
-compatible_features 0x0
108
+ typedef struct vq_action {
109
-autoclear_features 0x0
109
+ uint8_t queue;
110
+incompatible_features [63]
110
+ uint8_t length;
111
+compatible_features []
111
+ uint8_t write;
112
+autoclear_features []
112
+ uint8_t next;
113
refcount_order 4
113
+ uint8_t kick;
114
header_length 104
114
+ } vq_action;
115
115
+
116
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
116
+ /* Keep track of the free head for each queue we interact with */
117
refcount_table_clusters 1
117
+ bool vq_touched[MAX_NUM_QUEUES + 2] = {0};
118
nb_snapshots 0
118
+ uint32_t free_head[MAX_NUM_QUEUES + 2];
119
snapshot_offset 0x0
119
+
120
-incompatible_features 0x0
120
+ QGuestAllocator *t_alloc = fuzz_qos_alloc;
121
-compatible_features 0x0
121
+
122
-autoclear_features 0x8000000000000000
122
+ QVirtioSCSI *scsi = fuzz_qos_obj;
123
+incompatible_features []
123
+ QVirtioDevice *dev = scsi->vdev;
124
+compatible_features []
124
+ QVirtQueue *q;
125
+autoclear_features [63]
125
+ vq_action vqa;
126
refcount_order 4
126
+ while (Size >= sizeof(vqa)) {
127
header_length 104
127
+ /* Copy the action, so we can normalize length, queue and flags */
128
128
+ memcpy(&vqa, Data, sizeof(vqa));
129
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
129
+
130
refcount_table_clusters 1
130
+ Data += sizeof(vqa);
131
nb_snapshots 0
131
+ Size -= sizeof(vqa);
132
snapshot_offset 0x0
132
+
133
-incompatible_features 0x0
133
+ vqa.queue = vqa.queue % queues->num_queues;
134
-compatible_features 0x0
134
+ /* Cap length at the number of remaining bytes in data */
135
-autoclear_features 0x0
135
+ vqa.length = vqa.length >= Size ? Size : vqa.length;
136
+incompatible_features []
136
+ vqa.write = vqa.write & 1;
137
+compatible_features []
137
+ vqa.next = vqa.next & 1;
138
+autoclear_features []
138
+ vqa.kick = vqa.kick & 1;
139
refcount_order 4
139
+
140
header_length 104
140
+
141
141
+ q = queues->vq[vqa.queue];
142
diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out
142
+
143
index XXXXXXX..XXXXXXX 100644
143
+ /* Copy the data into ram, and place it on the virtqueue */
144
--- a/tests/qemu-iotests/039.out
144
+ uint64_t req_addr = guest_alloc(t_alloc, vqa.length);
145
+++ b/tests/qemu-iotests/039.out
145
+ qtest_memwrite(s, req_addr, Data, vqa.length);
146
@@ -XXX,XX +XXX,XX @@ QA output created by 039
146
+ if (vq_touched[vqa.queue] == 0) {
147
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
147
+ vq_touched[vqa.queue] = 1;
148
wrote 512/512 bytes at offset 0
148
+ free_head[vqa.queue] = qvirtqueue_add(s, q, req_addr, vqa.length,
149
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
149
+ vqa.write, vqa.next);
150
-incompatible_features 0x0
150
+ } else {
151
+incompatible_features []
151
+ qvirtqueue_add(s, q, req_addr, vqa.length, vqa.write , vqa.next);
152
No errors were found on the image.
152
+ }
153
153
+
154
== Creating a dirty image file ==
154
+ if (vqa.kick) {
155
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
155
+ qvirtqueue_kick(s, dev, q, free_head[vqa.queue]);
156
wrote 512/512 bytes at offset 0
156
+ free_head[vqa.queue] = 0;
157
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
157
+ }
158
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
158
+ Data += vqa.length;
159
-incompatible_features 0x1
159
+ Size -= vqa.length;
160
+incompatible_features [0]
160
+ }
161
ERROR cluster 5 refcount=0 reference=1
161
+ /* In the end, kick each queue we interacted with */
162
ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0
162
+ for (int i = 0; i < MAX_NUM_QUEUES + 2; i++) {
163
163
+ if (vq_touched[i]) {
164
@@ -XXX,XX +XXX,XX @@ Data may be corrupted, or further writes to the image may corrupt it.
164
+ qvirtqueue_kick(s, dev, queues->vq[i], free_head[i]);
165
== Read-only access must still work ==
165
+ }
166
read 512/512 bytes at offset 0
166
+ }
167
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
167
+}
168
-incompatible_features 0x1
168
+
169
+incompatible_features [0]
169
+static void virtio_scsi_fork_fuzz(QTestState *s,
170
170
+ const unsigned char *Data, size_t Size)
171
== Repairing the image file must succeed ==
171
+{
172
ERROR cluster 5 refcount=0 reference=1
172
+ QVirtioSCSI *scsi = fuzz_qos_obj;
173
@@ -XXX,XX +XXX,XX @@ The following inconsistencies were found and repaired:
173
+ static QVirtioSCSIQueues *queues;
174
174
+ if (!queues) {
175
Double checking the fixed image now...
175
+ queues = qvirtio_scsi_init(scsi->vdev, 0);
176
No errors were found on the image.
176
+ }
177
-incompatible_features 0x0
177
+ if (fork() == 0) {
178
+incompatible_features []
178
+ virtio_scsi_fuzz(s, queues, Data, Size);
179
179
+ flush_events(s);
180
== Data should still be accessible after repair ==
180
+ _Exit(0);
181
read 512/512 bytes at offset 0
181
+ } else {
182
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
182
+ wait(NULL);
183
wrote 512/512 bytes at offset 0
183
+ }
184
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
184
+}
185
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
185
+
186
-incompatible_features 0x1
186
+static void virtio_scsi_with_flag_fuzz(QTestState *s,
187
+incompatible_features [0]
187
+ const unsigned char *Data, size_t Size)
188
ERROR cluster 5 refcount=0 reference=1
188
+{
189
Rebuilding refcount structure
189
+ QVirtioSCSI *scsi = fuzz_qos_obj;
190
Repairing cluster 1 refcount=1 reference=0
190
+ static QVirtioSCSIQueues *queues;
191
Repairing cluster 2 refcount=1 reference=0
191
+
192
wrote 512/512 bytes at offset 0
192
+ if (fork() == 0) {
193
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
193
+ if (Size >= sizeof(uint64_t)) {
194
-incompatible_features 0x0
194
+ queues = qvirtio_scsi_init(scsi->vdev, *(uint64_t *)Data);
195
+incompatible_features []
195
+ virtio_scsi_fuzz(s, queues,
196
196
+ Data + sizeof(uint64_t), Size - sizeof(uint64_t));
197
== Creating an image file with lazy_refcounts=off ==
197
+ flush_events(s);
198
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
198
+ }
199
wrote 512/512 bytes at offset 0
199
+ _Exit(0);
200
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
200
+ } else {
201
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
201
+ wait(NULL);
202
-incompatible_features 0x0
202
+ }
203
+incompatible_features []
203
+}
204
No errors were found on the image.
204
+
205
205
+static void virtio_scsi_pre_fuzz(QTestState *s)
206
== Committing to a backing file with lazy_refcounts=on ==
206
+{
207
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/
207
+ qos_init_path(s);
208
wrote 512/512 bytes at offset 0
208
+ counter_shm_init();
209
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
209
+}
210
Image committed.
210
+
211
-incompatible_features 0x0
211
+static void *virtio_scsi_test_setup(GString *cmd_line, void *arg)
212
-incompatible_features 0x0
212
+{
213
+incompatible_features []
213
+ g_string_append(cmd_line,
214
+incompatible_features []
214
+ " -drive file=blkdebug::null-co://,"
215
No errors were found on the image.
215
+ "file.image.read-zeroes=on,"
216
No errors were found on the image.
216
+ "if=none,id=dr1,format=raw,file.align=4k "
217
217
+ "-device scsi-hd,drive=dr1,lun=0,scsi-id=1");
218
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
218
+ return arg;
219
wrote 512/512 bytes at offset 0
219
+}
220
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
220
+
221
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
221
+
222
-incompatible_features 0x1
222
+static void register_virtio_scsi_fuzz_targets(void)
223
+incompatible_features [0]
223
+{
224
ERROR cluster 5 refcount=0 reference=1
224
+ fuzz_add_qos_target(&(FuzzTarget){
225
ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0
225
+ .name = "virtio-scsi-fuzz",
226
226
+ .description = "Fuzz the virtio-scsi virtual queues, forking"
227
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
227
+ "for each fuzz run",
228
wrote 512/512 bytes at offset 0
228
+ .pre_vm_init = &counter_shm_init,
229
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
229
+ .pre_fuzz = &virtio_scsi_pre_fuzz,
230
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
230
+ .fuzz = virtio_scsi_fork_fuzz,},
231
-incompatible_features 0x0
231
+ "virtio-scsi",
232
+incompatible_features []
232
+ &(QOSGraphTestOptions){.before = virtio_scsi_test_setup}
233
No errors were found on the image.
233
+ );
234
*** done
234
+
235
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
235
+ fuzz_add_qos_target(&(FuzzTarget){
236
index XXXXXXX..XXXXXXX 100644
236
+ .name = "virtio-scsi-flags-fuzz",
237
--- a/tests/qemu-iotests/060.out
237
+ .description = "Fuzz the virtio-scsi virtual queues, forking"
238
+++ b/tests/qemu-iotests/060.out
238
+ "for each fuzz run (also fuzzes the virtio flags)",
239
@@ -XXX,XX +XXX,XX @@ ERROR cluster 3 refcount=1 reference=3
239
+ .pre_vm_init = &counter_shm_init,
240
240
+ .pre_fuzz = &virtio_scsi_pre_fuzz,
241
1 errors were found on the image.
241
+ .fuzz = virtio_scsi_with_flag_fuzz,},
242
Data may be corrupted, or further writes to the image may corrupt it.
242
+ "virtio-scsi",
243
-incompatible_features 0x0
243
+ &(QOSGraphTestOptions){.before = virtio_scsi_test_setup}
244
+incompatible_features []
244
+ );
245
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with active L1 table); further corruption events will be suppressed
245
+}
246
write failed: Input/output error
246
+
247
-incompatible_features 0x2
247
+fuzz_target_init(register_virtio_scsi_fuzz_targets);
248
+incompatible_features [1]
249
image: TEST_DIR/t.IMGFMT
250
file format: IMGFMT
251
virtual size: 64 MiB (67108864 bytes)
252
@@ -XXX,XX +XXX,XX @@ ERROR cluster 2 refcount=1 reference=2
253
254
2 errors were found on the image.
255
Data may be corrupted, or further writes to the image may corrupt it.
256
-incompatible_features 0x0
257
+incompatible_features []
258
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with refcount block); further corruption events will be suppressed
259
write failed: Input/output error
260
-incompatible_features 0x2
261
+incompatible_features [1]
262
ERROR refcount block 0 refcount=2
263
ERROR cluster 2 refcount=1 reference=2
264
Rebuilding refcount structure
265
@@ -XXX,XX +XXX,XX @@ The following inconsistencies were found and repaired:
266
267
Double checking the fixed image now...
268
No errors were found on the image.
269
-incompatible_features 0x0
270
+incompatible_features []
271
wrote 512/512 bytes at offset 0
272
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
-incompatible_features 0x0
274
+incompatible_features []
275
276
=== Testing cluster data reference into inactive L2 table ===
277
278
@@ -XXX,XX +XXX,XX @@ Data may be corrupted, or further writes to the image may corrupt it.
279
280
1 leaked clusters were found on the image.
281
This means waste of disk space, but no harm to data.
282
-incompatible_features 0x0
283
+incompatible_features []
284
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with inactive L2 table); further corruption events will be suppressed
285
write failed: Input/output error
286
-incompatible_features 0x2
287
+incompatible_features [1]
288
ERROR cluster 4 refcount=1 reference=2
289
Leaked cluster 9 refcount=1 reference=0
290
Repairing cluster 4 refcount=1 reference=2
291
@@ -XXX,XX +XXX,XX @@ The following inconsistencies were found and repaired:
292
293
Double checking the fixed image now...
294
No errors were found on the image.
295
-incompatible_features 0x0
296
+incompatible_features []
297
wrote 512/512 bytes at offset 0
298
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
299
-incompatible_features 0x0
300
+incompatible_features []
301
read 512/512 bytes at offset 0
302
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
303
No errors were found on the image.
304
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
305
index XXXXXXX..XXXXXXX 100644
306
--- a/tests/qemu-iotests/061.out
307
+++ b/tests/qemu-iotests/061.out
308
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
309
refcount_table_clusters 1
310
nb_snapshots 0
311
snapshot_offset 0x0
312
-incompatible_features 0x0
313
-compatible_features 0x1
314
-autoclear_features 0x0
315
+incompatible_features []
316
+compatible_features [0]
317
+autoclear_features []
318
refcount_order 4
319
header_length 104
320
321
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
322
refcount_table_clusters 1
323
nb_snapshots 0
324
snapshot_offset 0x0
325
-incompatible_features 0x0
326
-compatible_features 0x0
327
-autoclear_features 0x0
328
+incompatible_features []
329
+compatible_features []
330
+autoclear_features []
331
refcount_order 4
332
header_length 72
333
334
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
335
refcount_table_clusters 1
336
nb_snapshots 0
337
snapshot_offset 0x0
338
-incompatible_features 0x0
339
-compatible_features 0x1
340
-autoclear_features 0x0
341
+incompatible_features []
342
+compatible_features [0]
343
+autoclear_features []
344
refcount_order 4
345
header_length 104
346
347
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
348
refcount_table_clusters 1
349
nb_snapshots 0
350
snapshot_offset 0x0
351
-incompatible_features 0x0
352
-compatible_features 0x0
353
-autoclear_features 0x0
354
+incompatible_features []
355
+compatible_features []
356
+autoclear_features []
357
refcount_order 4
358
header_length 72
359
360
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
361
refcount_table_clusters 1
362
nb_snapshots 0
363
snapshot_offset 0x0
364
-incompatible_features 0x1
365
-compatible_features 0x1
366
-autoclear_features 0x0
367
+incompatible_features [0]
368
+compatible_features [0]
369
+autoclear_features []
370
refcount_order 4
371
header_length 104
372
373
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x80000
374
refcount_table_clusters 1
375
nb_snapshots 0
376
snapshot_offset 0x0
377
-incompatible_features 0x0
378
-compatible_features 0x0
379
-autoclear_features 0x0
380
+incompatible_features []
381
+compatible_features []
382
+autoclear_features []
383
refcount_order 4
384
header_length 72
385
386
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
387
refcount_table_clusters 1
388
nb_snapshots 0
389
snapshot_offset 0x0
390
-incompatible_features 0x0
391
-compatible_features 0x40000000000
392
-autoclear_features 0x40000000000
393
+incompatible_features []
394
+compatible_features [42]
395
+autoclear_features [42]
396
refcount_order 4
397
header_length 104
398
399
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
400
refcount_table_clusters 1
401
nb_snapshots 0
402
snapshot_offset 0x0
403
-incompatible_features 0x0
404
-compatible_features 0x0
405
-autoclear_features 0x0
406
+incompatible_features []
407
+compatible_features []
408
+autoclear_features []
409
refcount_order 4
410
header_length 72
411
412
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
413
refcount_table_clusters 1
414
nb_snapshots 0
415
snapshot_offset 0x0
416
-incompatible_features 0x0
417
-compatible_features 0x0
418
-autoclear_features 0x0
419
+incompatible_features []
420
+compatible_features []
421
+autoclear_features []
422
refcount_order 4
423
header_length 72
424
425
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
426
refcount_table_clusters 1
427
nb_snapshots 0
428
snapshot_offset 0x0
429
-incompatible_features 0x0
430
-compatible_features 0x1
431
-autoclear_features 0x0
432
+incompatible_features []
433
+compatible_features [0]
434
+autoclear_features []
435
refcount_order 4
436
header_length 104
437
438
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
439
refcount_table_clusters 1
440
nb_snapshots 0
441
snapshot_offset 0x0
442
-incompatible_features 0x1
443
-compatible_features 0x1
444
-autoclear_features 0x0
445
+incompatible_features [0]
446
+compatible_features [0]
447
+autoclear_features []
448
refcount_order 4
449
header_length 104
450
451
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x80000
452
refcount_table_clusters 1
453
nb_snapshots 0
454
snapshot_offset 0x0
455
-incompatible_features 0x0
456
-compatible_features 0x0
457
-autoclear_features 0x0
458
+incompatible_features []
459
+compatible_features []
460
+autoclear_features []
461
refcount_order 4
462
header_length 104
463
464
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
465
index XXXXXXX..XXXXXXX 100644
466
--- a/tests/qemu-iotests/137.out
467
+++ b/tests/qemu-iotests/137.out
468
@@ -XXX,XX +XXX,XX @@ qemu-io: Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are
469
wrote 512/512 bytes at offset 0
470
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
471
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
472
-incompatible_features 0x0
473
+incompatible_features []
474
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
475
wrote 65536/65536 bytes at offset 0
476
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
477
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
478
index XXXXXXX..XXXXXXX 100755
479
--- a/tests/qemu-iotests/qcow2.py
480
+++ b/tests/qemu-iotests/qcow2.py
481
@@ -XXX,XX +XXX,XX @@ class QcowHeader:
482
[ uint64_t, '%#x', 'snapshot_offset' ],
483
484
# Version 3 header fields
485
- [ uint64_t, '%#x', 'incompatible_features' ],
486
- [ uint64_t, '%#x', 'compatible_features' ],
487
- [ uint64_t, '%#x', 'autoclear_features' ],
488
+ [ uint64_t, 'mask', 'incompatible_features' ],
489
+ [ uint64_t, 'mask', 'compatible_features' ],
490
+ [ uint64_t, 'mask', 'autoclear_features' ],
491
[ uint32_t, '%d', 'refcount_order' ],
492
[ uint32_t, '%d', 'header_length' ],
493
];
494
@@ -XXX,XX +XXX,XX @@ class QcowHeader:
495
496
def dump(self):
497
for f in QcowHeader.fields:
498
- print("%-25s" % f[2], f[1] % self.__dict__[f[2]])
499
+ value = self.__dict__[f[2]]
500
+ if f[1] == 'mask':
501
+ bits = []
502
+ for bit in range(64):
503
+ if value & (1 << bit):
504
+ bits.append(bit)
505
+ value_str = str(bits)
506
+ else:
507
+ value_str = f[1] % value
508
+
509
+ print("%-25s" % f[2], value_str)
510
print("")
511
512
def dump_extensions(self):
513
--
248
--
514
2.24.1
249
2.24.1
515
250
516
diff view generated by jsdifflib
1
This is useful for tests that want to whitelist fields from dump-header
1
From: Alexander Bulekov <alxndr@bu.edu>
2
(with grep) but still print all header extensions.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
5
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Message-id: 20191107163708.833192-3-mreitz@redhat.com
5
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Message-id: 20200220041118.23264-23-alxndr@bu.edu
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
8
---
9
tests/qemu-iotests/qcow2.py | 5 +++++
9
docs/devel/fuzzing.txt | 116 +++++++++++++++++++++++++++++++++++++++++
10
1 file changed, 5 insertions(+)
10
1 file changed, 116 insertions(+)
11
create mode 100644 docs/devel/fuzzing.txt
11
12
12
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
13
diff --git a/docs/devel/fuzzing.txt b/docs/devel/fuzzing.txt
13
index XXXXXXX..XXXXXXX 100755
14
new file mode 100644
14
--- a/tests/qemu-iotests/qcow2.py
15
index XXXXXXX..XXXXXXX
15
+++ b/tests/qemu-iotests/qcow2.py
16
--- /dev/null
16
@@ -XXX,XX +XXX,XX @@ def cmd_dump_header(fd):
17
+++ b/docs/devel/fuzzing.txt
17
h.dump()
18
@@ -XXX,XX +XXX,XX @@
18
h.dump_extensions()
19
+= Fuzzing =
19
20
+def cmd_dump_header_exts(fd):
21
+ h = QcowHeader(fd)
22
+ h.dump_extensions()
23
+
20
+
24
def cmd_set_header(fd, name, value):
21
+== Introduction ==
25
try:
22
+
26
value = int(value, 0)
23
+This document describes the virtual-device fuzzing infrastructure in QEMU and
27
@@ -XXX,XX +XXX,XX @@ def cmd_set_feature_bit(fd, group, bit):
24
+how to use it to implement additional fuzzers.
28
25
+
29
cmds = [
26
+== Basics ==
30
[ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],
27
+
31
+ [ 'dump-header-exts', cmd_dump_header_exts, 0, 'Dump image header extensions' ],
28
+Fuzzing operates by passing inputs to an entry point/target function. The
32
[ 'set-header', cmd_set_header, 2, 'Set a field in the header'],
29
+fuzzer tracks the code coverage triggered by the input. Based on these
33
[ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
30
+findings, the fuzzer mutates the input and repeats the fuzzing.
34
[ 'add-header-ext-stdio', cmd_add_header_ext_stdio, 1, 'Add a header extension, data from stdin' ],
31
+
32
+To fuzz QEMU, we rely on libfuzzer. Unlike other fuzzers such as AFL, libfuzzer
33
+is an _in-process_ fuzzer. For the developer, this means that it is their
34
+responsibility to ensure that state is reset between fuzzing-runs.
35
+
36
+== Building the fuzzers ==
37
+
38
+NOTE: If possible, build a 32-bit binary. When forking, the 32-bit fuzzer is
39
+much faster, since the page-map has a smaller size. This is due to the fact that
40
+AddressSanitizer mmaps ~20TB of memory, as part of its detection. This results
41
+in a large page-map, and a much slower fork().
42
+
43
+To build the fuzzers, install a recent version of clang:
44
+Configure with (substitute the clang binaries with the version you installed):
45
+
46
+ CC=clang-8 CXX=clang++-8 /path/to/configure --enable-fuzzing
47
+
48
+Fuzz targets are built similarly to system/softmmu:
49
+
50
+ make i386-softmmu/fuzz
51
+
52
+This builds ./i386-softmmu/qemu-fuzz-i386
53
+
54
+The first option to this command is: --fuzz_taget=FUZZ_NAME
55
+To list all of the available fuzzers run qemu-fuzz-i386 with no arguments.
56
+
57
+eg:
58
+ ./i386-softmmu/qemu-fuzz-i386 --fuzz-target=virtio-net-fork-fuzz
59
+
60
+Internally, libfuzzer parses all arguments that do not begin with "--".
61
+Information about these is available by passing -help=1
62
+
63
+Now the only thing left to do is wait for the fuzzer to trigger potential
64
+crashes.
65
+
66
+== Adding a new fuzzer ==
67
+Coverage over virtual devices can be improved by adding additional fuzzers.
68
+Fuzzers are kept in tests/qtest/fuzz/ and should be added to
69
+tests/qtest/fuzz/Makefile.include
70
+
71
+Fuzzers can rely on both qtest and libqos to communicate with virtual devices.
72
+
73
+1. Create a new source file. For example ``tests/qtest/fuzz/foo-device-fuzz.c``.
74
+
75
+2. Write the fuzzing code using the libqtest/libqos API. See existing fuzzers
76
+for reference.
77
+
78
+3. Register the fuzzer in ``tests/fuzz/Makefile.include`` by appending the
79
+corresponding object to fuzz-obj-y
80
+
81
+Fuzzers can be more-or-less thought of as special qtest programs which can
82
+modify the qtest commands and/or qtest command arguments based on inputs
83
+provided by libfuzzer. Libfuzzer passes a byte array and length. Commonly the
84
+fuzzer loops over the byte-array interpreting it as a list of qtest commands,
85
+addresses, or values.
86
+
87
+= Implementation Details =
88
+
89
+== The Fuzzer's Lifecycle ==
90
+
91
+The fuzzer has two entrypoints that libfuzzer calls. libfuzzer provides it's
92
+own main(), which performs some setup, and calls the entrypoints:
93
+
94
+LLVMFuzzerInitialize: called prior to fuzzing. Used to initialize all of the
95
+necessary state
96
+
97
+LLVMFuzzerTestOneInput: called for each fuzzing run. Processes the input and
98
+resets the state at the end of each run.
99
+
100
+In more detail:
101
+
102
+LLVMFuzzerInitialize parses the arguments to the fuzzer (must start with two
103
+dashes, so they are ignored by libfuzzer main()). Currently, the arguments
104
+select the fuzz target. Then, the qtest client is initialized. If the target
105
+requires qos, qgraph is set up and the QOM/LIBQOS modules are initialized.
106
+Then the QGraph is walked and the QEMU cmd_line is determined and saved.
107
+
108
+After this, the vl.c:qemu__main is called to set up the guest. There are
109
+target-specific hooks that can be called before and after qemu_main, for
110
+additional setup(e.g. PCI setup, or VM snapshotting).
111
+
112
+LLVMFuzzerTestOneInput: Uses qtest/qos functions to act based on the fuzz
113
+input. It is also responsible for manually calling the main loop/main_loop_wait
114
+to ensure that bottom halves are executed and any cleanup required before the
115
+next input.
116
+
117
+Since the same process is reused for many fuzzing runs, QEMU state needs to
118
+be reset at the end of each run. There are currently two implemented
119
+options for resetting state:
120
+1. Reboot the guest between runs.
121
+ Pros: Straightforward and fast for simple fuzz targets.
122
+ Cons: Depending on the device, does not reset all device state. If the
123
+ device requires some initialization prior to being ready for fuzzing
124
+ (common for QOS-based targets), this initialization needs to be done after
125
+ each reboot.
126
+ Example target: i440fx-qtest-reboot-fuzz
127
+2. Run each test case in a separate forked process and copy the coverage
128
+ information back to the parent. This is fairly similar to AFL's "deferred"
129
+ fork-server mode [3]
130
+ Pros: Relatively fast. Devices only need to be initialized once. No need
131
+ to do slow reboots or vmloads.
132
+ Cons: Not officially supported by libfuzzer. Does not work well for devices
133
+ that rely on dedicated threads.
134
+ Example target: virtio-net-fork-fuzz
35
--
135
--
36
2.24.1
136
2.24.1
37
137
38
diff view generated by jsdifflib