1
The following changes since commit 98b2faeaee96ab084d0b1669918688d8895c155f:
1
The following changes since commit 9cf289af47bcfae5c75de37d8e5d6fd23705322c:
2
2
3
Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging (2017-02-10 18:07:02 +0000)
3
Merge tag 'qga-pull-request' of gitlab.com:marcandre.lureau/qemu into staging (2022-05-04 03:42:49 -0700)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://github.com/XanClic/qemu.git tags/pull-block-2017-02-12
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 10d6eda1926804a09aa0710ca62933087813de0b:
9
for you to fetch changes up to bef2e050d6a7feb865854c65570c496ac5a8cf53:
10
10
11
qemu-img: Avoid setting ret to unused value in img_convert() (2017-02-12 00:56:32 +0100)
11
util/event-loop-base: Introduce options to set the thread pool size (2022-05-04 17:02:19 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches
14
Pull request
15
16
Add new thread-pool-min/thread-pool-max parameters to control the thread pool
17
used for async I/O.
15
18
16
----------------------------------------------------------------
19
----------------------------------------------------------------
17
Alberto Garcia (2):
18
qcow2: Optimize the refcount-block overlap check
19
qemu-io: don't allow I/O operations larger than BDRV_REQUEST_MAX_BYTES
20
20
21
Daniel P. Berrange (1):
21
Nicolas Saenz Julienne (3):
22
iotests: record separate timings per format,protocol pair
22
Introduce event-loop-base abstract class
23
util/main-loop: Introduce the main loop into QOM
24
util/event-loop-base: Introduce options to set the thread pool size
23
25
24
Dou Liyang (2):
26
qapi/qom.json | 43 ++++++++--
25
block/qapi: reduce the coupling between the bdrv_query_stats and bdrv_query_bds_stats
27
meson.build | 26 +++---
26
block/qapi: reduce the execution time of qmp_query_blockstats
28
include/block/aio.h | 10 +++
29
include/block/thread-pool.h | 3 +
30
include/qemu/main-loop.h | 10 +++
31
include/sysemu/event-loop-base.h | 41 +++++++++
32
include/sysemu/iothread.h | 6 +-
33
event-loop-base.c | 140 +++++++++++++++++++++++++++++++
34
iothread.c | 68 +++++----------
35
util/aio-posix.c | 1 +
36
util/async.c | 20 +++++
37
util/main-loop.c | 65 ++++++++++++++
38
util/thread-pool.c | 55 +++++++++++-
39
13 files changed, 419 insertions(+), 69 deletions(-)
40
create mode 100644 include/sysemu/event-loop-base.h
41
create mode 100644 event-loop-base.c
27
42
28
Fam Zheng (2):
43
--
29
qapi: Tweak error message of bdrv_query_image_info
44
2.35.1
30
iotests: Fix reference output for 059
31
32
Jeff Cody (3):
33
block: check full backing filename when searching protocol filenames
34
qemu-iotests: Don't create fifos / pidfiles with protocol paths
35
qemu-iotest: test to lookup protocol-based image with relative backing
36
37
Max Reitz (1):
38
qemu-img: Improve commit invalid base message
39
40
Nir Soffer (3):
41
qemu-io: Return non-zero exit code on failure
42
qemu-iotests: Add _unsupported_fmt helper
43
qemu-io: Add failure regression tests
44
45
Peter Lieven (2):
46
block/nfs: fix NULL pointer dereference in URI parsing
47
block/nfs: fix naming of runtime opts
48
49
Peter Maydell (2):
50
qemu-img: Use qemu_strtoul() rather than raw strtoul()
51
qemu-img: Avoid setting ret to unused value in img_convert()
52
53
QingFeng Hao (2):
54
iotests: Fix a problem in common.filter
55
block/vmdk: Fix the endian problem of buf_len and lba
56
57
Vladimir Sementsov-Ogievskiy (1):
58
block: bdrv_invalidate_cache: invalidate children first
59
60
tests/qemu-iotests/Makefile | 2 +-
61
block/qcow2.h | 1 +
62
block.c | 24 +++++++---
63
block/nfs.c | 49 ++++++++++----------
64
block/qapi.c | 99 +++++++++++++++++-----------------------
65
block/qcow2-refcount.c | 24 +++++++++-
66
block/qcow2.c | 1 +
67
block/vmdk.c | 4 +-
68
qemu-img.c | 44 +++++++++---------
69
qemu-io-cmds.c | 20 +++++---
70
qemu-io.c | 8 +++-
71
tests/qemu-iotests/.gitignore | 2 +-
72
tests/qemu-iotests/059.out | 5 +-
73
tests/qemu-iotests/070.out | 1 -
74
tests/qemu-iotests/075.out | 7 ---
75
tests/qemu-iotests/076.out | 3 --
76
tests/qemu-iotests/078.out | 6 ---
77
tests/qemu-iotests/080.out | 18 --------
78
tests/qemu-iotests/083.out | 17 -------
79
tests/qemu-iotests/088.out | 6 ---
80
tests/qemu-iotests/092.out | 12 -----
81
tests/qemu-iotests/116.out | 7 ---
82
tests/qemu-iotests/131.out | 1 -
83
tests/qemu-iotests/140.out | 1 -
84
tests/qemu-iotests/173 | 97 +++++++++++++++++++++++++++++++++++++++
85
tests/qemu-iotests/173.out | 12 +++++
86
tests/qemu-iotests/174 | 59 ++++++++++++++++++++++++
87
tests/qemu-iotests/174.out | 7 +++
88
tests/qemu-iotests/check | 12 +++--
89
tests/qemu-iotests/common.config | 6 ++-
90
tests/qemu-iotests/common.filter | 2 +-
91
tests/qemu-iotests/common.qemu | 10 ++--
92
tests/qemu-iotests/common.rc | 17 +++++--
93
tests/qemu-iotests/group | 2 +
94
34 files changed, 366 insertions(+), 220 deletions(-)
95
create mode 100755 tests/qemu-iotests/173
96
create mode 100644 tests/qemu-iotests/173.out
97
create mode 100755 tests/qemu-iotests/174
98
create mode 100644 tests/qemu-iotests/174.out
99
diff view generated by jsdifflib
Deleted patch
1
From: QingFeng Hao <haoqf@linux.vnet.ibm.com>
2
1
3
If TEST_DIR is set to /tmp, test case 144 will fail. The reason is that
4
TEST_DIR resembles 144's test image name tmp.qcow2.
5
When 144 is testing $TEST_DIR/tmp.qcow2, it wants to replace
6
$TEST_DIR/tmp.qcow2 to TEST_DIR/tmp.qcow2, but actually it will fail
7
and get TEST_DIRTEST_DIR.qcow2 in this case.
8
The fix is just to modify the code to replace $TEST_DIR/ with TEST_DIR/.
9
10
Signed-off-by: QingFeng Hao <haoqf@linux.vnet.ibm.com>
11
Message-id: 20161216054723.96055-2-haoqf@linux.vnet.ibm.com
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
[mreitz: Fixed commit message and dropped superfluous escaping]
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
tests/qemu-iotests/common.filter | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
18
19
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
20
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/common.filter
22
+++ b/tests/qemu-iotests/common.filter
23
@@ -XXX,XX +XXX,XX @@ _filter_generated_node_ids()
24
# replace occurrences of the actual TEST_DIR value with TEST_DIR
25
_filter_testdir()
26
{
27
- sed -e "s#$TEST_DIR#TEST_DIR#g"
28
+ sed -e "s#$TEST_DIR/#TEST_DIR/#g"
29
}
30
31
# replace occurrences of the actual IMGFMT value with IMGFMT
32
--
33
2.11.0
34
35
diff view generated by jsdifflib
Deleted patch
1
When trying to invoke qemu-img commit with a base image file name that
2
is not part of the top image's backing chain, the user receives a rather
3
plain "Base not found" error message. This is not really helpful because
4
it does not explain what "not found" means, potentially leaving the user
5
wondering why qemu cannot find a file despite it clearly existing in the
6
file system.
7
1
8
Improve the error message by clarifying that "not found" means "not
9
found in the top image's backing chain".
10
11
Reported-by: Ala Hino <ahino@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 20161201020508.24417-1-mreitz@redhat.com
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
qemu-img.c | 4 +++-
18
1 file changed, 3 insertions(+), 1 deletion(-)
19
20
diff --git a/qemu-img.c b/qemu-img.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/qemu-img.c
23
+++ b/qemu-img.c
24
@@ -XXX,XX +XXX,XX @@ static int img_commit(int argc, char **argv)
25
if (base) {
26
base_bs = bdrv_find_backing_image(bs, base);
27
if (!base_bs) {
28
- error_setg(&local_err, QERR_BASE_NOT_FOUND, base);
29
+ error_setg(&local_err,
30
+ "Did not find '%s' in the backing chain of '%s'",
31
+ base, filename);
32
goto done;
33
}
34
} else {
35
--
36
2.11.0
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
@bs doesn't always have a device name, such as when it comes from
4
"qemu-img info". Report file name instead.
5
6
Signed-off-by: Fam Zheng <famz@redhat.com>
7
Message-id: 20170119130759.28319-2-famz@redhat.com
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/qapi.c | 4 ++--
12
1 file changed, 2 insertions(+), 2 deletions(-)
13
14
diff --git a/block/qapi.c b/block/qapi.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/qapi.c
17
+++ b/block/qapi.c
18
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
19
20
size = bdrv_getlength(bs);
21
if (size < 0) {
22
- error_setg_errno(errp, -size, "Can't get size of device '%s'",
23
- bdrv_get_device_name(bs));
24
+ error_setg_errno(errp, -size, "Can't get image size '%s'",
25
+ bs->exact_filename);
26
goto out;
27
}
28
29
--
30
2.11.0
31
32
diff view generated by jsdifflib
1
From: Dou Liyang <douly.fnst@cn.fujitsu.com>
1
From: Nicolas Saenz Julienne <nsaenzju@redhat.com>
2
2
3
In order to reduce the execution time, this patch optimize
3
Introduce the 'event-loop-base' abstract class, it'll hold the
4
the qmp_query_blockstats():
4
properties common to all event loops and provide the necessary hooks for
5
Remove the next_query_bds function.
5
their creation and maintenance. Then have iothread inherit from it.
6
Remove the bdrv_query_stats function.
6
7
Remove some judgement sentence.
7
EventLoopBaseClass is defined as user creatable and provides a hook for
8
8
its children to attach themselves to the user creatable class 'complete'
9
The original qmp_query_blockstats calls next_query_bds to get
9
function. It also provides an update_params() callback to propagate
10
the next objects in each loops. In the next_query_bds, it checks
10
property changes onto its children.
11
the query_nodes and blk. It also call bdrv_query_stats to get
11
12
the stats, In the bdrv_query_stats, it checks blk and bs each
12
The new 'event-loop-base' class will live in the root directory. It is
13
times. This waste more times, which may stall the main loop a
13
built on its own using the 'link_whole' option (there are no direct
14
bit. And if the disk is too many and donot use the dataplane
14
function dependencies between the class and its children, it all happens
15
feature, this may affect the performance in main loop thread.
15
trough 'constructor' magic). And also imposes new compilation
16
16
dependencies:
17
This patch removes that two functions, and makes the structure
17
18
clearly.
18
qom <- event-loop-base <- blockdev (iothread.c)
19
19
20
Signed-off-by: Dou Liyang <douly.fnst@cn.fujitsu.com>
20
And in subsequent patches:
21
Message-id: 1484467275-27919-3-git-send-email-douly.fnst@cn.fujitsu.com
21
22
Reviewed-by: Markus Armbruster <armbru@redhat.com>
22
qom <- event-loop-base <- qemuutil (util/main-loop.c)
23
[mreitz: Removed duplicate info->value assignment]
23
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
All this forced some amount of reordering in meson.build:
25
26
- Moved qom build definition before qemuutil. Doing it the other way
27
around (i.e. moving qemuutil after qom) isn't possible as a lot of
28
core libraries that live in between the two depend on it.
29
30
- Process the 'hw' subdir earlier, as it introduces files into the
31
'qom' source set.
32
33
No functional changes intended.
34
35
Signed-off-by: Nicolas Saenz Julienne <nsaenzju@redhat.com>
36
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
37
Acked-by: Markus Armbruster <armbru@redhat.com>
38
Message-id: 20220425075723.20019-2-nsaenzju@redhat.com
39
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
25
---
40
---
26
block/qapi.c | 73 ++++++++++++++++++++++++------------------------------------
41
qapi/qom.json | 22 +++++--
27
1 file changed, 29 insertions(+), 44 deletions(-)
42
meson.build | 23 ++++---
28
43
include/sysemu/event-loop-base.h | 36 +++++++++++
29
diff --git a/block/qapi.c b/block/qapi.c
44
include/sysemu/iothread.h | 6 +-
45
event-loop-base.c | 104 +++++++++++++++++++++++++++++++
46
iothread.c | 65 ++++++-------------
47
6 files changed, 192 insertions(+), 64 deletions(-)
48
create mode 100644 include/sysemu/event-loop-base.h
49
create mode 100644 event-loop-base.c
50
51
diff --git a/qapi/qom.json b/qapi/qom.json
30
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
31
--- a/block/qapi.c
53
--- a/qapi/qom.json
32
+++ b/block/qapi.c
54
+++ b/qapi/qom.json
33
@@ -XXX,XX +XXX,XX @@ static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs,
55
@@ -XXX,XX +XXX,XX @@
34
return s;
56
'*repeat': 'bool',
57
'*grab-toggle': 'GrabToggleKeys' } }
58
59
+##
60
+# @EventLoopBaseProperties:
61
+#
62
+# Common properties for event loops
63
+#
64
+# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
65
+# 0 means that the engine will use its default.
66
+# (default: 0)
67
+#
68
+# Since: 7.1
69
+##
70
+{ 'struct': 'EventLoopBaseProperties',
71
+ 'data': { '*aio-max-batch': 'int' } }
72
+
73
##
74
# @IothreadProperties:
75
#
76
@@ -XXX,XX +XXX,XX @@
77
# algorithm detects it is spending too long polling without
78
# encountering events. 0 selects a default behaviour (default: 0)
79
#
80
-# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
81
-# 0 means that the engine will use its default
82
-# (default:0, since 6.1)
83
+# The @aio-max-batch option is available since 6.1.
84
#
85
# Since: 2.0
86
##
87
{ 'struct': 'IothreadProperties',
88
+ 'base': 'EventLoopBaseProperties',
89
'data': { '*poll-max-ns': 'int',
90
'*poll-grow': 'int',
91
- '*poll-shrink': 'int',
92
- '*aio-max-batch': 'int' } }
93
+ '*poll-shrink': 'int' } }
94
95
##
96
# @MemoryBackendProperties:
97
diff --git a/meson.build b/meson.build
98
index XXXXXXX..XXXXXXX 100644
99
--- a/meson.build
100
+++ b/meson.build
101
@@ -XXX,XX +XXX,XX @@ subdir('qom')
102
subdir('authz')
103
subdir('crypto')
104
subdir('ui')
105
+subdir('hw')
106
107
108
if enable_modules
109
@@ -XXX,XX +XXX,XX @@ if enable_modules
110
modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
111
endif
112
113
+qom_ss = qom_ss.apply(config_host, strict: false)
114
+libqom = static_library('qom', qom_ss.sources() + genh,
115
+ dependencies: [qom_ss.dependencies()],
116
+ name_suffix: 'fa')
117
+qom = declare_dependency(link_whole: libqom)
118
+
119
+event_loop_base = files('event-loop-base.c')
120
+event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
121
+ build_by_default: true)
122
+event_loop_base = declare_dependency(link_whole: event_loop_base,
123
+ dependencies: [qom])
124
+
125
stub_ss = stub_ss.apply(config_all, strict: false)
126
127
util_ss.add_all(trace_ss)
128
@@ -XXX,XX +XXX,XX @@ subdir('monitor')
129
subdir('net')
130
subdir('replay')
131
subdir('semihosting')
132
-subdir('hw')
133
subdir('tcg')
134
subdir('fpu')
135
subdir('accel')
136
@@ -XXX,XX +XXX,XX @@ qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
137
capture: true,
138
command: [undefsym, nm, '@INPUT@'])
139
140
-qom_ss = qom_ss.apply(config_host, strict: false)
141
-libqom = static_library('qom', qom_ss.sources() + genh,
142
- dependencies: [qom_ss.dependencies()],
143
- name_suffix: 'fa')
144
-
145
-qom = declare_dependency(link_whole: libqom)
146
-
147
authz_ss = authz_ss.apply(config_host, strict: false)
148
libauthz = static_library('authz', authz_ss.sources() + genh,
149
dependencies: [authz_ss.dependencies()],
150
@@ -XXX,XX +XXX,XX @@ libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
151
build_by_default: false)
152
153
blockdev = declare_dependency(link_whole: [libblockdev],
154
- dependencies: [block])
155
+ dependencies: [block, event_loop_base])
156
157
qmp_ss = qmp_ss.apply(config_host, strict: false)
158
libqmp = static_library('qmp', qmp_ss.sources() + genh,
159
diff --git a/include/sysemu/event-loop-base.h b/include/sysemu/event-loop-base.h
160
new file mode 100644
161
index XXXXXXX..XXXXXXX
162
--- /dev/null
163
+++ b/include/sysemu/event-loop-base.h
164
@@ -XXX,XX +XXX,XX @@
165
+/*
166
+ * QEMU event-loop backend
167
+ *
168
+ * Copyright (C) 2022 Red Hat Inc
169
+ *
170
+ * Authors:
171
+ * Nicolas Saenz Julienne <nsaenzju@redhat.com>
172
+ *
173
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
174
+ * See the COPYING file in the top-level directory.
175
+ */
176
+#ifndef QEMU_EVENT_LOOP_BASE_H
177
+#define QEMU_EVENT_LOOP_BASE_H
178
+
179
+#include "qom/object.h"
180
+#include "block/aio.h"
181
+#include "qemu/typedefs.h"
182
+
183
+#define TYPE_EVENT_LOOP_BASE "event-loop-base"
184
+OBJECT_DECLARE_TYPE(EventLoopBase, EventLoopBaseClass,
185
+ EVENT_LOOP_BASE)
186
+
187
+struct EventLoopBaseClass {
188
+ ObjectClass parent_class;
189
+
190
+ void (*init)(EventLoopBase *base, Error **errp);
191
+ void (*update_params)(EventLoopBase *base, Error **errp);
192
+};
193
+
194
+struct EventLoopBase {
195
+ Object parent;
196
+
197
+ /* AioContext AIO engine parameters */
198
+ int64_t aio_max_batch;
199
+};
200
+#endif
201
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
202
index XXXXXXX..XXXXXXX 100644
203
--- a/include/sysemu/iothread.h
204
+++ b/include/sysemu/iothread.h
205
@@ -XXX,XX +XXX,XX @@
206
#include "block/aio.h"
207
#include "qemu/thread.h"
208
#include "qom/object.h"
209
+#include "sysemu/event-loop-base.h"
210
211
#define TYPE_IOTHREAD "iothread"
212
213
struct IOThread {
214
- Object parent_obj;
215
+ EventLoopBase parent_obj;
216
217
QemuThread thread;
218
AioContext *ctx;
219
@@ -XXX,XX +XXX,XX @@ struct IOThread {
220
int64_t poll_max_ns;
221
int64_t poll_grow;
222
int64_t poll_shrink;
223
-
224
- /* AioContext AIO engine parameters */
225
- int64_t aio_max_batch;
226
};
227
typedef struct IOThread IOThread;
228
229
diff --git a/event-loop-base.c b/event-loop-base.c
230
new file mode 100644
231
index XXXXXXX..XXXXXXX
232
--- /dev/null
233
+++ b/event-loop-base.c
234
@@ -XXX,XX +XXX,XX @@
235
+/*
236
+ * QEMU event-loop base
237
+ *
238
+ * Copyright (C) 2022 Red Hat Inc
239
+ *
240
+ * Authors:
241
+ * Stefan Hajnoczi <stefanha@redhat.com>
242
+ * Nicolas Saenz Julienne <nsaenzju@redhat.com>
243
+ *
244
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
245
+ * See the COPYING file in the top-level directory.
246
+ */
247
+
248
+#include "qemu/osdep.h"
249
+#include "qom/object_interfaces.h"
250
+#include "qapi/error.h"
251
+#include "sysemu/event-loop-base.h"
252
+
253
+typedef struct {
254
+ const char *name;
255
+ ptrdiff_t offset; /* field's byte offset in EventLoopBase struct */
256
+} EventLoopBaseParamInfo;
257
+
258
+static EventLoopBaseParamInfo aio_max_batch_info = {
259
+ "aio-max-batch", offsetof(EventLoopBase, aio_max_batch),
260
+};
261
+
262
+static void event_loop_base_get_param(Object *obj, Visitor *v,
263
+ const char *name, void *opaque, Error **errp)
264
+{
265
+ EventLoopBase *event_loop_base = EVENT_LOOP_BASE(obj);
266
+ EventLoopBaseParamInfo *info = opaque;
267
+ int64_t *field = (void *)event_loop_base + info->offset;
268
+
269
+ visit_type_int64(v, name, field, errp);
270
+}
271
+
272
+static void event_loop_base_set_param(Object *obj, Visitor *v,
273
+ const char *name, void *opaque, Error **errp)
274
+{
275
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(obj);
276
+ EventLoopBase *base = EVENT_LOOP_BASE(obj);
277
+ EventLoopBaseParamInfo *info = opaque;
278
+ int64_t *field = (void *)base + info->offset;
279
+ int64_t value;
280
+
281
+ if (!visit_type_int64(v, name, &value, errp)) {
282
+ return;
283
+ }
284
+
285
+ if (value < 0) {
286
+ error_setg(errp, "%s value must be in range [0, %" PRId64 "]",
287
+ info->name, INT64_MAX);
288
+ return;
289
+ }
290
+
291
+ *field = value;
292
+
293
+ if (bc->update_params) {
294
+ bc->update_params(base, errp);
295
+ }
296
+
297
+ return;
298
+}
299
+
300
+static void event_loop_base_complete(UserCreatable *uc, Error **errp)
301
+{
302
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(uc);
303
+ EventLoopBase *base = EVENT_LOOP_BASE(uc);
304
+
305
+ if (bc->init) {
306
+ bc->init(base, errp);
307
+ }
308
+}
309
+
310
+static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
311
+{
312
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
313
+ ucc->complete = event_loop_base_complete;
314
+
315
+ object_class_property_add(klass, "aio-max-batch", "int",
316
+ event_loop_base_get_param,
317
+ event_loop_base_set_param,
318
+ NULL, &aio_max_batch_info);
319
+}
320
+
321
+static const TypeInfo event_loop_base_info = {
322
+ .name = TYPE_EVENT_LOOP_BASE,
323
+ .parent = TYPE_OBJECT,
324
+ .instance_size = sizeof(EventLoopBase),
325
+ .class_size = sizeof(EventLoopBaseClass),
326
+ .class_init = event_loop_base_class_init,
327
+ .abstract = true,
328
+ .interfaces = (InterfaceInfo[]) {
329
+ { TYPE_USER_CREATABLE },
330
+ { }
331
+ }
332
+};
333
+
334
+static void register_types(void)
335
+{
336
+ type_register_static(&event_loop_base_info);
337
+}
338
+type_init(register_types);
339
diff --git a/iothread.c b/iothread.c
340
index XXXXXXX..XXXXXXX 100644
341
--- a/iothread.c
342
+++ b/iothread.c
343
@@ -XXX,XX +XXX,XX @@
344
#include "qemu/module.h"
345
#include "block/aio.h"
346
#include "block/block.h"
347
+#include "sysemu/event-loop-base.h"
348
#include "sysemu/iothread.h"
349
#include "qapi/error.h"
350
#include "qapi/qapi-commands-misc.h"
351
@@ -XXX,XX +XXX,XX @@ static void iothread_init_gcontext(IOThread *iothread)
352
iothread->main_loop = g_main_loop_new(iothread->worker_context, TRUE);
35
}
353
}
36
354
37
-static BlockStats *bdrv_query_stats(BlockBackend *blk,
355
-static void iothread_set_aio_context_params(IOThread *iothread, Error **errp)
38
- const BlockDriverState *bs,
356
+static void iothread_set_aio_context_params(EventLoopBase *base, Error **errp)
39
- bool query_backing)
357
{
358
+ IOThread *iothread = IOTHREAD(base);
359
ERRP_GUARD();
360
361
+ if (!iothread->ctx) {
362
+ return;
363
+ }
364
+
365
aio_context_set_poll_params(iothread->ctx,
366
iothread->poll_max_ns,
367
iothread->poll_grow,
368
@@ -XXX,XX +XXX,XX @@ static void iothread_set_aio_context_params(IOThread *iothread, Error **errp)
369
}
370
371
aio_context_set_aio_params(iothread->ctx,
372
- iothread->aio_max_batch,
373
+ iothread->parent_obj.aio_max_batch,
374
errp);
375
}
376
377
-static void iothread_complete(UserCreatable *obj, Error **errp)
378
+
379
+static void iothread_init(EventLoopBase *base, Error **errp)
380
{
381
Error *local_error = NULL;
382
- IOThread *iothread = IOTHREAD(obj);
383
+ IOThread *iothread = IOTHREAD(base);
384
char *thread_name;
385
386
iothread->stopping = false;
387
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
388
*/
389
iothread_init_gcontext(iothread);
390
391
- iothread_set_aio_context_params(iothread, &local_error);
392
+ iothread_set_aio_context_params(base, &local_error);
393
if (local_error) {
394
error_propagate(errp, local_error);
395
aio_context_unref(iothread->ctx);
396
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
397
* to inherit.
398
*/
399
thread_name = g_strdup_printf("IO %s",
400
- object_get_canonical_path_component(OBJECT(obj)));
401
+ object_get_canonical_path_component(OBJECT(base)));
402
qemu_thread_create(&iothread->thread, thread_name, iothread_run,
403
iothread, QEMU_THREAD_JOINABLE);
404
g_free(thread_name);
405
@@ -XXX,XX +XXX,XX @@ static IOThreadParamInfo poll_grow_info = {
406
static IOThreadParamInfo poll_shrink_info = {
407
"poll-shrink", offsetof(IOThread, poll_shrink),
408
};
409
-static IOThreadParamInfo aio_max_batch_info = {
410
- "aio-max-batch", offsetof(IOThread, aio_max_batch),
411
-};
412
413
static void iothread_get_param(Object *obj, Visitor *v,
414
const char *name, IOThreadParamInfo *info, Error **errp)
415
@@ -XXX,XX +XXX,XX @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
416
}
417
}
418
419
-static void iothread_get_aio_param(Object *obj, Visitor *v,
420
- const char *name, void *opaque, Error **errp)
40
-{
421
-{
41
- BlockStats *s;
422
- IOThreadParamInfo *info = opaque;
42
-
423
-
43
- s = bdrv_query_bds_stats(bs, query_backing);
424
- iothread_get_param(obj, v, name, info, errp);
44
-
425
-}
45
- if (blk) {
426
-
46
- s->has_device = true;
427
-static void iothread_set_aio_param(Object *obj, Visitor *v,
47
- s->device = g_strdup(blk_name(blk));
428
- const char *name, void *opaque, Error **errp)
48
- bdrv_query_blk_stats(s->stats, blk);
429
-{
430
- IOThread *iothread = IOTHREAD(obj);
431
- IOThreadParamInfo *info = opaque;
432
-
433
- if (!iothread_set_param(obj, v, name, info, errp)) {
434
- return;
49
- }
435
- }
50
-
436
-
51
- return s;
437
- if (iothread->ctx) {
438
- aio_context_set_aio_params(iothread->ctx,
439
- iothread->aio_max_batch,
440
- errp);
441
- }
52
-}
442
-}
53
-
443
-
54
BlockInfoList *qmp_query_block(Error **errp)
444
static void iothread_class_init(ObjectClass *klass, void *class_data)
55
{
445
{
56
BlockInfoList *head = NULL, **p_next = &head;
446
- UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
57
@@ -XXX,XX +XXX,XX @@ BlockInfoList *qmp_query_block(Error **errp)
447
- ucc->complete = iothread_complete;
58
return head;
448
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_CLASS(klass);
449
+
450
+ bc->init = iothread_init;
451
+ bc->update_params = iothread_set_aio_context_params;
452
453
object_class_property_add(klass, "poll-max-ns", "int",
454
iothread_get_poll_param,
455
@@ -XXX,XX +XXX,XX @@ static void iothread_class_init(ObjectClass *klass, void *class_data)
456
iothread_get_poll_param,
457
iothread_set_poll_param,
458
NULL, &poll_shrink_info);
459
- object_class_property_add(klass, "aio-max-batch", "int",
460
- iothread_get_aio_param,
461
- iothread_set_aio_param,
462
- NULL, &aio_max_batch_info);
59
}
463
}
60
464
61
-static bool next_query_bds(BlockBackend **blk, BlockDriverState **bs,
465
static const TypeInfo iothread_info = {
62
- bool query_nodes)
466
.name = TYPE_IOTHREAD,
63
-{
467
- .parent = TYPE_OBJECT,
64
- if (query_nodes) {
468
+ .parent = TYPE_EVENT_LOOP_BASE,
65
- *bs = bdrv_next_node(*bs);
469
.class_init = iothread_class_init,
66
- return !!*bs;
470
.instance_size = sizeof(IOThread),
67
- }
471
.instance_init = iothread_instance_init,
68
-
472
.instance_finalize = iothread_instance_finalize,
69
- *blk = blk_next(*blk);
473
- .interfaces = (InterfaceInfo[]) {
70
- *bs = *blk ? blk_bs(*blk) : NULL;
474
- {TYPE_USER_CREATABLE},
71
-
475
- {}
72
- return !!*blk;
476
- },
73
-}
477
};
74
-
478
75
BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
479
static void iothread_register_types(void)
76
bool query_nodes,
480
@@ -XXX,XX +XXX,XX @@ static int query_one_iothread(Object *object, void *opaque)
77
Error **errp)
481
info->poll_max_ns = iothread->poll_max_ns;
78
{
482
info->poll_grow = iothread->poll_grow;
79
BlockStatsList *head = NULL, **p_next = &head;
483
info->poll_shrink = iothread->poll_shrink;
80
- BlockBackend *blk = NULL;
484
- info->aio_max_batch = iothread->aio_max_batch;
81
- BlockDriverState *bs = NULL;
485
+ info->aio_max_batch = iothread->parent_obj.aio_max_batch;
82
+ BlockBackend *blk;
486
83
+ BlockDriverState *bs;
487
QAPI_LIST_APPEND(*tail, info);
84
488
return 0;
85
/* Just to be safe if query_nodes is not always initialized */
86
- query_nodes = has_query_nodes && query_nodes;
87
-
88
- while (next_query_bds(&blk, &bs, query_nodes)) {
89
- BlockStatsList *info = g_malloc0(sizeof(*info));
90
- AioContext *ctx = blk ? blk_get_aio_context(blk)
91
- : bdrv_get_aio_context(bs);
92
+ if (has_query_nodes && query_nodes) {
93
+ for (bs = bdrv_next_node(NULL); bs; bs = bdrv_next_node(bs)) {
94
+ BlockStatsList *info = g_malloc0(sizeof(*info));
95
+ AioContext *ctx = bdrv_get_aio_context(bs);
96
97
- aio_context_acquire(ctx);
98
- info->value = bdrv_query_stats(blk, bs, !query_nodes);
99
- aio_context_release(ctx);
100
+ aio_context_acquire(ctx);
101
+ info->value = bdrv_query_bds_stats(bs, false);
102
+ aio_context_release(ctx);
103
104
- *p_next = info;
105
- p_next = &info->next;
106
+ *p_next = info;
107
+ p_next = &info->next;
108
+ }
109
+ } else {
110
+ for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
111
+ BlockStatsList *info = g_malloc0(sizeof(*info));
112
+ AioContext *ctx = blk_get_aio_context(blk);
113
+ BlockStats *s;
114
+
115
+ aio_context_acquire(ctx);
116
+ s = bdrv_query_bds_stats(blk_bs(blk), true);
117
+ s->has_device = true;
118
+ s->device = g_strdup(blk_name(blk));
119
+ bdrv_query_blk_stats(s->stats, blk);
120
+ aio_context_release(ctx);
121
+
122
+ info->value = s;
123
+ *p_next = info;
124
+ p_next = &info->next;
125
+ }
126
}
127
128
return head;
129
--
489
--
130
2.11.0
490
2.35.1
131
132
diff view generated by jsdifflib
1
From: Dou Liyang <douly.fnst@cn.fujitsu.com>
1
From: Nicolas Saenz Julienne <nsaenzju@redhat.com>
2
2
3
The bdrv_query_stats and bdrv_query_bds_stats functions need to call
3
'event-loop-base' provides basic property handling for all 'AioContext'
4
each other, that increases the coupling. it also makes the program
4
based event loops. So let's define a new 'MainLoopClass' that inherits
5
complicated and makes some unnecessary tests.
5
from it. This will permit tweaking the main loop's properties through
6
6
qapi as well as through the command line using the '-object' keyword[1].
7
Remove the call from bdrv_query_bds_stats to bdrv_query_stats, just
7
Only one instance of 'MainLoopClass' might be created at any time.
8
take some recursion to make it clearly.
8
9
9
'EventLoopBaseClass' learns a new callback, 'can_be_deleted()' so as to
10
Avoid testing whether the blk is NULL during querying the bds stats.
10
mark 'MainLoop' as non-deletable.
11
It is unnecessary.
11
12
12
[1] For example:
13
Signed-off-by: Dou Liyang <douly.fnst@cn.fujitsu.com>
13
-object main-loop,id=main-loop,aio-max-batch=<value>
14
Message-id: 1484467275-27919-2-git-send-email-douly.fnst@cn.fujitsu.com
14
15
Reviewed-by: Markus Armbruster <armbru@redhat.com>
15
Signed-off-by: Nicolas Saenz Julienne <nsaenzju@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
17
Acked-by: Markus Armbruster <armbru@redhat.com>
18
Message-id: 20220425075723.20019-3-nsaenzju@redhat.com
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
17
---
20
---
18
block/qapi.c | 26 ++++++++++++++------------
21
qapi/qom.json | 13 ++++++++
19
1 file changed, 14 insertions(+), 12 deletions(-)
22
meson.build | 3 +-
20
23
include/qemu/main-loop.h | 10 ++++++
21
diff --git a/block/qapi.c b/block/qapi.c
24
include/sysemu/event-loop-base.h | 1 +
22
index XXXXXXX..XXXXXXX 100644
25
event-loop-base.c | 13 ++++++++
23
--- a/block/qapi.c
26
util/main-loop.c | 56 ++++++++++++++++++++++++++++++++
24
+++ b/block/qapi.c
27
6 files changed, 95 insertions(+), 1 deletion(-)
25
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
28
26
qapi_free_BlockInfo(info);
29
diff --git a/qapi/qom.json b/qapi/qom.json
27
}
30
index XXXXXXX..XXXXXXX 100644
28
31
--- a/qapi/qom.json
29
-static BlockStats *bdrv_query_stats(BlockBackend *blk,
32
+++ b/qapi/qom.json
30
- const BlockDriverState *bs,
33
@@ -XXX,XX +XXX,XX @@
31
- bool query_backing);
34
'*poll-grow': 'int',
32
-
35
'*poll-shrink': 'int' } }
33
static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
36
34
{
37
+##
35
BlockAcctStats *stats = blk_get_stats(blk);
38
+# @MainLoopProperties:
36
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
39
+#
40
+# Properties for the main-loop object.
41
+#
42
+# Since: 7.1
43
+##
44
+{ 'struct': 'MainLoopProperties',
45
+ 'base': 'EventLoopBaseProperties',
46
+ 'data': {} }
47
+
48
##
49
# @MemoryBackendProperties:
50
#
51
@@ -XXX,XX +XXX,XX @@
52
{ 'name': 'input-linux',
53
'if': 'CONFIG_LINUX' },
54
'iothread',
55
+ 'main-loop',
56
{ 'name': 'memory-backend-epc',
57
'if': 'CONFIG_LINUX' },
58
'memory-backend-file',
59
@@ -XXX,XX +XXX,XX @@
60
'input-linux': { 'type': 'InputLinuxProperties',
61
'if': 'CONFIG_LINUX' },
62
'iothread': 'IothreadProperties',
63
+ 'main-loop': 'MainLoopProperties',
64
'memory-backend-epc': { 'type': 'MemoryBackendEpcProperties',
65
'if': 'CONFIG_LINUX' },
66
'memory-backend-file': 'MemoryBackendFileProperties',
67
diff --git a/meson.build b/meson.build
68
index XXXXXXX..XXXXXXX 100644
69
--- a/meson.build
70
+++ b/meson.build
71
@@ -XXX,XX +XXX,XX @@ libqemuutil = static_library('qemuutil',
72
sources: util_ss.sources() + stub_ss.sources() + genh,
73
dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
74
qemuutil = declare_dependency(link_with: libqemuutil,
75
- sources: genh + version_res)
76
+ sources: genh + version_res,
77
+ dependencies: [event_loop_base])
78
79
if have_system or have_user
80
decodetree = generator(find_program('scripts/decodetree.py'),
81
diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
82
index XXXXXXX..XXXXXXX 100644
83
--- a/include/qemu/main-loop.h
84
+++ b/include/qemu/main-loop.h
85
@@ -XXX,XX +XXX,XX @@
86
#define QEMU_MAIN_LOOP_H
87
88
#include "block/aio.h"
89
+#include "qom/object.h"
90
+#include "sysemu/event-loop-base.h"
91
92
#define SIG_IPI SIGUSR1
93
94
+#define TYPE_MAIN_LOOP "main-loop"
95
+OBJECT_DECLARE_TYPE(MainLoop, MainLoopClass, MAIN_LOOP)
96
+
97
+struct MainLoop {
98
+ EventLoopBase parent_obj;
99
+};
100
+typedef struct MainLoop MainLoop;
101
+
102
/**
103
* qemu_init_main_loop: Set up the process so that it can run the main loop.
104
*
105
diff --git a/include/sysemu/event-loop-base.h b/include/sysemu/event-loop-base.h
106
index XXXXXXX..XXXXXXX 100644
107
--- a/include/sysemu/event-loop-base.h
108
+++ b/include/sysemu/event-loop-base.h
109
@@ -XXX,XX +XXX,XX @@ struct EventLoopBaseClass {
110
111
void (*init)(EventLoopBase *base, Error **errp);
112
void (*update_params)(EventLoopBase *base, Error **errp);
113
+ bool (*can_be_deleted)(EventLoopBase *base);
114
};
115
116
struct EventLoopBase {
117
diff --git a/event-loop-base.c b/event-loop-base.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/event-loop-base.c
120
+++ b/event-loop-base.c
121
@@ -XXX,XX +XXX,XX @@ static void event_loop_base_complete(UserCreatable *uc, Error **errp)
37
}
122
}
38
}
123
}
39
124
40
-static void bdrv_query_bds_stats(BlockStats *s, const BlockDriverState *bs,
125
+static bool event_loop_base_can_be_deleted(UserCreatable *uc)
41
+static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs,
126
+{
42
bool query_backing)
127
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(uc);
128
+ EventLoopBase *backend = EVENT_LOOP_BASE(uc);
129
+
130
+ if (bc->can_be_deleted) {
131
+ return bc->can_be_deleted(backend);
132
+ }
133
+
134
+ return true;
135
+}
136
+
137
static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
43
{
138
{
44
+ BlockStats *s = NULL;
139
UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
45
+
140
ucc->complete = event_loop_base_complete;
46
+ s = g_malloc0(sizeof(*s));
141
+ ucc->can_be_deleted = event_loop_base_can_be_deleted;
47
+ s->stats = g_malloc0(sizeof(*s->stats));
142
48
+
143
object_class_property_add(klass, "aio-max-batch", "int",
49
+ if (!bs) {
144
event_loop_base_get_param,
50
+ return s;
145
diff --git a/util/main-loop.c b/util/main-loop.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/util/main-loop.c
148
+++ b/util/main-loop.c
149
@@ -XXX,XX +XXX,XX @@
150
#include "qemu/error-report.h"
151
#include "qemu/queue.h"
152
#include "qemu/compiler.h"
153
+#include "qom/object.h"
154
155
#ifndef _WIN32
156
#include <sys/wait.h>
157
@@ -XXX,XX +XXX,XX @@ int qemu_init_main_loop(Error **errp)
158
return 0;
159
}
160
161
+static void main_loop_update_params(EventLoopBase *base, Error **errp)
162
+{
163
+ if (!qemu_aio_context) {
164
+ error_setg(errp, "qemu aio context not ready");
165
+ return;
51
+ }
166
+ }
52
+
167
+
53
if (bdrv_get_node_name(bs)[0]) {
168
+ aio_context_set_aio_params(qemu_aio_context, base->aio_max_batch, errp);
54
s->has_node_name = true;
169
+}
55
s->node_name = g_strdup(bdrv_get_node_name(bs));
170
+
56
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_bds_stats(BlockStats *s, const BlockDriverState *bs,
171
+MainLoop *mloop;
57
172
+
58
if (bs->file) {
173
+static void main_loop_init(EventLoopBase *base, Error **errp)
59
s->has_parent = true;
174
+{
60
- s->parent = bdrv_query_stats(NULL, bs->file->bs, query_backing);
175
+ MainLoop *m = MAIN_LOOP(base);
61
+ s->parent = bdrv_query_bds_stats(bs->file->bs, query_backing);
176
+
62
}
177
+ if (mloop) {
63
178
+ error_setg(errp, "only one main-loop instance allowed");
64
if (query_backing && bs->backing) {
179
+ return;
65
s->has_backing = true;
180
+ }
66
- s->backing = bdrv_query_stats(NULL, bs->backing->bs, query_backing);
181
+
67
+ s->backing = bdrv_query_bds_stats(bs->backing->bs, query_backing);
182
+ main_loop_update_params(base, errp);
68
}
183
+
69
184
+ mloop = m;
70
+ return s;
185
+ return;
71
}
186
+}
72
187
+
73
static BlockStats *bdrv_query_stats(BlockBackend *blk,
188
+static bool main_loop_can_be_deleted(EventLoopBase *base)
74
@@ -XXX,XX +XXX,XX @@ static BlockStats *bdrv_query_stats(BlockBackend *blk,
189
+{
75
{
190
+ return false;
76
BlockStats *s;
191
+}
77
192
+
78
- s = g_malloc0(sizeof(*s));
193
+static void main_loop_class_init(ObjectClass *oc, void *class_data)
79
- s->stats = g_malloc0(sizeof(*s->stats));
194
+{
80
+ s = bdrv_query_bds_stats(bs, query_backing);
195
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_CLASS(oc);
81
196
+
82
if (blk) {
197
+ bc->init = main_loop_init;
83
s->has_device = true;
198
+ bc->update_params = main_loop_update_params;
84
s->device = g_strdup(blk_name(blk));
199
+ bc->can_be_deleted = main_loop_can_be_deleted;
85
bdrv_query_blk_stats(s->stats, blk);
200
+}
86
}
201
+
87
- if (bs) {
202
+static const TypeInfo main_loop_info = {
88
- bdrv_query_bds_stats(s, bs, query_backing);
203
+ .name = TYPE_MAIN_LOOP,
89
- }
204
+ .parent = TYPE_EVENT_LOOP_BASE,
90
205
+ .class_init = main_loop_class_init,
91
return s;
206
+ .instance_size = sizeof(MainLoop),
92
}
207
+};
208
+
209
+static void main_loop_register_types(void)
210
+{
211
+ type_register_static(&main_loop_info);
212
+}
213
+
214
+type_init(main_loop_register_types)
215
+
216
static int max_priority;
217
218
#ifndef _WIN32
93
--
219
--
94
2.11.0
220
2.35.1
95
96
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Current implementation invalidates firstly parent bds and then its
4
children. This leads to the following bug:
5
6
after incoming migration, in bdrv_invalidate_cache_all:
7
1. invalidate parent bds - reopen it with BDRV_O_INACTIVE cleared
8
2. child is not yet invalidated
9
3. parent check that its BDRV_O_INACTIVE is cleared
10
4. parent writes to child
11
5. assert in bdrv_co_pwritev, as BDRV_O_INACTIVE is set for child
12
13
This patch fixes it by just changing invalidate sequence: invalidate
14
children first.
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Message-id: 20170131112308.54189-1-vsementsov@virtuozzo.com
18
Reviewed-by: Max Reitz <mreitz@redhat.com>
19
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
22
block.c | 11 +++++------
23
1 file changed, 5 insertions(+), 6 deletions(-)
24
25
diff --git a/block.c b/block.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
28
+++ b/block.c
29
@@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
30
if (!(bs->open_flags & BDRV_O_INACTIVE)) {
31
return;
32
}
33
- bs->open_flags &= ~BDRV_O_INACTIVE;
34
35
- if (bs->drv->bdrv_invalidate_cache) {
36
- bs->drv->bdrv_invalidate_cache(bs, &local_err);
37
+ QLIST_FOREACH(child, &bs->children, next) {
38
+ bdrv_invalidate_cache(child->bs, &local_err);
39
if (local_err) {
40
- bs->open_flags |= BDRV_O_INACTIVE;
41
error_propagate(errp, local_err);
42
return;
43
}
44
}
45
46
- QLIST_FOREACH(child, &bs->children, next) {
47
- bdrv_invalidate_cache(child->bs, &local_err);
48
+ bs->open_flags &= ~BDRV_O_INACTIVE;
49
+ if (bs->drv->bdrv_invalidate_cache) {
50
+ bs->drv->bdrv_invalidate_cache(bs, &local_err);
51
if (local_err) {
52
bs->open_flags |= BDRV_O_INACTIVE;
53
error_propagate(errp, local_err);
54
--
55
2.11.0
56
57
diff view generated by jsdifflib
Deleted patch
1
From: Peter Lieven <pl@kamp.de>
2
1
3
parse_uint_full wants to put the parsed value into the
4
variable passed via its second argument which is NULL.
5
6
Fixes: 94d6a7a76e9df9919629428f6c598e2b97d9426c
7
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Peter Lieven <pl@kamp.de>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Message-id: 1485942829-10756-2-git-send-email-pl@kamp.de
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/nfs.c | 3 ++-
14
1 file changed, 2 insertions(+), 1 deletion(-)
15
16
diff --git a/block/nfs.c b/block/nfs.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/nfs.c
19
+++ b/block/nfs.c
20
@@ -XXX,XX +XXX,XX @@ static int nfs_parse_uri(const char *filename, QDict *options, Error **errp)
21
qdict_put(options, "path", qstring_from_str(uri->path));
22
23
for (i = 0; i < qp->n; i++) {
24
+ unsigned long long val;
25
if (!qp->p[i].value) {
26
error_setg(errp, "Value for NFS parameter expected: %s",
27
qp->p[i].name);
28
goto out;
29
}
30
- if (parse_uint_full(qp->p[i].value, NULL, 0)) {
31
+ if (parse_uint_full(qp->p[i].value, &val, 0)) {
32
error_setg(errp, "Illegal value for NFS parameter: %s",
33
qp->p[i].name);
34
goto out;
35
--
36
2.11.0
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Peter Lieven <pl@kamp.de>
2
1
3
commit 94d6a7a accidentally left the naming of runtime opts and QAPI
4
scheme inconsistent. As one consequence passing of parameters in the
5
URI is broken. Sync the naming of the runtime opts to the QAPI
6
scheme.
7
8
Please note that this is technically backwards incompatible with the 2.8
9
release, but the 2.8 release is the only version that had the wrong naming.
10
Furthermore release 2.8 suffered from a NULL pointer dereference during
11
URI parsing.
12
13
Fixes: 94d6a7a76e9df9919629428f6c598e2b97d9426c
14
Cc: qemu-stable@nongnu.org
15
Signed-off-by: Peter Lieven <pl@kamp.de>
16
Message-id: 1485942829-10756-3-git-send-email-pl@kamp.de
17
[mreitz: Fixed commit message]
18
Reviewed-by: Eric Blake <eblake@redhat.com>
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
---
21
block/nfs.c | 46 +++++++++++++++++++++++-----------------------
22
1 file changed, 23 insertions(+), 23 deletions(-)
23
24
diff --git a/block/nfs.c b/block/nfs.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/nfs.c
27
+++ b/block/nfs.c
28
@@ -XXX,XX +XXX,XX @@ static QemuOptsList runtime_opts = {
29
.help = "Path of the image on the host",
30
},
31
{
32
- .name = "uid",
33
+ .name = "user",
34
.type = QEMU_OPT_NUMBER,
35
.help = "UID value to use when talking to the server",
36
},
37
{
38
- .name = "gid",
39
+ .name = "group",
40
.type = QEMU_OPT_NUMBER,
41
.help = "GID value to use when talking to the server",
42
},
43
{
44
- .name = "tcp-syncnt",
45
+ .name = "tcp-syn-count",
46
.type = QEMU_OPT_NUMBER,
47
.help = "Number of SYNs to send during the session establish",
48
},
49
{
50
- .name = "readahead",
51
+ .name = "readahead-size",
52
.type = QEMU_OPT_NUMBER,
53
.help = "Set the readahead size in bytes",
54
},
55
{
56
- .name = "pagecache",
57
+ .name = "page-cache-size",
58
.type = QEMU_OPT_NUMBER,
59
.help = "Set the pagecache size in bytes",
60
},
61
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
62
goto fail;
63
}
64
65
- if (qemu_opt_get(opts, "uid")) {
66
- client->uid = qemu_opt_get_number(opts, "uid", 0);
67
+ if (qemu_opt_get(opts, "user")) {
68
+ client->uid = qemu_opt_get_number(opts, "user", 0);
69
nfs_set_uid(client->context, client->uid);
70
}
71
72
- if (qemu_opt_get(opts, "gid")) {
73
- client->gid = qemu_opt_get_number(opts, "gid", 0);
74
+ if (qemu_opt_get(opts, "group")) {
75
+ client->gid = qemu_opt_get_number(opts, "group", 0);
76
nfs_set_gid(client->context, client->gid);
77
}
78
79
- if (qemu_opt_get(opts, "tcp-syncnt")) {
80
- client->tcp_syncnt = qemu_opt_get_number(opts, "tcp-syncnt", 0);
81
+ if (qemu_opt_get(opts, "tcp-syn-count")) {
82
+ client->tcp_syncnt = qemu_opt_get_number(opts, "tcp-syn-count", 0);
83
nfs_set_tcp_syncnt(client->context, client->tcp_syncnt);
84
}
85
86
#ifdef LIBNFS_FEATURE_READAHEAD
87
- if (qemu_opt_get(opts, "readahead")) {
88
+ if (qemu_opt_get(opts, "readahead-size")) {
89
if (open_flags & BDRV_O_NOCACHE) {
90
error_setg(errp, "Cannot enable NFS readahead "
91
"if cache.direct = on");
92
goto fail;
93
}
94
- client->readahead = qemu_opt_get_number(opts, "readahead", 0);
95
+ client->readahead = qemu_opt_get_number(opts, "readahead-size", 0);
96
if (client->readahead > QEMU_NFS_MAX_READAHEAD_SIZE) {
97
error_report("NFS Warning: Truncating NFS readahead "
98
"size to %d", QEMU_NFS_MAX_READAHEAD_SIZE);
99
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
100
#endif
101
102
#ifdef LIBNFS_FEATURE_PAGECACHE
103
- if (qemu_opt_get(opts, "pagecache")) {
104
+ if (qemu_opt_get(opts, "page-cache-size")) {
105
if (open_flags & BDRV_O_NOCACHE) {
106
error_setg(errp, "Cannot enable NFS pagecache "
107
"if cache.direct = on");
108
goto fail;
109
}
110
- client->pagecache = qemu_opt_get_number(opts, "pagecache", 0);
111
+ client->pagecache = qemu_opt_get_number(opts, "page-cache-size", 0);
112
if (client->pagecache > QEMU_NFS_MAX_PAGECACHE_SIZE) {
113
error_report("NFS Warning: Truncating NFS pagecache "
114
"size to %d pages", QEMU_NFS_MAX_PAGECACHE_SIZE);
115
@@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
116
qdict_put(opts, "path", qstring_from_str(client->path));
117
118
if (client->uid) {
119
- qdict_put(opts, "uid", qint_from_int(client->uid));
120
+ qdict_put(opts, "user", qint_from_int(client->uid));
121
}
122
if (client->gid) {
123
- qdict_put(opts, "gid", qint_from_int(client->gid));
124
+ qdict_put(opts, "group", qint_from_int(client->gid));
125
}
126
if (client->tcp_syncnt) {
127
- qdict_put(opts, "tcp-syncnt",
128
- qint_from_int(client->tcp_syncnt));
129
+ qdict_put(opts, "tcp-syn-cnt",
130
+ qint_from_int(client->tcp_syncnt));
131
}
132
if (client->readahead) {
133
- qdict_put(opts, "readahead",
134
- qint_from_int(client->readahead));
135
+ qdict_put(opts, "readahead-size",
136
+ qint_from_int(client->readahead));
137
}
138
if (client->pagecache) {
139
- qdict_put(opts, "pagecache",
140
- qint_from_int(client->pagecache));
141
+ qdict_put(opts, "page-cache-size",
142
+ qint_from_int(client->pagecache));
143
}
144
if (client->debug) {
145
qdict_put(opts, "debug", qint_from_int(client->debug));
146
--
147
2.11.0
148
149
diff view generated by jsdifflib
Deleted patch
1
From: Nir Soffer <nirsof@gmail.com>
2
1
3
The result of openfile was not checked, leading to failure deep in the
4
actual command with confusing error message, and exiting with exit code 0.
5
6
Here is a simple example - trying to read with the wrong format:
7
8
$ touch file
9
$ qemu-io -f qcow2 -c 'read -P 1 0 1024' file; echo $?
10
can't open device file: Image is not in qcow2 format
11
no file open, try 'help open'
12
0
13
14
With this patch, we fail earlier with exit code 1:
15
16
$ ./qemu-io -f qcow2 -c 'read -P 1 0 1024' file; echo $?
17
can't open device file: Image is not in qcow2 format
18
1
19
20
Failing earlier, we don't log this error now:
21
22
no file open, try 'help open'
23
24
But some tests expected it; the line was removed from the test output.
25
26
Signed-off-by: Nir Soffer <nirsof@gmail.com>
27
Reviewed-by: Eric Blake <eblake@redhat.com>
28
Message-id: 20170201003120.23378-2-nirsof@gmail.com
29
Reviewed-by: Max Reitz <mreitz@redhat.com>
30
Signed-off-by: Max Reitz <mreitz@redhat.com>
31
---
32
qemu-io.c | 8 ++++++--
33
tests/qemu-iotests/059.out | 3 ---
34
tests/qemu-iotests/070.out | 1 -
35
tests/qemu-iotests/075.out | 7 -------
36
tests/qemu-iotests/076.out | 3 ---
37
tests/qemu-iotests/078.out | 6 ------
38
tests/qemu-iotests/080.out | 18 ------------------
39
tests/qemu-iotests/083.out | 17 -----------------
40
tests/qemu-iotests/088.out | 6 ------
41
tests/qemu-iotests/092.out | 12 ------------
42
tests/qemu-iotests/116.out | 7 -------
43
tests/qemu-iotests/131.out | 1 -
44
tests/qemu-iotests/140.out | 1 -
45
13 files changed, 6 insertions(+), 84 deletions(-)
46
47
diff --git a/qemu-io.c b/qemu-io.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/qemu-io.c
50
+++ b/qemu-io.c
51
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
52
exit(1);
53
}
54
opts = qemu_opts_to_qdict(qopts, NULL);
55
- openfile(NULL, flags, writethrough, opts);
56
+ if (openfile(NULL, flags, writethrough, opts)) {
57
+ exit(1);
58
+ }
59
} else {
60
if (format) {
61
opts = qdict_new();
62
qdict_put(opts, "driver", qstring_from_str(format));
63
}
64
- openfile(argv[optind], flags, writethrough, opts);
65
+ if (openfile(argv[optind], flags, writethrough, opts)) {
66
+ exit(1);
67
+ }
68
}
69
}
70
command_loop();
71
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
72
index XXXXXXX..XXXXXXX 100644
73
--- a/tests/qemu-iotests/059.out
74
+++ b/tests/qemu-iotests/059.out
75
@@ -XXX,XX +XXX,XX @@ QA output created by 059
76
=== Testing invalid granularity ===
77
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
78
can't open device TEST_DIR/t.vmdk: Invalid granularity, image may be corrupt
79
-no file open, try 'help open'
80
81
=== Testing too big L2 table size ===
82
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
83
can't open device TEST_DIR/t.vmdk: L2 table size too big
84
-no file open, try 'help open'
85
86
=== Testing too big L1 table size ===
87
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
88
can't open device TEST_DIR/t.vmdk: L1 size too big
89
-no file open, try 'help open'
90
91
=== Testing monolithicFlat creation and opening ===
92
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 subformat=monolithicFlat
93
diff --git a/tests/qemu-iotests/070.out b/tests/qemu-iotests/070.out
94
index XXXXXXX..XXXXXXX 100644
95
--- a/tests/qemu-iotests/070.out
96
+++ b/tests/qemu-iotests/070.out
97
@@ -XXX,XX +XXX,XX @@ QA output created by 070
98
can't open device TEST_DIR/iotest-dirtylog-10G-4M.vhdx: VHDX image file 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx' opened read-only, but contains a log that needs to be replayed
99
To replay the log, run:
100
qemu-img check -r all 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx'
101
- no file open, try 'help open'
102
=== Verify open image replays log ===
103
read 18874368/18874368 bytes at offset 0
104
18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
105
diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out
106
index XXXXXXX..XXXXXXX 100644
107
--- a/tests/qemu-iotests/075.out
108
+++ b/tests/qemu-iotests/075.out
109
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 1048064
110
111
== block_size must be a multiple of 512 ==
112
can't open device TEST_DIR/simple-pattern.cloop: block_size 513 must be a multiple of 512
113
-no file open, try 'help open'
114
115
== block_size cannot be zero ==
116
can't open device TEST_DIR/simple-pattern.cloop: block_size cannot be zero
117
-no file open, try 'help open'
118
119
== huge block_size ===
120
can't open device TEST_DIR/simple-pattern.cloop: block_size 4294966784 must be 64 MB or less
121
-no file open, try 'help open'
122
123
== offsets_size overflow ===
124
can't open device TEST_DIR/simple-pattern.cloop: n_blocks 4294967295 must be 536870911 or less
125
-no file open, try 'help open'
126
127
== refuse images that require too many offsets ===
128
can't open device TEST_DIR/simple-pattern.cloop: image requires too many offsets, try increasing block size
129
-no file open, try 'help open'
130
131
== refuse images with non-monotonically increasing offsets ==
132
can't open device TEST_DIR/simple-pattern.cloop: offsets not monotonically increasing at index 1, image file is corrupt
133
-no file open, try 'help open'
134
135
== refuse images with invalid compressed block size ==
136
can't open device TEST_DIR/simple-pattern.cloop: invalid compressed block size at index 1, image file is corrupt
137
-no file open, try 'help open'
138
*** done
139
diff --git a/tests/qemu-iotests/076.out b/tests/qemu-iotests/076.out
140
index XXXXXXX..XXXXXXX 100644
141
--- a/tests/qemu-iotests/076.out
142
+++ b/tests/qemu-iotests/076.out
143
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
144
145
== Negative catalog size ==
146
can't open device TEST_DIR/parallels-v1: Catalog too large
147
-no file open, try 'help open'
148
149
== Overflow in catalog allocation ==
150
can't open device TEST_DIR/parallels-v1: Catalog too large
151
-no file open, try 'help open'
152
153
== Zero sectors per track ==
154
can't open device TEST_DIR/parallels-v1: Invalid image: Zero sectors per track
155
-no file open, try 'help open'
156
157
== Read from a valid v2 image ==
158
read 65536/65536 bytes at offset 0
159
diff --git a/tests/qemu-iotests/078.out b/tests/qemu-iotests/078.out
160
index XXXXXXX..XXXXXXX 100644
161
--- a/tests/qemu-iotests/078.out
162
+++ b/tests/qemu-iotests/078.out
163
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
164
165
== Negative catalog size ==
166
can't open device TEST_DIR/empty.bochs: Catalog size is too large
167
-no file open, try 'help open'
168
169
== Overflow for catalog size * sizeof(uint32_t) ==
170
can't open device TEST_DIR/empty.bochs: Catalog size is too large
171
-no file open, try 'help open'
172
173
== Too small catalog bitmap for image size ==
174
can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size
175
-no file open, try 'help open'
176
can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size
177
-no file open, try 'help open'
178
179
== Negative extent size ==
180
can't open device TEST_DIR/empty.bochs: Extent size 2147483648 is too large
181
-no file open, try 'help open'
182
183
== Zero extent size ==
184
can't open device TEST_DIR/empty.bochs: Extent size must be at least 512
185
-no file open, try 'help open'
186
*** done
187
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
188
index XXXXXXX..XXXXXXX 100644
189
--- a/tests/qemu-iotests/080.out
190
+++ b/tests/qemu-iotests/080.out
191
@@ -XXX,XX +XXX,XX @@ QA output created by 080
192
== Huge header size ==
193
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
194
can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size
195
-no file open, try 'help open'
196
can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size
197
-no file open, try 'help open'
198
199
== Huge unknown header extension ==
200
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
201
can't open device TEST_DIR/t.qcow2: Invalid backing file offset
202
-no file open, try 'help open'
203
can't open device TEST_DIR/t.qcow2: Header extension too large
204
-no file open, try 'help open'
205
can't open device TEST_DIR/t.qcow2: Header extension too large
206
-no file open, try 'help open'
207
208
== Huge refcount table size ==
209
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
210
can't open device TEST_DIR/t.qcow2: Reference count table too large
211
-no file open, try 'help open'
212
can't open device TEST_DIR/t.qcow2: Reference count table too large
213
-no file open, try 'help open'
214
215
== Misaligned refcount table ==
216
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
217
can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
218
-no file open, try 'help open'
219
220
== Huge refcount offset ==
221
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
222
can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
223
-no file open, try 'help open'
224
225
== Invalid snapshot table ==
226
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
227
can't open device TEST_DIR/t.qcow2: Too many snapshots
228
-no file open, try 'help open'
229
can't open device TEST_DIR/t.qcow2: Too many snapshots
230
-no file open, try 'help open'
231
can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset
232
-no file open, try 'help open'
233
can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset
234
-no file open, try 'help open'
235
236
== Hitting snapshot table size limit ==
237
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
238
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
239
== Invalid L1 table ==
240
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
241
can't open device TEST_DIR/t.qcow2: Active L1 table too large
242
-no file open, try 'help open'
243
can't open device TEST_DIR/t.qcow2: Active L1 table too large
244
-no file open, try 'help open'
245
can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
246
-no file open, try 'help open'
247
can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
248
-no file open, try 'help open'
249
250
== Invalid L1 table (with internal snapshot in the image) ==
251
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
252
@@ -XXX,XX +XXX,XX @@ qemu-img: Could not open 'TEST_DIR/t.IMGFMT': L1 table is too small
253
== Invalid backing file size ==
254
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
255
can't open device TEST_DIR/t.qcow2: Backing file name too long
256
-no file open, try 'help open'
257
258
== Invalid L2 entry (huge physical offset) ==
259
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
260
diff --git a/tests/qemu-iotests/083.out b/tests/qemu-iotests/083.out
261
index XXXXXXX..XXXXXXX 100644
262
--- a/tests/qemu-iotests/083.out
263
+++ b/tests/qemu-iotests/083.out
264
@@ -XXX,XX +XXX,XX @@ QA output created by 083
265
=== Check disconnect before neg1 ===
266
267
can't open device nbd:127.0.0.1:PORT:exportname=foo
268
-no file open, try 'help open'
269
270
=== Check disconnect after neg1 ===
271
272
can't open device nbd:127.0.0.1:PORT:exportname=foo
273
-no file open, try 'help open'
274
275
=== Check disconnect 8 neg1 ===
276
277
can't open device nbd:127.0.0.1:PORT:exportname=foo
278
-no file open, try 'help open'
279
280
=== Check disconnect 16 neg1 ===
281
282
can't open device nbd:127.0.0.1:PORT:exportname=foo
283
-no file open, try 'help open'
284
285
=== Check disconnect before export ===
286
287
can't open device nbd:127.0.0.1:PORT:exportname=foo
288
-no file open, try 'help open'
289
290
=== Check disconnect after export ===
291
292
can't open device nbd:127.0.0.1:PORT:exportname=foo
293
-no file open, try 'help open'
294
295
=== Check disconnect 4 export ===
296
297
can't open device nbd:127.0.0.1:PORT:exportname=foo
298
-no file open, try 'help open'
299
300
=== Check disconnect 12 export ===
301
302
can't open device nbd:127.0.0.1:PORT:exportname=foo
303
-no file open, try 'help open'
304
305
=== Check disconnect 16 export ===
306
307
can't open device nbd:127.0.0.1:PORT:exportname=foo
308
-no file open, try 'help open'
309
310
=== Check disconnect before neg2 ===
311
312
can't open device nbd:127.0.0.1:PORT:exportname=foo
313
-no file open, try 'help open'
314
315
=== Check disconnect after neg2 ===
316
317
@@ -XXX,XX +XXX,XX @@ read failed: Input/output error
318
=== Check disconnect 8 neg2 ===
319
320
can't open device nbd:127.0.0.1:PORT:exportname=foo
321
-no file open, try 'help open'
322
323
=== Check disconnect 10 neg2 ===
324
325
can't open device nbd:127.0.0.1:PORT:exportname=foo
326
-no file open, try 'help open'
327
328
=== Check disconnect before request ===
329
330
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
331
=== Check disconnect before neg-classic ===
332
333
can't open device nbd:127.0.0.1:PORT
334
-no file open, try 'help open'
335
336
=== Check disconnect 8 neg-classic ===
337
338
can't open device nbd:127.0.0.1:PORT
339
-no file open, try 'help open'
340
341
=== Check disconnect 16 neg-classic ===
342
343
can't open device nbd:127.0.0.1:PORT
344
-no file open, try 'help open'
345
346
=== Check disconnect 24 neg-classic ===
347
348
can't open device nbd:127.0.0.1:PORT
349
-no file open, try 'help open'
350
351
=== Check disconnect 28 neg-classic ===
352
353
can't open device nbd:127.0.0.1:PORT
354
-no file open, try 'help open'
355
356
=== Check disconnect after neg-classic ===
357
358
diff --git a/tests/qemu-iotests/088.out b/tests/qemu-iotests/088.out
359
index XXXXXXX..XXXXXXX 100644
360
--- a/tests/qemu-iotests/088.out
361
+++ b/tests/qemu-iotests/088.out
362
@@ -XXX,XX +XXX,XX @@ QA output created by 088
363
== Invalid block size ==
364
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
365
can't open device TEST_DIR/t.vpc: Invalid block size 0
366
-no file open, try 'help open'
367
can't open device TEST_DIR/t.vpc: Invalid block size 0
368
-no file open, try 'help open'
369
can't open device TEST_DIR/t.vpc: Invalid block size 128
370
-no file open, try 'help open'
371
can't open device TEST_DIR/t.vpc: Invalid block size 128
372
-no file open, try 'help open'
373
can't open device TEST_DIR/t.vpc: Invalid block size 305419896
374
-no file open, try 'help open'
375
can't open device TEST_DIR/t.vpc: Invalid block size 305419896
376
-no file open, try 'help open'
377
*** done
378
diff --git a/tests/qemu-iotests/092.out b/tests/qemu-iotests/092.out
379
index XXXXXXX..XXXXXXX 100644
380
--- a/tests/qemu-iotests/092.out
381
+++ b/tests/qemu-iotests/092.out
382
@@ -XXX,XX +XXX,XX @@ QA output created by 092
383
== Invalid cluster size ==
384
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
385
can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
386
-no file open, try 'help open'
387
can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
388
-no file open, try 'help open'
389
can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
390
-no file open, try 'help open'
391
can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
392
-no file open, try 'help open'
393
394
== Invalid L2 table size ==
395
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
396
can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
397
-no file open, try 'help open'
398
can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
399
-no file open, try 'help open'
400
can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
401
-no file open, try 'help open'
402
can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
403
-no file open, try 'help open'
404
405
== Invalid size ==
406
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
407
can't open device TEST_DIR/t.qcow: Image too large
408
-no file open, try 'help open'
409
can't open device TEST_DIR/t.qcow: Image too large
410
-no file open, try 'help open'
411
412
== Invalid backing file length ==
413
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
414
can't open device TEST_DIR/t.qcow: Backing file name too long
415
-no file open, try 'help open'
416
can't open device TEST_DIR/t.qcow: Backing file name too long
417
-no file open, try 'help open'
418
*** done
419
diff --git a/tests/qemu-iotests/116.out b/tests/qemu-iotests/116.out
420
index XXXXXXX..XXXXXXX 100644
421
--- a/tests/qemu-iotests/116.out
422
+++ b/tests/qemu-iotests/116.out
423
@@ -XXX,XX +XXX,XX @@ QA output created by 116
424
== truncated header cluster ==
425
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
426
can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
427
-no file open, try 'help open'
428
429
== invalid header magic ==
430
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
431
can't open device TEST_DIR/t.qed: Image not in QED format
432
-no file open, try 'help open'
433
434
== invalid cluster size ==
435
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
436
can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
437
-no file open, try 'help open'
438
439
== invalid table size ==
440
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
441
can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
442
-no file open, try 'help open'
443
444
== invalid header size ==
445
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
446
can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
447
-no file open, try 'help open'
448
449
== invalid L1 table offset ==
450
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
451
can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
452
-no file open, try 'help open'
453
454
== invalid image size ==
455
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
456
can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
457
-no file open, try 'help open'
458
*** done
459
diff --git a/tests/qemu-iotests/131.out b/tests/qemu-iotests/131.out
460
index XXXXXXX..XXXXXXX 100644
461
--- a/tests/qemu-iotests/131.out
462
+++ b/tests/qemu-iotests/131.out
463
@@ -XXX,XX +XXX,XX @@ read 32768/32768 bytes at offset 0
464
32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
465
== Corrupt image ==
466
can't open device TEST_DIR/t.parallels: parallels: Image was not closed correctly; cannot be opened read/write
467
-no file open, try 'help open'
468
ERROR image was not closed correctly
469
470
1 errors were found on the image.
471
diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out
472
index XXXXXXX..XXXXXXX 100644
473
--- a/tests/qemu-iotests/140.out
474
+++ b/tests/qemu-iotests/140.out
475
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
476
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
477
{"return": {}}
478
can't open device nbd+unix:///drv?socket=TEST_DIR/nbd: No export with name 'drv' available
479
-no file open, try 'help open'
480
{"return": {}}
481
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
482
*** done
483
--
484
2.11.0
485
486
diff view generated by jsdifflib
Deleted patch
1
From: Nir Soffer <nirsof@gmail.com>
2
1
3
This helper allows adding tests supporting any format expect the
4
specified formats. This may be useful to test that many formats behave
5
in a common way.
6
7
Signed-off-by: Nir Soffer <nirsof@gmail.com>
8
Message-id: 20170201003120.23378-3-nirsof@gmail.com
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/common.rc | 11 +++++++++++
13
1 file changed, 11 insertions(+)
14
15
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/common.rc
18
+++ b/tests/qemu-iotests/common.rc
19
@@ -XXX,XX +XXX,XX @@ _supported_fmt()
20
_notrun "not suitable for this image format: $IMGFMT"
21
}
22
23
+# tests whether $IMGFMT is one of the unsupported image format for a test
24
+#
25
+_unsupported_fmt()
26
+{
27
+ for f; do
28
+ if [ "$f" = "$IMGFMT" ]; then
29
+ _notrun "not suitable for this image format: $IMGFMT"
30
+ fi
31
+ done
32
+}
33
+
34
# tests whether $IMGPROTO is one of the supported image protocols for a test
35
#
36
_supported_proto()
37
--
38
2.11.0
39
40
diff view generated by jsdifflib
Deleted patch
1
From: Nir Soffer <nirsof@gmail.com>
2
1
3
Add regression tests checking that qemu-io fails with non-zero exit code
4
when reading non-existing file or using the wrong image format.
5
6
Signed-off-by: Nir Soffer <nirsof@gmail.com>
7
Message-id: 20170201003120.23378-4-nirsof@gmail.com
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/174 | 59 ++++++++++++++++++++++++++++++++++++++++++++++
12
tests/qemu-iotests/174.out | 7 ++++++
13
tests/qemu-iotests/group | 1 +
14
3 files changed, 67 insertions(+)
15
create mode 100755 tests/qemu-iotests/174
16
create mode 100644 tests/qemu-iotests/174.out
17
18
diff --git a/tests/qemu-iotests/174 b/tests/qemu-iotests/174
19
new file mode 100755
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/qemu-iotests/174
23
@@ -XXX,XX +XXX,XX @@
24
+#!/bin/bash
25
+#
26
+# Test that qemu-io fail with non-zero exit code
27
+#
28
+# Copyright (C) 2017 Nir Soffer <nirsof@gmail.com>
29
+#
30
+# This program is free software; you can redistribute it and/or modify
31
+# it under the terms of the GNU General Public License as published by
32
+# the Free Software Foundation; either version 2 of the License, or
33
+# (at your option) any later version.
34
+#
35
+# This program is distributed in the hope that it will be useful,
36
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
37
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38
+# GNU General Public License for more details.
39
+#
40
+# You should have received a copy of the GNU General Public License
41
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
42
+#
43
+
44
+# creator
45
+owner=nirsof@gmail.com
46
+
47
+seq=`basename $0`
48
+echo "QA output created by $seq"
49
+
50
+here=`pwd`
51
+status=1    # failure is the default!
52
+
53
+_cleanup()
54
+{
55
+    _cleanup_test_img
56
+}
57
+trap "_cleanup; exit \$status" 0 1 2 3 15
58
+
59
+# get standard environment, filters and checks
60
+. ./common.rc
61
+. ./common.filter
62
+
63
+_unsupported_fmt raw
64
+
65
+
66
+size=256K
67
+IMGFMT=raw IMGOPTS= _make_test_img $size | _filter_imgfmt
68
+
69
+echo
70
+echo "== reading wrong format should fail =="
71
+$QEMU_IO -f $IMGFMT -c "read 0 $size" "$TEST_IMG" 2>/dev/null
72
+test $? -eq 1 || _fail "did not fail"
73
+
74
+echo
75
+echo "== reading missing file should fail =="
76
+$QEMU_IO -c "read 0 $size" "$TEST_DIR/missing" 2>/dev/null
77
+test $? -eq 1 || _fail "did not fail"
78
+
79
+# success, all done
80
+echo "*** done"
81
+rm -f $seq.full
82
+status=0
83
diff --git a/tests/qemu-iotests/174.out b/tests/qemu-iotests/174.out
84
new file mode 100644
85
index XXXXXXX..XXXXXXX
86
--- /dev/null
87
+++ b/tests/qemu-iotests/174.out
88
@@ -XXX,XX +XXX,XX @@
89
+QA output created by 174
90
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=262144
91
+
92
+== reading wrong format should fail ==
93
+
94
+== reading missing file should fail ==
95
+*** done
96
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
97
index XXXXXXX..XXXXXXX 100644
98
--- a/tests/qemu-iotests/group
99
+++ b/tests/qemu-iotests/group
100
@@ -XXX,XX +XXX,XX @@
101
171 rw auto quick
102
172 auto
103
173 rw auto
104
+174 auto
105
--
106
2.11.0
107
108
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
The metadata overlap checks introduced in a40f1c2add help detect
4
corruption in the qcow2 image by verifying that data writes don't
5
overlap with existing metadata sections.
6
7
The 'refcount-block' check in particular iterates over the refcount
8
table in order to get the addresses of all refcount blocks and check
9
that none of them overlap with the region where we want to write.
10
11
The problem with the refcount table is that since it always occupies
12
complete clusters its size is usually very big. With the default
13
values of cluster_size=64KB and refcount_bits=16 this table holds 8192
14
entries, each one of them enough to map 2GB worth of host clusters.
15
16
So unless we're using images with several TB of allocated data this
17
table is going to be mostly empty, and iterating over it is a waste of
18
CPU. If the storage backend is fast enough this can have an effect on
19
I/O performance.
20
21
This patch keeps the index of the last used (i.e. non-zero) entry in
22
the refcount table and updates it every time the table changes. The
23
refcount-block overlap check then uses that index instead of reading
24
the whole table.
25
26
In my tests with a 4GB qcow2 file stored in RAM this doubles the
27
amount of write IOPS.
28
29
Signed-off-by: Alberto Garcia <berto@igalia.com>
30
Message-id: 20170201123828.4815-1-berto@igalia.com
31
Reviewed-by: Max Reitz <mreitz@redhat.com>
32
Signed-off-by: Max Reitz <mreitz@redhat.com>
33
---
34
block/qcow2.h | 1 +
35
block/qcow2-refcount.c | 24 +++++++++++++++++++++++-
36
block/qcow2.c | 1 +
37
3 files changed, 25 insertions(+), 1 deletion(-)
38
39
diff --git a/block/qcow2.h b/block/qcow2.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/qcow2.h
42
+++ b/block/qcow2.h
43
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcow2State {
44
uint64_t *refcount_table;
45
uint64_t refcount_table_offset;
46
uint32_t refcount_table_size;
47
+ uint32_t max_refcount_table_index; /* Last used entry in refcount_table */
48
uint64_t free_cluster_index;
49
uint64_t free_byte_offset;
50
51
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/qcow2-refcount.c
54
+++ b/block/qcow2-refcount.c
55
@@ -XXX,XX +XXX,XX @@ static Qcow2SetRefcountFunc *const set_refcount_funcs[] = {
56
/*********************************************************/
57
/* refcount handling */
58
59
+static void update_max_refcount_table_index(BDRVQcow2State *s)
60
+{
61
+ unsigned i = s->refcount_table_size - 1;
62
+ while (i > 0 && (s->refcount_table[i] & REFT_OFFSET_MASK) == 0) {
63
+ i--;
64
+ }
65
+ /* Set s->max_refcount_table_index to the index of the last used entry */
66
+ s->max_refcount_table_index = i;
67
+}
68
+
69
int qcow2_refcount_init(BlockDriverState *bs)
70
{
71
BDRVQcow2State *s = bs->opaque;
72
@@ -XXX,XX +XXX,XX @@ int qcow2_refcount_init(BlockDriverState *bs)
73
}
74
for(i = 0; i < s->refcount_table_size; i++)
75
be64_to_cpus(&s->refcount_table[i]);
76
+ update_max_refcount_table_index(s);
77
}
78
return 0;
79
fail:
80
@@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs,
81
}
82
83
s->refcount_table[refcount_table_index] = new_block;
84
+ /* If there's a hole in s->refcount_table then it can happen
85
+ * that refcount_table_index < s->max_refcount_table_index */
86
+ s->max_refcount_table_index =
87
+ MAX(s->max_refcount_table_index, refcount_table_index);
88
89
/* The new refcount block may be where the caller intended to put its
90
* data, so let it restart the search. */
91
@@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs,
92
s->refcount_table = new_table;
93
s->refcount_table_size = table_size;
94
s->refcount_table_offset = table_offset;
95
+ update_max_refcount_table_index(s);
96
97
/* Free old table. */
98
qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t),
99
@@ -XXX,XX +XXX,XX @@ write_refblocks:
100
s->refcount_table = on_disk_reftable;
101
s->refcount_table_offset = reftable_offset;
102
s->refcount_table_size = reftable_size;
103
+ update_max_refcount_table_index(s);
104
105
return 0;
106
107
@@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
108
}
109
110
if ((chk & QCOW2_OL_REFCOUNT_BLOCK) && s->refcount_table) {
111
- for (i = 0; i < s->refcount_table_size; i++) {
112
+ unsigned last_entry = s->max_refcount_table_index;
113
+ assert(last_entry < s->refcount_table_size);
114
+ assert(last_entry + 1 == s->refcount_table_size ||
115
+ (s->refcount_table[last_entry + 1] & REFT_OFFSET_MASK) == 0);
116
+ for (i = 0; i <= last_entry; i++) {
117
if ((s->refcount_table[i] & REFT_OFFSET_MASK) &&
118
overlaps_with(s->refcount_table[i] & REFT_OFFSET_MASK,
119
s->cluster_size)) {
120
@@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
121
/* Now update the rest of the in-memory information */
122
old_reftable = s->refcount_table;
123
s->refcount_table = new_reftable;
124
+ update_max_refcount_table_index(s);
125
126
s->refcount_bits = 1 << refcount_order;
127
s->refcount_max = UINT64_C(1) << (s->refcount_bits - 1);
128
diff --git a/block/qcow2.c b/block/qcow2.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/block/qcow2.c
131
+++ b/block/qcow2.c
132
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
133
134
s->refcount_table_offset = s->cluster_size;
135
s->refcount_table_size = s->cluster_size / sizeof(uint64_t);
136
+ s->max_refcount_table_index = 0;
137
138
g_free(s->refcount_table);
139
s->refcount_table = new_reftable;
140
--
141
2.11.0
142
143
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
Passing a request size larger than BDRV_REQUEST_MAX_BYTES to any of the
4
I/O commands results in an error. While 'read' and 'write' handle the
5
error correctly, 'aio_read' and 'aio_write' hit an assertion:
6
7
blk_aio_read_entry: Assertion `rwco->qiov->size == acb->bytes' failed.
8
9
The reason is that the QEMU I/O code cannot handle request sizes
10
larger than BDRV_REQUEST_MAX_BYTES, so this patch makes qemu-io check
11
that all values are within range.
12
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
14
Message-id: 79f66648c685929a144396bda24d13a207131dcf.1485878688.git.berto@igalia.com
15
[mreitz: Use BDRV_REQUEST_MAX_BYTES instead of INT_MAX]
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
qemu-io-cmds.c | 20 +++++++++++++-------
19
1 file changed, 13 insertions(+), 7 deletions(-)
20
21
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/qemu-io-cmds.c
24
+++ b/qemu-io-cmds.c
25
@@ -XXX,XX +XXX,XX @@ create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
26
goto fail;
27
}
28
29
- if (len > SIZE_MAX) {
30
- printf("Argument '%s' exceeds maximum size %llu\n", arg,
31
- (unsigned long long)SIZE_MAX);
32
+ if (len > BDRV_REQUEST_MAX_BYTES) {
33
+ printf("Argument '%s' exceeds maximum size %" PRIu64 "\n", arg,
34
+ (uint64_t)BDRV_REQUEST_MAX_BYTES);
35
+ goto fail;
36
+ }
37
+
38
+ if (count > BDRV_REQUEST_MAX_BYTES - len) {
39
+ printf("The total number of bytes exceed the maximum size %" PRIu64
40
+ "\n", (uint64_t)BDRV_REQUEST_MAX_BYTES);
41
goto fail;
42
}
43
44
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
45
if (count < 0) {
46
print_cvtnum_err(count, argv[optind]);
47
return 0;
48
- } else if (count > SIZE_MAX) {
49
+ } else if (count > BDRV_REQUEST_MAX_BYTES) {
50
printf("length cannot exceed %" PRIu64 ", given %s\n",
51
- (uint64_t) SIZE_MAX, argv[optind]);
52
+ (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
53
return 0;
54
}
55
56
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
57
if (count < 0) {
58
print_cvtnum_err(count, argv[optind]);
59
return 0;
60
- } else if (count > SIZE_MAX) {
61
+ } else if (count > BDRV_REQUEST_MAX_BYTES) {
62
printf("length cannot exceed %" PRIu64 ", given %s\n",
63
- (uint64_t) SIZE_MAX, argv[optind]);
64
+ (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
65
return 0;
66
}
67
68
--
69
2.11.0
70
71
diff view generated by jsdifflib
Deleted patch
1
From: Peter Maydell <peter.maydell@linaro.org>
2
1
3
Some of the argument parsing in qemu-img uses strtoul() to parse
4
integer arguments. This is tricky to get correct and in fact the
5
code does not get it right, because it assigns the result of
6
strtoul() to an 'int' variable and then tries to check for > INT_MAX.
7
Coverity correctly complains that the comparison is always false.
8
9
Rewrite to use qemu_strtoul(), which has a saner convention for
10
reporting conversion failures.
11
12
(Fixes CID 1356421, CID 1356422, CID 1356423.)
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Message-id: 1486744104-15590-2-git-send-email-peter.maydell@linaro.org
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
qemu-img.c | 32 ++++++++++++++++----------------
20
1 file changed, 16 insertions(+), 16 deletions(-)
21
22
diff --git a/qemu-img.c b/qemu-img.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/qemu-img.c
25
+++ b/qemu-img.c
26
@@ -XXX,XX +XXX,XX @@ static int img_bench(int argc, char **argv)
27
break;
28
case 'c':
29
{
30
- char *end;
31
- errno = 0;
32
- count = strtoul(optarg, &end, 0);
33
- if (errno || *end || count > INT_MAX) {
34
+ unsigned long res;
35
+
36
+ if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) {
37
error_report("Invalid request count specified");
38
return 1;
39
}
40
+ count = res;
41
break;
42
}
43
case 'd':
44
{
45
- char *end;
46
- errno = 0;
47
- depth = strtoul(optarg, &end, 0);
48
- if (errno || *end || depth > INT_MAX) {
49
+ unsigned long res;
50
+
51
+ if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) {
52
error_report("Invalid queue depth specified");
53
return 1;
54
}
55
+ depth = res;
56
break;
57
}
58
case 'f':
59
@@ -XXX,XX +XXX,XX @@ static int img_bench(int argc, char **argv)
60
break;
61
case OPTION_PATTERN:
62
{
63
- char *end;
64
- errno = 0;
65
- pattern = strtoul(optarg, &end, 0);
66
- if (errno || *end || pattern > 0xff) {
67
+ unsigned long res;
68
+
69
+ if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > 0xff) {
70
error_report("Invalid pattern byte specified");
71
return 1;
72
}
73
+ pattern = res;
74
break;
75
}
76
case OPTION_FLUSH_INTERVAL:
77
{
78
- char *end;
79
- errno = 0;
80
- flush_interval = strtoul(optarg, &end, 0);
81
- if (errno || *end || flush_interval > INT_MAX) {
82
+ unsigned long res;
83
+
84
+ if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) {
85
error_report("Invalid flush interval specified");
86
return 1;
87
}
88
+ flush_interval = res;
89
break;
90
}
91
case OPTION_NO_DRAIN:
92
--
93
2.11.0
94
95
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
From: Nicolas Saenz Julienne <nsaenzju@redhat.com>
2
2
3
Coverity points out that we assign the return value from
3
The thread pool regulates itself: when idle, it kills threads until
4
bdrv_snapshot_load_tmp() to 'ret' in img_convert(), but then
4
empty, when in demand, it creates new threads until full. This behaviour
5
never use that variable. (We check for failure by looking
5
doesn't play well with latency sensitive workloads where the price of
6
at local_err instead.) Drop the unused assignment, bringing
6
creating a new thread is too high. For example, when paired with qemu's
7
the call into line with the following call to
7
'-mlock', or using safety features like SafeStack, creating a new thread
8
bdrv_snapshot_laod_tmp_by_id_or_name().
8
has been measured take multiple milliseconds.
9
9
10
(Fixes CID 1247240.)
10
In order to mitigate this let's introduce a new 'EventLoopBase'
11
property to set the thread pool size. The threads will be created during
12
the pool's initialization or upon updating the property's value, remain
13
available during its lifetime regardless of demand, and destroyed upon
14
freeing it. A properly characterized workload will then be able to
15
configure the pool to avoid any latency spikes.
11
16
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Nicolas Saenz Julienne <nsaenzju@redhat.com>
13
Message-id: 1486744104-15590-3-git-send-email-peter.maydell@linaro.org
18
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Acked-by: Markus Armbruster <armbru@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
Message-id: 20220425075723.20019-4-nsaenzju@redhat.com
21
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
22
---
17
qemu-img.c | 8 ++++----
23
qapi/qom.json | 10 +++++-
18
1 file changed, 4 insertions(+), 4 deletions(-)
24
include/block/aio.h | 10 ++++++
25
include/block/thread-pool.h | 3 ++
26
include/sysemu/event-loop-base.h | 4 +++
27
event-loop-base.c | 23 +++++++++++++
28
iothread.c | 3 ++
29
util/aio-posix.c | 1 +
30
util/async.c | 20 ++++++++++++
31
util/main-loop.c | 9 ++++++
32
util/thread-pool.c | 55 +++++++++++++++++++++++++++++---
33
10 files changed, 133 insertions(+), 5 deletions(-)
19
34
20
diff --git a/qemu-img.c b/qemu-img.c
35
diff --git a/qapi/qom.json b/qapi/qom.json
21
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
22
--- a/qemu-img.c
37
--- a/qapi/qom.json
23
+++ b/qemu-img.c
38
+++ b/qapi/qom.json
24
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
39
@@ -XXX,XX +XXX,XX @@
40
# 0 means that the engine will use its default.
41
# (default: 0)
42
#
43
+# @thread-pool-min: minimum number of threads reserved in the thread pool
44
+# (default:0)
45
+#
46
+# @thread-pool-max: maximum number of threads the thread pool can contain
47
+# (default:64)
48
+#
49
# Since: 7.1
50
##
51
{ 'struct': 'EventLoopBaseProperties',
52
- 'data': { '*aio-max-batch': 'int' } }
53
+ 'data': { '*aio-max-batch': 'int',
54
+ '*thread-pool-min': 'int',
55
+ '*thread-pool-max': 'int' } }
56
57
##
58
# @IothreadProperties:
59
diff --git a/include/block/aio.h b/include/block/aio.h
60
index XXXXXXX..XXXXXXX 100644
61
--- a/include/block/aio.h
62
+++ b/include/block/aio.h
63
@@ -XXX,XX +XXX,XX @@ struct AioContext {
64
QSLIST_HEAD(, Coroutine) scheduled_coroutines;
65
QEMUBH *co_schedule_bh;
66
67
+ int thread_pool_min;
68
+ int thread_pool_max;
69
/* Thread pool for performing work and receiving completion callbacks.
70
* Has its own locking.
71
*/
72
@@ -XXX,XX +XXX,XX @@ void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
73
void aio_context_set_aio_params(AioContext *ctx, int64_t max_batch,
74
Error **errp);
75
76
+/**
77
+ * aio_context_set_thread_pool_params:
78
+ * @ctx: the aio context
79
+ * @min: min number of threads to have readily available in the thread pool
80
+ * @min: max number of threads the thread pool can contain
81
+ */
82
+void aio_context_set_thread_pool_params(AioContext *ctx, int64_t min,
83
+ int64_t max, Error **errp);
84
#endif
85
diff --git a/include/block/thread-pool.h b/include/block/thread-pool.h
86
index XXXXXXX..XXXXXXX 100644
87
--- a/include/block/thread-pool.h
88
+++ b/include/block/thread-pool.h
89
@@ -XXX,XX +XXX,XX @@
90
91
#include "block/block.h"
92
93
+#define THREAD_POOL_MAX_THREADS_DEFAULT 64
94
+
95
typedef int ThreadPoolFunc(void *opaque);
96
97
typedef struct ThreadPool ThreadPool;
98
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool,
99
int coroutine_fn thread_pool_submit_co(ThreadPool *pool,
100
ThreadPoolFunc *func, void *arg);
101
void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg);
102
+void thread_pool_update_params(ThreadPool *pool, struct AioContext *ctx);
103
104
#endif
105
diff --git a/include/sysemu/event-loop-base.h b/include/sysemu/event-loop-base.h
106
index XXXXXXX..XXXXXXX 100644
107
--- a/include/sysemu/event-loop-base.h
108
+++ b/include/sysemu/event-loop-base.h
109
@@ -XXX,XX +XXX,XX @@ struct EventLoopBase {
110
111
/* AioContext AIO engine parameters */
112
int64_t aio_max_batch;
113
+
114
+ /* AioContext thread pool parameters */
115
+ int64_t thread_pool_min;
116
+ int64_t thread_pool_max;
117
};
118
#endif
119
diff --git a/event-loop-base.c b/event-loop-base.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/event-loop-base.c
122
+++ b/event-loop-base.c
123
@@ -XXX,XX +XXX,XX @@
124
#include "qemu/osdep.h"
125
#include "qom/object_interfaces.h"
126
#include "qapi/error.h"
127
+#include "block/thread-pool.h"
128
#include "sysemu/event-loop-base.h"
129
130
typedef struct {
131
@@ -XXX,XX +XXX,XX @@ typedef struct {
132
ptrdiff_t offset; /* field's byte offset in EventLoopBase struct */
133
} EventLoopBaseParamInfo;
134
135
+static void event_loop_base_instance_init(Object *obj)
136
+{
137
+ EventLoopBase *base = EVENT_LOOP_BASE(obj);
138
+
139
+ base->thread_pool_max = THREAD_POOL_MAX_THREADS_DEFAULT;
140
+}
141
+
142
static EventLoopBaseParamInfo aio_max_batch_info = {
143
"aio-max-batch", offsetof(EventLoopBase, aio_max_batch),
144
};
145
+static EventLoopBaseParamInfo thread_pool_min_info = {
146
+ "thread-pool-min", offsetof(EventLoopBase, thread_pool_min),
147
+};
148
+static EventLoopBaseParamInfo thread_pool_max_info = {
149
+ "thread-pool-max", offsetof(EventLoopBase, thread_pool_max),
150
+};
151
152
static void event_loop_base_get_param(Object *obj, Visitor *v,
153
const char *name, void *opaque, Error **errp)
154
@@ -XXX,XX +XXX,XX @@ static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
155
event_loop_base_get_param,
156
event_loop_base_set_param,
157
NULL, &aio_max_batch_info);
158
+ object_class_property_add(klass, "thread-pool-min", "int",
159
+ event_loop_base_get_param,
160
+ event_loop_base_set_param,
161
+ NULL, &thread_pool_min_info);
162
+ object_class_property_add(klass, "thread-pool-max", "int",
163
+ event_loop_base_get_param,
164
+ event_loop_base_set_param,
165
+ NULL, &thread_pool_max_info);
166
}
167
168
static const TypeInfo event_loop_base_info = {
169
.name = TYPE_EVENT_LOOP_BASE,
170
.parent = TYPE_OBJECT,
171
.instance_size = sizeof(EventLoopBase),
172
+ .instance_init = event_loop_base_instance_init,
173
.class_size = sizeof(EventLoopBaseClass),
174
.class_init = event_loop_base_class_init,
175
.abstract = true,
176
diff --git a/iothread.c b/iothread.c
177
index XXXXXXX..XXXXXXX 100644
178
--- a/iothread.c
179
+++ b/iothread.c
180
@@ -XXX,XX +XXX,XX @@ static void iothread_set_aio_context_params(EventLoopBase *base, Error **errp)
181
aio_context_set_aio_params(iothread->ctx,
182
iothread->parent_obj.aio_max_batch,
183
errp);
184
+
185
+ aio_context_set_thread_pool_params(iothread->ctx, base->thread_pool_min,
186
+ base->thread_pool_max, errp);
187
}
188
189
190
diff --git a/util/aio-posix.c b/util/aio-posix.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/util/aio-posix.c
193
+++ b/util/aio-posix.c
194
@@ -XXX,XX +XXX,XX @@
195
196
#include "qemu/osdep.h"
197
#include "block/block.h"
198
+#include "block/thread-pool.h"
199
#include "qemu/main-loop.h"
200
#include "qemu/rcu.h"
201
#include "qemu/rcu_queue.h"
202
diff --git a/util/async.c b/util/async.c
203
index XXXXXXX..XXXXXXX 100644
204
--- a/util/async.c
205
+++ b/util/async.c
206
@@ -XXX,XX +XXX,XX @@ AioContext *aio_context_new(Error **errp)
207
208
ctx->aio_max_batch = 0;
209
210
+ ctx->thread_pool_min = 0;
211
+ ctx->thread_pool_max = THREAD_POOL_MAX_THREADS_DEFAULT;
212
+
213
return ctx;
214
fail:
215
g_source_destroy(&ctx->source);
216
@@ -XXX,XX +XXX,XX @@ void qemu_set_current_aio_context(AioContext *ctx)
217
assert(!get_my_aiocontext());
218
set_my_aiocontext(ctx);
219
}
220
+
221
+void aio_context_set_thread_pool_params(AioContext *ctx, int64_t min,
222
+ int64_t max, Error **errp)
223
+{
224
+
225
+ if (min > max || !max || min > INT_MAX || max > INT_MAX) {
226
+ error_setg(errp, "bad thread-pool-min/thread-pool-max values");
227
+ return;
228
+ }
229
+
230
+ ctx->thread_pool_min = min;
231
+ ctx->thread_pool_max = max;
232
+
233
+ if (ctx->thread_pool) {
234
+ thread_pool_update_params(ctx->thread_pool, ctx);
235
+ }
236
+}
237
diff --git a/util/main-loop.c b/util/main-loop.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/util/main-loop.c
240
+++ b/util/main-loop.c
241
@@ -XXX,XX +XXX,XX @@
242
#include "sysemu/replay.h"
243
#include "qemu/main-loop.h"
244
#include "block/aio.h"
245
+#include "block/thread-pool.h"
246
#include "qemu/error-report.h"
247
#include "qemu/queue.h"
248
#include "qemu/compiler.h"
249
@@ -XXX,XX +XXX,XX @@ int qemu_init_main_loop(Error **errp)
250
251
static void main_loop_update_params(EventLoopBase *base, Error **errp)
252
{
253
+ ERRP_GUARD();
254
+
255
if (!qemu_aio_context) {
256
error_setg(errp, "qemu aio context not ready");
257
return;
25
}
258
}
26
259
27
if (sn_opts) {
260
aio_context_set_aio_params(qemu_aio_context, base->aio_max_batch, errp);
28
- ret = bdrv_snapshot_load_tmp(bs[0],
261
+ if (*errp) {
29
- qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID),
262
+ return;
30
- qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME),
263
+ }
31
- &local_err);
264
+
32
+ bdrv_snapshot_load_tmp(bs[0],
265
+ aio_context_set_thread_pool_params(qemu_aio_context, base->thread_pool_min,
33
+ qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID),
266
+ base->thread_pool_max, errp);
34
+ qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME),
267
}
35
+ &local_err);
268
36
} else if (snapshot_name != NULL) {
269
MainLoop *mloop;
37
if (bs_n > 1) {
270
diff --git a/util/thread-pool.c b/util/thread-pool.c
38
error_report("No support for concatenating multiple snapshot");
271
index XXXXXXX..XXXXXXX 100644
272
--- a/util/thread-pool.c
273
+++ b/util/thread-pool.c
274
@@ -XXX,XX +XXX,XX @@ struct ThreadPool {
275
QemuMutex lock;
276
QemuCond worker_stopped;
277
QemuSemaphore sem;
278
- int max_threads;
279
QEMUBH *new_thread_bh;
280
281
/* The following variables are only accessed from one AioContext. */
282
@@ -XXX,XX +XXX,XX @@ struct ThreadPool {
283
int new_threads; /* backlog of threads we need to create */
284
int pending_threads; /* threads created but not running yet */
285
bool stopping;
286
+ int min_threads;
287
+ int max_threads;
288
};
289
290
+static inline bool back_to_sleep(ThreadPool *pool, int ret)
291
+{
292
+ /*
293
+ * The semaphore timed out, we should exit the loop except when:
294
+ * - There is work to do, we raced with the signal.
295
+ * - The max threads threshold just changed, we raced with the signal.
296
+ * - The thread pool forces a minimum number of readily available threads.
297
+ */
298
+ if (ret == -1 && (!QTAILQ_EMPTY(&pool->request_list) ||
299
+ pool->cur_threads > pool->max_threads ||
300
+ pool->cur_threads <= pool->min_threads)) {
301
+ return true;
302
+ }
303
+
304
+ return false;
305
+}
306
+
307
static void *worker_thread(void *opaque)
308
{
309
ThreadPool *pool = opaque;
310
@@ -XXX,XX +XXX,XX @@ static void *worker_thread(void *opaque)
311
ret = qemu_sem_timedwait(&pool->sem, 10000);
312
qemu_mutex_lock(&pool->lock);
313
pool->idle_threads--;
314
- } while (ret == -1 && !QTAILQ_EMPTY(&pool->request_list));
315
- if (ret == -1 || pool->stopping) {
316
+ } while (back_to_sleep(pool, ret));
317
+ if (ret == -1 || pool->stopping ||
318
+ pool->cur_threads > pool->max_threads) {
319
break;
320
}
321
322
@@ -XXX,XX +XXX,XX @@ void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg)
323
thread_pool_submit_aio(pool, func, arg, NULL, NULL);
324
}
325
326
+void thread_pool_update_params(ThreadPool *pool, AioContext *ctx)
327
+{
328
+ qemu_mutex_lock(&pool->lock);
329
+
330
+ pool->min_threads = ctx->thread_pool_min;
331
+ pool->max_threads = ctx->thread_pool_max;
332
+
333
+ /*
334
+ * We either have to:
335
+ * - Increase the number available of threads until over the min_threads
336
+ * threshold.
337
+ * - Decrease the number of available threads until under the max_threads
338
+ * threshold.
339
+ * - Do nothing. The current number of threads fall in between the min and
340
+ * max thresholds. We'll let the pool manage itself.
341
+ */
342
+ for (int i = pool->cur_threads; i < pool->min_threads; i++) {
343
+ spawn_thread(pool);
344
+ }
345
+
346
+ for (int i = pool->cur_threads; i > pool->max_threads; i--) {
347
+ qemu_sem_post(&pool->sem);
348
+ }
349
+
350
+ qemu_mutex_unlock(&pool->lock);
351
+}
352
+
353
static void thread_pool_init_one(ThreadPool *pool, AioContext *ctx)
354
{
355
if (!ctx) {
356
@@ -XXX,XX +XXX,XX @@ static void thread_pool_init_one(ThreadPool *pool, AioContext *ctx)
357
qemu_mutex_init(&pool->lock);
358
qemu_cond_init(&pool->worker_stopped);
359
qemu_sem_init(&pool->sem, 0);
360
- pool->max_threads = 64;
361
pool->new_thread_bh = aio_bh_new(ctx, spawn_thread_bh_fn, pool);
362
363
QLIST_INIT(&pool->head);
364
QTAILQ_INIT(&pool->request_list);
365
+
366
+ thread_pool_update_params(pool, ctx);
367
}
368
369
ThreadPool *thread_pool_new(AioContext *ctx)
39
--
370
--
40
2.11.0
371
2.35.1
41
42
diff view generated by jsdifflib