1
The following changes since commit bfec359afba088aaacc7d316f43302f28c6e642a:
1
The following changes since commit 9cf289af47bcfae5c75de37d8e5d6fd23705322c:
2
2
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-qdev-2017-04-21' into staging (2017-04-21 11:42:03 +0100)
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/codyprime/qemu-kvm-jtc.git tags/block-pull-request
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 1507631e438930bc07f776f303af127a9cdb4d41:
9
for you to fetch changes up to bef2e050d6a7feb865854c65570c496ac5a8cf53:
10
10
11
qemu-iotests: _cleanup_qemu must be called on exit (2017-04-21 08:32:44 -0400)
11
util/event-loop-base: Introduce options to set the thread pool size (2022-05-04 17:02:19 +0100)
12
13
----------------------------------------------------------------
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.
12
18
13
----------------------------------------------------------------
19
----------------------------------------------------------------
14
20
15
Block patches for 2.10
21
Nicolas Saenz Julienne (3):
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
16
25
17
----------------------------------------------------------------
26
qapi/qom.json | 43 ++++++++--
18
27
meson.build | 26 +++---
19
Ashish Mittal (2):
28
include/block/aio.h | 10 +++
20
block/vxhs.c: Add support for a new block device type called "vxhs"
29
include/block/thread-pool.h | 3 +
21
block/vxhs.c: Add qemu-iotests for new block device type "vxhs"
30
include/qemu/main-loop.h | 10 +++
22
31
include/sysemu/event-loop-base.h | 41 +++++++++
23
Jeff Cody (10):
32
include/sysemu/iothread.h | 6 +-
24
qemu-iotests: exclude vxhs from image creation via protocol
33
event-loop-base.c | 140 +++++++++++++++++++++++++++++++
25
block: add bdrv_set_read_only() helper function
34
iothread.c | 68 +++++----------
26
block: do not set BDS read_only if copy_on_read enabled
35
util/aio-posix.c | 1 +
27
block: honor BDRV_O_ALLOW_RDWR when clearing bs->read_only
36
util/async.c | 20 +++++
28
block: code movement
37
util/main-loop.c | 65 ++++++++++++++
29
block: introduce bdrv_can_set_read_only()
38
util/thread-pool.c | 55 +++++++++++-
30
block: use bdrv_can_set_read_only() during reopen
39
13 files changed, 419 insertions(+), 69 deletions(-)
31
block/rbd - update variable names to more apt names
40
create mode 100644 include/sysemu/event-loop-base.h
32
block/rbd: Add support for reopen()
41
create mode 100644 event-loop-base.c
33
qemu-iotests: _cleanup_qemu must be called on exit
34
35
block.c | 56 +++-
36
block/Makefile.objs | 2 +
37
block/bochs.c | 5 +-
38
block/cloop.c | 5 +-
39
block/dmg.c | 6 +-
40
block/rbd.c | 65 +++--
41
block/trace-events | 17 ++
42
block/vvfat.c | 19 +-
43
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++
44
configure | 39 +++
45
include/block/block.h | 2 +
46
qapi/block-core.json | 23 +-
47
tests/qemu-iotests/017 | 1 +
48
tests/qemu-iotests/020 | 1 +
49
tests/qemu-iotests/028 | 1 +
50
tests/qemu-iotests/029 | 1 +
51
tests/qemu-iotests/073 | 1 +
52
tests/qemu-iotests/094 | 11 +-
53
tests/qemu-iotests/102 | 5 +-
54
tests/qemu-iotests/109 | 1 +
55
tests/qemu-iotests/114 | 1 +
56
tests/qemu-iotests/117 | 1 +
57
tests/qemu-iotests/130 | 2 +
58
tests/qemu-iotests/134 | 1 +
59
tests/qemu-iotests/140 | 1 +
60
tests/qemu-iotests/141 | 1 +
61
tests/qemu-iotests/143 | 1 +
62
tests/qemu-iotests/156 | 2 +
63
tests/qemu-iotests/158 | 1 +
64
tests/qemu-iotests/common | 6 +
65
tests/qemu-iotests/common.config | 13 +
66
tests/qemu-iotests/common.filter | 1 +
67
tests/qemu-iotests/common.rc | 19 ++
68
33 files changed, 844 insertions(+), 42 deletions(-)
69
create mode 100644 block/vxhs.c
70
42
71
--
43
--
72
2.9.3
44
2.35.1
73
74
diff view generated by jsdifflib
1
From: Ashish Mittal <ashmit602@gmail.com>
1
From: Nicolas Saenz Julienne <nsaenzju@redhat.com>
2
2
3
Source code for the qnio library that this code loads can be downloaded from:
3
Introduce the 'event-loop-base' abstract class, it'll hold the
4
https://github.com/VeritasHyperScale/libqnio.git
4
properties common to all event loops and provide the necessary hooks for
5
5
their creation and maintenance. Then have iothread inherit from it.
6
Sample command line using JSON syntax:
6
7
./x86_64-softmmu/qemu-system-x86_64 -name instance-00000008 -S -vnc 0.0.0.0:0
7
EventLoopBaseClass is defined as user creatable and provides a hook for
8
-k en-us -vga cirrus -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
8
its children to attach themselves to the user creatable class 'complete'
9
-msg timestamp=on
9
function. It also provides an update_params() callback to propagate
10
'json:{"driver":"vxhs","vdisk-id":"c3e9095a-a5ee-4dce-afeb-2a59fb387410",
10
property changes onto its children.
11
"server":{"host":"172.172.17.4","port":"9999"}}'
11
12
12
The new 'event-loop-base' class will live in the root directory. It is
13
Sample command line using URI syntax:
13
built on its own using the 'link_whole' option (there are no direct
14
qemu-img convert -f raw -O raw -n
14
function dependencies between the class and its children, it all happens
15
/var/lib/nova/instances/_base/0c5eacd5ebea5ed914b6a3e7b18f1ce734c386ad
15
trough 'constructor' magic). And also imposes new compilation
16
vxhs://192.168.0.1:9999/c6718f6b-0401-441d-a8c3-1f0064d75ee0
16
dependencies:
17
17
18
Sample command line using TLS credentials (run in secure mode):
18
qom <- event-loop-base <- blockdev (iothread.c)
19
./qemu-io --object
19
20
tls-creds-x509,id=tls0,dir=/etc/pki/qemu/vxhs,endpoint=client -c 'read
20
And in subsequent patches:
21
-v 66000 2.5k' 'json:{"server.host": "127.0.0.1", "server.port": "9999",
21
22
"vdisk-id": "/test.raw", "driver": "vxhs", "tls-creds":"tls0"}'
22
qom <- event-loop-base <- qemuutil (util/main-loop.c)
23
23
24
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.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>
25
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
36
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
26
Reviewed-by: Jeff Cody <jcody@redhat.com>
37
Acked-by: Markus Armbruster <armbru@redhat.com>
27
Signed-off-by: Jeff Cody <jcody@redhat.com>
38
Message-id: 20220425075723.20019-2-nsaenzju@redhat.com
28
Message-id: 1491277689-24949-2-git-send-email-Ashish.Mittal@veritas.com
39
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
29
---
40
---
30
block/Makefile.objs | 2 +
41
qapi/qom.json | 22 +++++--
31
block/trace-events | 17 ++
42
meson.build | 23 ++++---
32
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++++++++++++++
43
include/sysemu/event-loop-base.h | 36 +++++++++++
33
configure | 39 ++++
44
include/sysemu/iothread.h | 6 +-
34
qapi/block-core.json | 23 ++-
45
event-loop-base.c | 104 +++++++++++++++++++++++++++++++
35
5 files changed, 654 insertions(+), 2 deletions(-)
46
iothread.c | 65 ++++++-------------
36
create mode 100644 block/vxhs.c
47
6 files changed, 192 insertions(+), 64 deletions(-)
37
48
create mode 100644 include/sysemu/event-loop-base.h
38
diff --git a/block/Makefile.objs b/block/Makefile.objs
49
create mode 100644 event-loop-base.c
50
51
diff --git a/qapi/qom.json b/qapi/qom.json
39
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
40
--- a/block/Makefile.objs
53
--- a/qapi/qom.json
41
+++ b/block/Makefile.objs
54
+++ b/qapi/qom.json
42
@@ -XXX,XX +XXX,XX @@ block-obj-$(CONFIG_LIBNFS) += nfs.o
55
@@ -XXX,XX +XXX,XX @@
43
block-obj-$(CONFIG_CURL) += curl.o
56
'*repeat': 'bool',
44
block-obj-$(CONFIG_RBD) += rbd.o
57
'*grab-toggle': 'GrabToggleKeys' } }
45
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
58
46
+block-obj-$(CONFIG_VXHS) += vxhs.o
59
+##
47
block-obj-$(CONFIG_LIBSSH2) += ssh.o
60
+# @EventLoopBaseProperties:
48
block-obj-y += accounting.o dirty-bitmap.o
61
+#
49
block-obj-y += write-threshold.o
62
+# Common properties for event loops
50
@@ -XXX,XX +XXX,XX @@ rbd.o-cflags := $(RBD_CFLAGS)
63
+#
51
rbd.o-libs := $(RBD_LIBS)
64
+# @aio-max-batch: maximum number of requests in a batch for the AIO engine,
52
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
65
+# 0 means that the engine will use its default.
53
gluster.o-libs := $(GLUSTERFS_LIBS)
66
+# (default: 0)
54
+vxhs.o-libs := $(VXHS_LIBS)
67
+#
55
ssh.o-cflags := $(LIBSSH2_CFLAGS)
68
+# Since: 7.1
56
ssh.o-libs := $(LIBSSH2_LIBS)
69
+##
57
block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o
70
+{ 'struct': 'EventLoopBaseProperties',
58
diff --git a/block/trace-events b/block/trace-events
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
59
index XXXXXXX..XXXXXXX 100644
98
index XXXXXXX..XXXXXXX 100644
60
--- a/block/trace-events
99
--- a/meson.build
61
+++ b/block/trace-events
100
+++ b/meson.build
62
@@ -XXX,XX +XXX,XX @@ qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s
101
@@ -XXX,XX +XXX,XX @@ subdir('qom')
63
qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64
102
subdir('authz')
64
qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64
103
subdir('crypto')
65
qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
104
subdir('ui')
66
+
105
+subdir('hw')
67
+# block/vxhs.c
106
68
+vxhs_iio_callback(int error) "ctx is NULL: error %d"
107
69
+vxhs_iio_callback_chnfail(int err, int error) "QNIO channel failed, no i/o %d, %d"
108
if enable_modules
70
+vxhs_iio_callback_unknwn(int opcode, int err) "unexpected opcode %d, errno %d"
109
@@ -XXX,XX +XXX,XX @@ if enable_modules
71
+vxhs_aio_rw_invalid(int req) "Invalid I/O request iodir %d"
110
modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
72
+vxhs_aio_rw_ioerr(char *guid, int iodir, uint64_t size, uint64_t off, void *acb, int ret, int err) "IO ERROR (vDisk %s) FOR : Read/Write = %d size = %lu offset = %lu ACB = %p. Error = %d, errno = %d"
111
endif
73
+vxhs_get_vdisk_stat_err(char *guid, int ret, int err) "vDisk (%s) stat ioctl failed, ret = %d, errno = %d"
112
74
+vxhs_get_vdisk_stat(char *vdisk_guid, uint64_t vdisk_size) "vDisk %s stat ioctl returned size %lu"
113
+qom_ss = qom_ss.apply(config_host, strict: false)
75
+vxhs_complete_aio(void *acb, uint64_t ret) "aio failed acb %p ret %ld"
114
+libqom = static_library('qom', qom_ss.sources() + genh,
76
+vxhs_parse_uri_filename(const char *filename) "URI passed via bdrv_parse_filename %s"
115
+ dependencies: [qom_ss.dependencies()],
77
+vxhs_open_vdiskid(const char *vdisk_id) "Opening vdisk-id %s"
116
+ name_suffix: 'fa')
78
+vxhs_open_hostinfo(char *of_vsa_addr, int port) "Adding host %s:%d to BDRVVXHSState"
117
+qom = declare_dependency(link_whole: libqom)
79
+vxhs_open_iio_open(const char *host) "Failed to connect to storage agent on host %s"
118
+
80
+vxhs_parse_uri_hostinfo(char *host, int port) "Host: IP %s, Port %d"
119
+event_loop_base = files('event-loop-base.c')
81
+vxhs_close(char *vdisk_guid) "Closing vdisk %s"
120
+event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
82
+vxhs_get_creds(const char *cacert, const char *client_key, const char *client_cert) "cacert %s, client_key %s, client_cert %s"
121
+ build_by_default: true)
83
diff --git a/block/vxhs.c b/block/vxhs.c
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
84
new file mode 100644
160
new file mode 100644
85
index XXXXXXX..XXXXXXX
161
index XXXXXXX..XXXXXXX
86
--- /dev/null
162
--- /dev/null
87
+++ b/block/vxhs.c
163
+++ b/include/sysemu/event-loop-base.h
88
@@ -XXX,XX +XXX,XX @@
164
@@ -XXX,XX +XXX,XX @@
89
+/*
165
+/*
90
+ * QEMU Block driver for Veritas HyperScale (VxHS)
166
+ * QEMU event-loop backend
91
+ *
167
+ *
92
+ * Copyright (c) 2017 Veritas Technologies LLC.
168
+ * Copyright (C) 2022 Red Hat Inc
169
+ *
170
+ * Authors:
171
+ * Nicolas Saenz Julienne <nsaenzju@redhat.com>
93
+ *
172
+ *
94
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
173
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
95
+ * See the COPYING file in the top-level directory.
174
+ * See the COPYING file in the top-level directory.
96
+ *
97
+ */
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
+ */
98
+
247
+
99
+#include "qemu/osdep.h"
248
+#include "qemu/osdep.h"
100
+#include <qnio/qnio_api.h>
249
+#include "qom/object_interfaces.h"
101
+#include <sys/param.h>
102
+#include "block/block_int.h"
103
+#include "qapi/qmp/qerror.h"
104
+#include "qapi/qmp/qdict.h"
105
+#include "qapi/qmp/qstring.h"
106
+#include "trace.h"
107
+#include "qemu/uri.h"
108
+#include "qapi/error.h"
250
+#include "qapi/error.h"
109
+#include "qemu/uuid.h"
251
+#include "sysemu/event-loop-base.h"
110
+#include "crypto/tlscredsx509.h"
252
+
111
+
253
+typedef struct {
112
+#define VXHS_OPT_FILENAME "filename"
254
+ const char *name;
113
+#define VXHS_OPT_VDISK_ID "vdisk-id"
255
+ ptrdiff_t offset; /* field's byte offset in EventLoopBase struct */
114
+#define VXHS_OPT_SERVER "server"
256
+} EventLoopBaseParamInfo;
115
+#define VXHS_OPT_HOST "host"
257
+
116
+#define VXHS_OPT_PORT "port"
258
+static EventLoopBaseParamInfo aio_max_batch_info = {
117
+
259
+ "aio-max-batch", offsetof(EventLoopBase, aio_max_batch),
118
+/* Only accessed under QEMU global mutex */
260
+};
119
+static uint32_t vxhs_ref;
261
+
120
+
262
+static void event_loop_base_get_param(Object *obj, Visitor *v,
121
+typedef enum {
263
+ const char *name, void *opaque, Error **errp)
122
+ VDISK_AIO_READ,
123
+ VDISK_AIO_WRITE,
124
+} VDISKAIOCmd;
125
+
126
+/*
127
+ * HyperScale AIO callbacks structure
128
+ */
129
+typedef struct VXHSAIOCB {
130
+ BlockAIOCB common;
131
+ int err;
132
+} VXHSAIOCB;
133
+
134
+typedef struct VXHSvDiskHostsInfo {
135
+ void *dev_handle; /* Device handle */
136
+ char *host; /* Host name or IP */
137
+ int port; /* Host's port number */
138
+} VXHSvDiskHostsInfo;
139
+
140
+/*
141
+ * Structure per vDisk maintained for state
142
+ */
143
+typedef struct BDRVVXHSState {
144
+ VXHSvDiskHostsInfo vdisk_hostinfo; /* Per host info */
145
+ char *vdisk_guid;
146
+ char *tlscredsid; /* tlscredsid */
147
+} BDRVVXHSState;
148
+
149
+static void vxhs_complete_aio_bh(void *opaque)
150
+{
264
+{
151
+ VXHSAIOCB *acb = opaque;
265
+ EventLoopBase *event_loop_base = EVENT_LOOP_BASE(obj);
152
+ BlockCompletionFunc *cb = acb->common.cb;
266
+ EventLoopBaseParamInfo *info = opaque;
153
+ void *cb_opaque = acb->common.opaque;
267
+ int64_t *field = (void *)event_loop_base + info->offset;
154
+ int ret = 0;
268
+
155
+
269
+ visit_type_int64(v, name, field, errp);
156
+ if (acb->err != 0) {
157
+ trace_vxhs_complete_aio(acb, acb->err);
158
+ ret = (-EIO);
159
+ }
160
+
161
+ qemu_aio_unref(acb);
162
+ cb(cb_opaque, ret);
163
+}
270
+}
164
+
271
+
165
+/*
272
+static void event_loop_base_set_param(Object *obj, Visitor *v,
166
+ * Called from a libqnio thread
273
+ const char *name, void *opaque, Error **errp)
167
+ */
168
+static void vxhs_iio_callback(void *ctx, uint32_t opcode, uint32_t error)
169
+{
274
+{
170
+ VXHSAIOCB *acb = NULL;
275
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(obj);
171
+
276
+ EventLoopBase *base = EVENT_LOOP_BASE(obj);
172
+ switch (opcode) {
277
+ EventLoopBaseParamInfo *info = opaque;
173
+ case IRP_READ_REQUEST:
278
+ int64_t *field = (void *)base + info->offset;
174
+ case IRP_WRITE_REQUEST:
279
+ int64_t value;
175
+
280
+
176
+ /*
281
+ if (!visit_type_int64(v, name, &value, errp)) {
177
+ * ctx is VXHSAIOCB*
282
+ return;
178
+ * ctx is NULL if error is QNIOERROR_CHANNEL_HUP
283
+ }
179
+ */
284
+
180
+ if (ctx) {
285
+ if (value < 0) {
181
+ acb = ctx;
286
+ error_setg(errp, "%s value must be in range [0, %" PRId64 "]",
182
+ } else {
287
+ info->name, INT64_MAX);
183
+ trace_vxhs_iio_callback(error);
288
+ return;
184
+ goto out;
289
+ }
185
+ }
290
+
186
+
291
+ *field = value;
187
+ if (error) {
292
+
188
+ if (!acb->err) {
293
+ if (bc->update_params) {
189
+ acb->err = error;
294
+ bc->update_params(base, errp);
190
+ }
295
+ }
191
+ trace_vxhs_iio_callback(error);
296
+
192
+ }
193
+
194
+ aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
195
+ vxhs_complete_aio_bh, acb);
196
+ break;
197
+
198
+ default:
199
+ if (error == QNIOERROR_HUP) {
200
+ /*
201
+ * Channel failed, spontaneous notification,
202
+ * not in response to I/O
203
+ */
204
+ trace_vxhs_iio_callback_chnfail(error, errno);
205
+ } else {
206
+ trace_vxhs_iio_callback_unknwn(opcode, error);
207
+ }
208
+ break;
209
+ }
210
+out:
211
+ return;
297
+ return;
212
+}
298
+}
213
+
299
+
214
+static QemuOptsList runtime_opts = {
300
+static void event_loop_base_complete(UserCreatable *uc, Error **errp)
215
+ .name = "vxhs",
301
+{
216
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
302
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(uc);
217
+ .desc = {
303
+ EventLoopBase *base = EVENT_LOOP_BASE(uc);
218
+ {
304
+
219
+ .name = VXHS_OPT_FILENAME,
305
+ if (bc->init) {
220
+ .type = QEMU_OPT_STRING,
306
+ bc->init(base, errp);
221
+ .help = "URI to the Veritas HyperScale image",
307
+ }
222
+ },
308
+}
223
+ {
309
+
224
+ .name = VXHS_OPT_VDISK_ID,
310
+static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
225
+ .type = QEMU_OPT_STRING,
311
+{
226
+ .help = "UUID of the VxHS vdisk",
312
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
227
+ },
313
+ ucc->complete = event_loop_base_complete;
228
+ {
314
+
229
+ .name = "tls-creds",
315
+ object_class_property_add(klass, "aio-max-batch", "int",
230
+ .type = QEMU_OPT_STRING,
316
+ event_loop_base_get_param,
231
+ .help = "ID of the TLS/SSL credentials to use",
317
+ event_loop_base_set_param,
232
+ },
318
+ NULL, &aio_max_batch_info);
233
+ { /* end of list */ }
319
+}
234
+ },
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
+ }
235
+};
332
+};
236
+
333
+
237
+static QemuOptsList runtime_tcp_opts = {
334
+static void register_types(void)
238
+ .name = "vxhs_tcp",
239
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_tcp_opts.head),
240
+ .desc = {
241
+ {
242
+ .name = VXHS_OPT_HOST,
243
+ .type = QEMU_OPT_STRING,
244
+ .help = "host address (ipv4 addresses)",
245
+ },
246
+ {
247
+ .name = VXHS_OPT_PORT,
248
+ .type = QEMU_OPT_NUMBER,
249
+ .help = "port number on which VxHSD is listening (default 9999)",
250
+ .def_value_str = "9999"
251
+ },
252
+ { /* end of list */ }
253
+ },
254
+};
255
+
256
+/*
257
+ * Parse incoming URI and populate *options with the host
258
+ * and device information
259
+ */
260
+static int vxhs_parse_uri(const char *filename, QDict *options)
261
+{
335
+{
262
+ URI *uri = NULL;
336
+ type_register_static(&event_loop_base_info);
263
+ char *port;
264
+ int ret = 0;
265
+
266
+ trace_vxhs_parse_uri_filename(filename);
267
+ uri = uri_parse(filename);
268
+ if (!uri || !uri->server || !uri->path) {
269
+ uri_free(uri);
270
+ return -EINVAL;
271
+ }
272
+
273
+ qdict_put(options, VXHS_OPT_SERVER".host", qstring_from_str(uri->server));
274
+
275
+ if (uri->port) {
276
+ port = g_strdup_printf("%d", uri->port);
277
+ qdict_put(options, VXHS_OPT_SERVER".port", qstring_from_str(port));
278
+ g_free(port);
279
+ }
280
+
281
+ qdict_put(options, "vdisk-id", qstring_from_str(uri->path));
282
+
283
+ trace_vxhs_parse_uri_hostinfo(uri->server, uri->port);
284
+ uri_free(uri);
285
+
286
+ return ret;
287
+}
337
+}
288
+
338
+type_init(register_types);
289
+static void vxhs_parse_filename(const char *filename, QDict *options,
339
diff --git a/iothread.c b/iothread.c
290
+ Error **errp)
340
index XXXXXXX..XXXXXXX 100644
291
+{
341
--- a/iothread.c
292
+ if (qdict_haskey(options, "vdisk-id") || qdict_haskey(options, "server")) {
342
+++ b/iothread.c
293
+ error_setg(errp, "vdisk-id/server and a file name may not be specified "
343
@@ -XXX,XX +XXX,XX @@
294
+ "at the same time");
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);
353
}
354
355
-static void iothread_set_aio_context_params(IOThread *iothread, Error **errp)
356
+static void iothread_set_aio_context_params(EventLoopBase *base, Error **errp)
357
{
358
+ IOThread *iothread = IOTHREAD(base);
359
ERRP_GUARD();
360
361
+ if (!iothread->ctx) {
295
+ return;
362
+ return;
296
+ }
363
+ }
297
+
364
+
298
+ if (strstr(filename, "://")) {
365
aio_context_set_poll_params(iothread->ctx,
299
+ int ret = vxhs_parse_uri(filename, options);
366
iothread->poll_max_ns,
300
+ if (ret < 0) {
367
iothread->poll_grow,
301
+ error_setg(errp, "Invalid URI. URI should be of the form "
368
@@ -XXX,XX +XXX,XX @@ static void iothread_set_aio_context_params(IOThread *iothread, Error **errp)
302
+ " vxhs://<host_ip>:<port>/<vdisk-id>");
369
}
303
+ }
370
304
+ }
371
aio_context_set_aio_params(iothread->ctx,
305
+}
372
- iothread->aio_max_batch,
306
+
373
+ iothread->parent_obj.aio_max_batch,
307
+static int vxhs_init_and_ref(void)
374
errp);
308
+{
375
}
309
+ if (vxhs_ref++ == 0) {
376
310
+ if (iio_init(QNIO_VERSION, vxhs_iio_callback)) {
377
-static void iothread_complete(UserCreatable *obj, Error **errp)
311
+ return -ENODEV;
378
+
312
+ }
379
+static void iothread_init(EventLoopBase *base, Error **errp)
313
+ }
380
{
314
+ return 0;
381
Error *local_error = NULL;
315
+}
382
- IOThread *iothread = IOTHREAD(obj);
316
+
383
+ IOThread *iothread = IOTHREAD(base);
317
+static void vxhs_unref(void)
384
char *thread_name;
318
+{
385
319
+ if (--vxhs_ref == 0) {
386
iothread->stopping = false;
320
+ iio_fini();
387
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
321
+ }
388
*/
322
+}
389
iothread_init_gcontext(iothread);
323
+
390
324
+static void vxhs_get_tls_creds(const char *id, char **cacert,
391
- iothread_set_aio_context_params(iothread, &local_error);
325
+ char **key, char **cert, Error **errp)
392
+ iothread_set_aio_context_params(base, &local_error);
326
+{
393
if (local_error) {
327
+ Object *obj;
394
error_propagate(errp, local_error);
328
+ QCryptoTLSCreds *creds;
395
aio_context_unref(iothread->ctx);
329
+ QCryptoTLSCredsX509 *creds_x509;
396
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
330
+
397
* to inherit.
331
+ obj = object_resolve_path_component(
398
*/
332
+ object_get_objects_root(), id);
399
thread_name = g_strdup_printf("IO %s",
333
+
400
- object_get_canonical_path_component(OBJECT(obj)));
334
+ if (!obj) {
401
+ object_get_canonical_path_component(OBJECT(base)));
335
+ error_setg(errp, "No TLS credentials with id '%s'",
402
qemu_thread_create(&iothread->thread, thread_name, iothread_run,
336
+ id);
403
iothread, QEMU_THREAD_JOINABLE);
337
+ return;
404
g_free(thread_name);
338
+ }
405
@@ -XXX,XX +XXX,XX @@ static IOThreadParamInfo poll_grow_info = {
339
+
406
static IOThreadParamInfo poll_shrink_info = {
340
+ creds_x509 = (QCryptoTLSCredsX509 *)
407
"poll-shrink", offsetof(IOThread, poll_shrink),
341
+ object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS_X509);
408
};
342
+
409
-static IOThreadParamInfo aio_max_batch_info = {
343
+ if (!creds_x509) {
410
- "aio-max-batch", offsetof(IOThread, aio_max_batch),
344
+ error_setg(errp, "Object with id '%s' is not TLS credentials",
411
-};
345
+ id);
412
346
+ return;
413
static void iothread_get_param(Object *obj, Visitor *v,
347
+ }
414
const char *name, IOThreadParamInfo *info, Error **errp)
348
+
415
@@ -XXX,XX +XXX,XX @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
349
+ creds = &creds_x509->parent_obj;
416
}
350
+
417
}
351
+ if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
418
352
+ error_setg(errp,
419
-static void iothread_get_aio_param(Object *obj, Visitor *v,
353
+ "Expecting TLS credentials with a client endpoint");
420
- const char *name, void *opaque, Error **errp)
354
+ return;
421
-{
355
+ }
422
- IOThreadParamInfo *info = opaque;
356
+
423
-
357
+ /*
424
- iothread_get_param(obj, v, name, info, errp);
358
+ * Get the cacert, client_cert and client_key file names.
425
-}
359
+ */
426
-
360
+ if (!creds->dir) {
427
-static void iothread_set_aio_param(Object *obj, Visitor *v,
361
+ error_setg(errp, "TLS object missing 'dir' property value");
428
- const char *name, void *opaque, Error **errp)
362
+ return;
429
-{
363
+ }
430
- IOThread *iothread = IOTHREAD(obj);
364
+
431
- IOThreadParamInfo *info = opaque;
365
+ *cacert = g_strdup_printf("%s/%s", creds->dir,
432
-
366
+ QCRYPTO_TLS_CREDS_X509_CA_CERT);
433
- if (!iothread_set_param(obj, v, name, info, errp)) {
367
+ *cert = g_strdup_printf("%s/%s", creds->dir,
434
- return;
368
+ QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
435
- }
369
+ *key = g_strdup_printf("%s/%s", creds->dir,
436
-
370
+ QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
437
- if (iothread->ctx) {
371
+}
438
- aio_context_set_aio_params(iothread->ctx,
372
+
439
- iothread->aio_max_batch,
373
+static int vxhs_open(BlockDriverState *bs, QDict *options,
440
- errp);
374
+ int bdrv_flags, Error **errp)
441
- }
375
+{
442
-}
376
+ BDRVVXHSState *s = bs->opaque;
443
-
377
+ void *dev_handlep;
444
static void iothread_class_init(ObjectClass *klass, void *class_data)
378
+ QDict *backing_options = NULL;
445
{
379
+ QemuOpts *opts = NULL;
446
- UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
380
+ QemuOpts *tcp_opts = NULL;
447
- ucc->complete = iothread_complete;
381
+ char *of_vsa_addr = NULL;
448
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_CLASS(klass);
382
+ Error *local_err = NULL;
449
+
383
+ const char *vdisk_id_opt;
450
+ bc->init = iothread_init;
384
+ const char *server_host_opt;
451
+ bc->update_params = iothread_set_aio_context_params;
385
+ int ret = 0;
452
386
+ char *cacert = NULL;
453
object_class_property_add(klass, "poll-max-ns", "int",
387
+ char *client_key = NULL;
454
iothread_get_poll_param,
388
+ char *client_cert = NULL;
455
@@ -XXX,XX +XXX,XX @@ static void iothread_class_init(ObjectClass *klass, void *class_data)
389
+
456
iothread_get_poll_param,
390
+ ret = vxhs_init_and_ref();
457
iothread_set_poll_param,
391
+ if (ret < 0) {
458
NULL, &poll_shrink_info);
392
+ ret = -EINVAL;
459
- object_class_property_add(klass, "aio-max-batch", "int",
393
+ goto out;
460
- iothread_get_aio_param,
394
+ }
461
- iothread_set_aio_param,
395
+
462
- NULL, &aio_max_batch_info);
396
+ /* Create opts info from runtime_opts and runtime_tcp_opts list */
463
}
397
+ opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
464
398
+ tcp_opts = qemu_opts_create(&runtime_tcp_opts, NULL, 0, &error_abort);
465
static const TypeInfo iothread_info = {
399
+
466
.name = TYPE_IOTHREAD,
400
+ qemu_opts_absorb_qdict(opts, options, &local_err);
467
- .parent = TYPE_OBJECT,
401
+ if (local_err) {
468
+ .parent = TYPE_EVENT_LOOP_BASE,
402
+ ret = -EINVAL;
469
.class_init = iothread_class_init,
403
+ goto out;
470
.instance_size = sizeof(IOThread),
404
+ }
471
.instance_init = iothread_instance_init,
405
+
472
.instance_finalize = iothread_instance_finalize,
406
+ /* vdisk-id is the disk UUID */
473
- .interfaces = (InterfaceInfo[]) {
407
+ vdisk_id_opt = qemu_opt_get(opts, VXHS_OPT_VDISK_ID);
474
- {TYPE_USER_CREATABLE},
408
+ if (!vdisk_id_opt) {
475
- {}
409
+ error_setg(&local_err, QERR_MISSING_PARAMETER, VXHS_OPT_VDISK_ID);
476
- },
410
+ ret = -EINVAL;
477
};
411
+ goto out;
478
412
+ }
479
static void iothread_register_types(void)
413
+
480
@@ -XXX,XX +XXX,XX @@ static int query_one_iothread(Object *object, void *opaque)
414
+ /* vdisk-id may contain a leading '/' */
481
info->poll_max_ns = iothread->poll_max_ns;
415
+ if (strlen(vdisk_id_opt) > UUID_FMT_LEN + 1) {
482
info->poll_grow = iothread->poll_grow;
416
+ error_setg(&local_err, "vdisk-id cannot be more than %d characters",
483
info->poll_shrink = iothread->poll_shrink;
417
+ UUID_FMT_LEN);
484
- info->aio_max_batch = iothread->aio_max_batch;
418
+ ret = -EINVAL;
485
+ info->aio_max_batch = iothread->parent_obj.aio_max_batch;
419
+ goto out;
486
420
+ }
487
QAPI_LIST_APPEND(*tail, info);
421
+
488
return 0;
422
+ s->vdisk_guid = g_strdup(vdisk_id_opt);
423
+ trace_vxhs_open_vdiskid(vdisk_id_opt);
424
+
425
+ /* get the 'server.' arguments */
426
+ qdict_extract_subqdict(options, &backing_options, VXHS_OPT_SERVER".");
427
+
428
+ qemu_opts_absorb_qdict(tcp_opts, backing_options, &local_err);
429
+ if (local_err != NULL) {
430
+ ret = -EINVAL;
431
+ goto out;
432
+ }
433
+
434
+ server_host_opt = qemu_opt_get(tcp_opts, VXHS_OPT_HOST);
435
+ if (!server_host_opt) {
436
+ error_setg(&local_err, QERR_MISSING_PARAMETER,
437
+ VXHS_OPT_SERVER"."VXHS_OPT_HOST);
438
+ ret = -EINVAL;
439
+ goto out;
440
+ }
441
+
442
+ if (strlen(server_host_opt) > MAXHOSTNAMELEN) {
443
+ error_setg(&local_err, "server.host cannot be more than %d characters",
444
+ MAXHOSTNAMELEN);
445
+ ret = -EINVAL;
446
+ goto out;
447
+ }
448
+
449
+ /* check if we got tls-creds via the --object argument */
450
+ s->tlscredsid = g_strdup(qemu_opt_get(opts, "tls-creds"));
451
+ if (s->tlscredsid) {
452
+ vxhs_get_tls_creds(s->tlscredsid, &cacert, &client_key,
453
+ &client_cert, &local_err);
454
+ if (local_err != NULL) {
455
+ ret = -EINVAL;
456
+ goto out;
457
+ }
458
+ trace_vxhs_get_creds(cacert, client_key, client_cert);
459
+ }
460
+
461
+ s->vdisk_hostinfo.host = g_strdup(server_host_opt);
462
+ s->vdisk_hostinfo.port = g_ascii_strtoll(qemu_opt_get(tcp_opts,
463
+ VXHS_OPT_PORT),
464
+ NULL, 0);
465
+
466
+ trace_vxhs_open_hostinfo(s->vdisk_hostinfo.host,
467
+ s->vdisk_hostinfo.port);
468
+
469
+ of_vsa_addr = g_strdup_printf("of://%s:%d",
470
+ s->vdisk_hostinfo.host,
471
+ s->vdisk_hostinfo.port);
472
+
473
+ /*
474
+ * Open qnio channel to storage agent if not opened before
475
+ */
476
+ dev_handlep = iio_open(of_vsa_addr, s->vdisk_guid, 0,
477
+ cacert, client_key, client_cert);
478
+ if (dev_handlep == NULL) {
479
+ trace_vxhs_open_iio_open(of_vsa_addr);
480
+ ret = -ENODEV;
481
+ goto out;
482
+ }
483
+ s->vdisk_hostinfo.dev_handle = dev_handlep;
484
+
485
+out:
486
+ g_free(of_vsa_addr);
487
+ QDECREF(backing_options);
488
+ qemu_opts_del(tcp_opts);
489
+ qemu_opts_del(opts);
490
+ g_free(cacert);
491
+ g_free(client_key);
492
+ g_free(client_cert);
493
+
494
+ if (ret < 0) {
495
+ vxhs_unref();
496
+ error_propagate(errp, local_err);
497
+ g_free(s->vdisk_hostinfo.host);
498
+ g_free(s->vdisk_guid);
499
+ g_free(s->tlscredsid);
500
+ s->vdisk_guid = NULL;
501
+ }
502
+
503
+ return ret;
504
+}
505
+
506
+static const AIOCBInfo vxhs_aiocb_info = {
507
+ .aiocb_size = sizeof(VXHSAIOCB)
508
+};
509
+
510
+/*
511
+ * This allocates QEMU-VXHS callback for each IO
512
+ * and is passed to QNIO. When QNIO completes the work,
513
+ * it will be passed back through the callback.
514
+ */
515
+static BlockAIOCB *vxhs_aio_rw(BlockDriverState *bs, int64_t sector_num,
516
+ QEMUIOVector *qiov, int nb_sectors,
517
+ BlockCompletionFunc *cb, void *opaque,
518
+ VDISKAIOCmd iodir)
519
+{
520
+ VXHSAIOCB *acb = NULL;
521
+ BDRVVXHSState *s = bs->opaque;
522
+ size_t size;
523
+ uint64_t offset;
524
+ int iio_flags = 0;
525
+ int ret = 0;
526
+ void *dev_handle = s->vdisk_hostinfo.dev_handle;
527
+
528
+ offset = sector_num * BDRV_SECTOR_SIZE;
529
+ size = nb_sectors * BDRV_SECTOR_SIZE;
530
+ acb = qemu_aio_get(&vxhs_aiocb_info, bs, cb, opaque);
531
+
532
+ /*
533
+ * Initialize VXHSAIOCB.
534
+ */
535
+ acb->err = 0;
536
+
537
+ iio_flags = IIO_FLAG_ASYNC;
538
+
539
+ switch (iodir) {
540
+ case VDISK_AIO_WRITE:
541
+ ret = iio_writev(dev_handle, acb, qiov->iov, qiov->niov,
542
+ offset, (uint64_t)size, iio_flags);
543
+ break;
544
+ case VDISK_AIO_READ:
545
+ ret = iio_readv(dev_handle, acb, qiov->iov, qiov->niov,
546
+ offset, (uint64_t)size, iio_flags);
547
+ break;
548
+ default:
549
+ trace_vxhs_aio_rw_invalid(iodir);
550
+ goto errout;
551
+ }
552
+
553
+ if (ret != 0) {
554
+ trace_vxhs_aio_rw_ioerr(s->vdisk_guid, iodir, size, offset,
555
+ acb, ret, errno);
556
+ goto errout;
557
+ }
558
+ return &acb->common;
559
+
560
+errout:
561
+ qemu_aio_unref(acb);
562
+ return NULL;
563
+}
564
+
565
+static BlockAIOCB *vxhs_aio_readv(BlockDriverState *bs,
566
+ int64_t sector_num, QEMUIOVector *qiov,
567
+ int nb_sectors,
568
+ BlockCompletionFunc *cb, void *opaque)
569
+{
570
+ return vxhs_aio_rw(bs, sector_num, qiov, nb_sectors, cb,
571
+ opaque, VDISK_AIO_READ);
572
+}
573
+
574
+static BlockAIOCB *vxhs_aio_writev(BlockDriverState *bs,
575
+ int64_t sector_num, QEMUIOVector *qiov,
576
+ int nb_sectors,
577
+ BlockCompletionFunc *cb, void *opaque)
578
+{
579
+ return vxhs_aio_rw(bs, sector_num, qiov, nb_sectors,
580
+ cb, opaque, VDISK_AIO_WRITE);
581
+}
582
+
583
+static void vxhs_close(BlockDriverState *bs)
584
+{
585
+ BDRVVXHSState *s = bs->opaque;
586
+
587
+ trace_vxhs_close(s->vdisk_guid);
588
+
589
+ g_free(s->vdisk_guid);
590
+ s->vdisk_guid = NULL;
591
+
592
+ /*
593
+ * Close vDisk device
594
+ */
595
+ if (s->vdisk_hostinfo.dev_handle) {
596
+ iio_close(s->vdisk_hostinfo.dev_handle);
597
+ s->vdisk_hostinfo.dev_handle = NULL;
598
+ }
599
+
600
+ vxhs_unref();
601
+
602
+ /*
603
+ * Free the dynamically allocated host string etc
604
+ */
605
+ g_free(s->vdisk_hostinfo.host);
606
+ g_free(s->tlscredsid);
607
+ s->tlscredsid = NULL;
608
+ s->vdisk_hostinfo.host = NULL;
609
+ s->vdisk_hostinfo.port = 0;
610
+}
611
+
612
+static int64_t vxhs_get_vdisk_stat(BDRVVXHSState *s)
613
+{
614
+ int64_t vdisk_size = -1;
615
+ int ret = 0;
616
+ void *dev_handle = s->vdisk_hostinfo.dev_handle;
617
+
618
+ ret = iio_ioctl(dev_handle, IOR_VDISK_STAT, &vdisk_size, 0);
619
+ if (ret < 0) {
620
+ trace_vxhs_get_vdisk_stat_err(s->vdisk_guid, ret, errno);
621
+ return -EIO;
622
+ }
623
+
624
+ trace_vxhs_get_vdisk_stat(s->vdisk_guid, vdisk_size);
625
+ return vdisk_size;
626
+}
627
+
628
+/*
629
+ * Returns the size of vDisk in bytes. This is required
630
+ * by QEMU block upper block layer so that it is visible
631
+ * to guest.
632
+ */
633
+static int64_t vxhs_getlength(BlockDriverState *bs)
634
+{
635
+ BDRVVXHSState *s = bs->opaque;
636
+ int64_t vdisk_size;
637
+
638
+ vdisk_size = vxhs_get_vdisk_stat(s);
639
+ if (vdisk_size < 0) {
640
+ return -EIO;
641
+ }
642
+
643
+ return vdisk_size;
644
+}
645
+
646
+static BlockDriver bdrv_vxhs = {
647
+ .format_name = "vxhs",
648
+ .protocol_name = "vxhs",
649
+ .instance_size = sizeof(BDRVVXHSState),
650
+ .bdrv_file_open = vxhs_open,
651
+ .bdrv_parse_filename = vxhs_parse_filename,
652
+ .bdrv_close = vxhs_close,
653
+ .bdrv_getlength = vxhs_getlength,
654
+ .bdrv_aio_readv = vxhs_aio_readv,
655
+ .bdrv_aio_writev = vxhs_aio_writev,
656
+};
657
+
658
+static void bdrv_vxhs_init(void)
659
+{
660
+ bdrv_register(&bdrv_vxhs);
661
+}
662
+
663
+block_init(bdrv_vxhs_init);
664
diff --git a/configure b/configure
665
index XXXXXXX..XXXXXXX 100755
666
--- a/configure
667
+++ b/configure
668
@@ -XXX,XX +XXX,XX @@ numa=""
669
tcmalloc="no"
670
jemalloc="no"
671
replication="yes"
672
+vxhs=""
673
674
supported_cpu="no"
675
supported_os="no"
676
@@ -XXX,XX +XXX,XX @@ for opt do
677
;;
678
--enable-replication) replication="yes"
679
;;
680
+ --disable-vxhs) vxhs="no"
681
+ ;;
682
+ --enable-vxhs) vxhs="yes"
683
+ ;;
684
*)
685
echo "ERROR: unknown option $opt"
686
echo "Try '$0 --help' for more information"
687
@@ -XXX,XX +XXX,XX @@ disabled with --disable-FEATURE, default is enabled if available:
688
xfsctl xfsctl support
689
qom-cast-debug cast debugging support
690
tools build qemu-io, qemu-nbd and qemu-image tools
691
+ vxhs Veritas HyperScale vDisk backend support
692
693
NOTE: The object files are built at the place where configure is launched
694
EOF
695
@@ -XXX,XX +XXX,XX @@ if compile_prog "" "" ; then
696
fi
697
698
##########################################
699
+# Veritas HyperScale block driver VxHS
700
+# Check if libvxhs is installed
701
+
702
+if test "$vxhs" != "no" ; then
703
+ cat > $TMPC <<EOF
704
+#include <stdint.h>
705
+#include <qnio/qnio_api.h>
706
+
707
+void *vxhs_callback;
708
+
709
+int main(void) {
710
+ iio_init(QNIO_VERSION, vxhs_callback);
711
+ return 0;
712
+}
713
+EOF
714
+ vxhs_libs="-lvxhs -lssl"
715
+ if compile_prog "" "$vxhs_libs" ; then
716
+ vxhs=yes
717
+ else
718
+ if test "$vxhs" = "yes" ; then
719
+ feature_not_found "vxhs block device" "Install libvxhs See github"
720
+ fi
721
+ vxhs=no
722
+ fi
723
+fi
724
+
725
+##########################################
726
# End of CC checks
727
# After here, no more $cc or $ld runs
728
729
@@ -XXX,XX +XXX,XX @@ echo "tcmalloc support $tcmalloc"
730
echo "jemalloc support $jemalloc"
731
echo "avx2 optimization $avx2_opt"
732
echo "replication support $replication"
733
+echo "VxHS block device $vxhs"
734
735
if test "$sdl_too_old" = "yes"; then
736
echo "-> Your SDL version is too old - please upgrade to have SDL support"
737
@@ -XXX,XX +XXX,XX @@ if test "$pthread_setname_np" = "yes" ; then
738
echo "CONFIG_PTHREAD_SETNAME_NP=y" >> $config_host_mak
739
fi
740
741
+if test "$vxhs" = "yes" ; then
742
+ echo "CONFIG_VXHS=y" >> $config_host_mak
743
+ echo "VXHS_LIBS=$vxhs_libs" >> $config_host_mak
744
+fi
745
+
746
if test "$tcg_interpreter" = "yes"; then
747
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
748
elif test "$ARCH" = "sparc64" ; then
749
diff --git a/qapi/block-core.json b/qapi/block-core.json
750
index XXXXXXX..XXXXXXX 100644
751
--- a/qapi/block-core.json
752
+++ b/qapi/block-core.json
753
@@ -XXX,XX +XXX,XX @@
754
#
755
# Drivers that are supported in block device operations.
756
#
757
+# @vxhs: Since 2.10
758
+#
759
# Since: 2.9
760
##
761
{ 'enum': 'BlockdevDriver',
762
@@ -XXX,XX +XXX,XX @@
763
'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
764
'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
765
'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
766
- 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
767
+ 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
768
769
##
770
# @BlockdevOptionsFile:
771
@@ -XXX,XX +XXX,XX @@
772
'data': { '*offset': 'int', '*size': 'int' } }
773
774
##
775
+# @BlockdevOptionsVxHS:
776
+#
777
+# Driver specific block device options for VxHS
778
+#
779
+# @vdisk-id: UUID of VxHS volume
780
+# @server: vxhs server IP, port
781
+# @tls-creds: TLS credentials ID
782
+#
783
+# Since: 2.10
784
+##
785
+{ 'struct': 'BlockdevOptionsVxHS',
786
+ 'data': { 'vdisk-id': 'str',
787
+ 'server': 'InetSocketAddressBase',
788
+ '*tls-creds': 'str' } }
789
+
790
+##
791
# @BlockdevOptions:
792
#
793
# Options for creating a block device. Many options are available for all
794
@@ -XXX,XX +XXX,XX @@
795
'vhdx': 'BlockdevOptionsGenericFormat',
796
'vmdk': 'BlockdevOptionsGenericCOWFormat',
797
'vpc': 'BlockdevOptionsGenericFormat',
798
- 'vvfat': 'BlockdevOptionsVVFAT'
799
+ 'vvfat': 'BlockdevOptionsVVFAT',
800
+ 'vxhs': 'BlockdevOptionsVxHS'
801
} }
802
803
##
804
--
489
--
805
2.9.3
490
2.35.1
806
807
diff view generated by jsdifflib
Deleted patch
1
From: Ashish Mittal <ashmit602@gmail.com>
2
1
3
These changes use a vxhs test server that is a part of the following
4
repository:
5
https://github.com/VeritasHyperScale/libqnio.git
6
7
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
10
Signed-off-by: Jeff Cody <jcody@redhat.com>
11
Message-id: 1491277689-24949-3-git-send-email-Ashish.Mittal@veritas.com
12
---
13
tests/qemu-iotests/common | 6 ++++++
14
tests/qemu-iotests/common.config | 13 +++++++++++++
15
tests/qemu-iotests/common.filter | 1 +
16
tests/qemu-iotests/common.rc | 19 +++++++++++++++++++
17
4 files changed, 39 insertions(+)
18
19
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
20
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/common
22
+++ b/tests/qemu-iotests/common
23
@@ -XXX,XX +XXX,XX @@ check options
24
-ssh test ssh
25
-nfs test nfs
26
-luks test luks
27
+ -vxhs test vxhs
28
-xdiff graphical mode diff
29
-nocache use O_DIRECT on backing file
30
-misalign misalign memory allocations
31
@@ -XXX,XX +XXX,XX @@ testlist options
32
xpand=false
33
;;
34
35
+ -vxhs)
36
+ IMGPROTO=vxhs
37
+ xpand=false
38
+ ;;
39
+
40
-ssh)
41
IMGPROTO=ssh
42
xpand=false
43
diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
44
index XXXXXXX..XXXXXXX 100644
45
--- a/tests/qemu-iotests/common.config
46
+++ b/tests/qemu-iotests/common.config
47
@@ -XXX,XX +XXX,XX @@ if [ -z "$QEMU_NBD_PROG" ]; then
48
export QEMU_NBD_PROG="`set_prog_path qemu-nbd`"
49
fi
50
51
+if [ -z "$QEMU_VXHS_PROG" ]; then
52
+ export QEMU_VXHS_PROG="`set_prog_path qnio_server`"
53
+fi
54
+
55
_qemu_wrapper()
56
{
57
(
58
@@ -XXX,XX +XXX,XX @@ _qemu_nbd_wrapper()
59
)
60
}
61
62
+_qemu_vxhs_wrapper()
63
+{
64
+ (
65
+ echo $BASHPID > "${TEST_DIR}/qemu-vxhs.pid"
66
+ exec "$QEMU_VXHS_PROG" $QEMU_VXHS_OPTIONS "$@"
67
+ )
68
+}
69
+
70
export QEMU=_qemu_wrapper
71
export QEMU_IMG=_qemu_img_wrapper
72
export QEMU_IO=_qemu_io_wrapper
73
export QEMU_NBD=_qemu_nbd_wrapper
74
+export QEMU_VXHS=_qemu_vxhs_wrapper
75
76
QEMU_IMG_EXTRA_ARGS=
77
if [ "$IMGOPTSSYNTAX" = "true" ]; then
78
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
79
index XXXXXXX..XXXXXXX 100644
80
--- a/tests/qemu-iotests/common.filter
81
+++ b/tests/qemu-iotests/common.filter
82
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
83
-e "s#$TEST_DIR#TEST_DIR#g" \
84
-e "s#$IMGFMT#IMGFMT#g" \
85
-e 's#nbd://127.0.0.1:10810$#TEST_DIR/t.IMGFMT#g' \
86
+ -e 's#json.*vdisk-id.*vxhs"}}#TEST_DIR/t.IMGFMT#' \
87
-e "/encrypted: yes/d" \
88
-e "/cluster_size: [0-9]\\+/d" \
89
-e "/table_size: [0-9]\\+/d" \
90
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
91
index XXXXXXX..XXXXXXX 100644
92
--- a/tests/qemu-iotests/common.rc
93
+++ b/tests/qemu-iotests/common.rc
94
@@ -XXX,XX +XXX,XX @@ else
95
elif [ "$IMGPROTO" = "nfs" ]; then
96
TEST_DIR="nfs://127.0.0.1/$TEST_DIR"
97
TEST_IMG=$TEST_DIR/t.$IMGFMT
98
+ elif [ "$IMGPROTO" = "vxhs" ]; then
99
+ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
100
+ TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT"
101
else
102
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
103
fi
104
@@ -XXX,XX +XXX,XX @@ _make_test_img()
105
eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT $TEST_IMG_FILE >/dev/null &"
106
sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
107
fi
108
+
109
+ # Start QNIO server on image directory for vxhs protocol
110
+ if [ $IMGPROTO = "vxhs" ]; then
111
+ eval "$QEMU_VXHS -d $TEST_DIR > /dev/null &"
112
+ sleep 1 # Wait for server to come up.
113
+ fi
114
}
115
116
_rm_test_img()
117
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img()
118
fi
119
rm -f "$TEST_IMG_FILE"
120
;;
121
+ vxhs)
122
+ if [ -f "${TEST_DIR}/qemu-vxhs.pid" ]; then
123
+ local QEMU_VXHS_PID
124
+ read QEMU_VXHS_PID < "${TEST_DIR}/qemu-vxhs.pid"
125
+ kill ${QEMU_VXHS_PID} >/dev/null 2>&1
126
+ rm -f "${TEST_DIR}/qemu-vxhs.pid"
127
+ fi
128
+ rm -f "$TEST_IMG_FILE"
129
+ ;;
130
+
131
file)
132
_rm_test_img "$TEST_DIR/t.$IMGFMT"
133
_rm_test_img "$TEST_DIR/t.$IMGFMT.orig"
134
--
135
2.9.3
136
137
diff view generated by jsdifflib
Deleted patch
1
The protocol VXHS does not support image creation. Some tests expect
2
to be able to create images through the protocol. Exclude VXHS from
3
these tests.
4
1
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
6
---
7
tests/qemu-iotests/017 | 1 +
8
tests/qemu-iotests/020 | 1 +
9
tests/qemu-iotests/029 | 1 +
10
tests/qemu-iotests/073 | 1 +
11
tests/qemu-iotests/114 | 1 +
12
tests/qemu-iotests/130 | 1 +
13
tests/qemu-iotests/134 | 1 +
14
tests/qemu-iotests/156 | 1 +
15
tests/qemu-iotests/158 | 1 +
16
9 files changed, 9 insertions(+)
17
18
diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/017
21
+++ b/tests/qemu-iotests/017
22
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
23
# Any format supporting backing files
24
_supported_fmt qcow qcow2 vmdk qed
25
_supported_proto generic
26
+_unsupported_proto vxhs
27
_supported_os Linux
28
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
29
30
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
31
index XXXXXXX..XXXXXXX 100755
32
--- a/tests/qemu-iotests/020
33
+++ b/tests/qemu-iotests/020
34
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
35
# Any format supporting backing files
36
_supported_fmt qcow qcow2 vmdk qed
37
_supported_proto generic
38
+_unsupported_proto vxhs
39
_supported_os Linux
40
_unsupported_imgopts "subformat=monolithicFlat" \
41
"subformat=twoGbMaxExtentFlat" \
42
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
43
index XXXXXXX..XXXXXXX 100755
44
--- a/tests/qemu-iotests/029
45
+++ b/tests/qemu-iotests/029
46
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
47
# Any format supporting intenal snapshots
48
_supported_fmt qcow2
49
_supported_proto generic
50
+_unsupported_proto vxhs
51
_supported_os Linux
52
# Internal snapshots are (currently) impossible with refcount_bits=1
53
_unsupported_imgopts 'refcount_bits=1[^0-9]'
54
diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073
55
index XXXXXXX..XXXXXXX 100755
56
--- a/tests/qemu-iotests/073
57
+++ b/tests/qemu-iotests/073
58
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
59
60
_supported_fmt qcow2
61
_supported_proto generic
62
+_unsupported_proto vxhs
63
_supported_os Linux
64
65
CLUSTER_SIZE=64k
66
diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114
67
index XXXXXXX..XXXXXXX 100755
68
--- a/tests/qemu-iotests/114
69
+++ b/tests/qemu-iotests/114
70
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
71
72
_supported_fmt qcow2
73
_supported_proto generic
74
+_unsupported_proto vxhs
75
_supported_os Linux
76
77
78
diff --git a/tests/qemu-iotests/130 b/tests/qemu-iotests/130
79
index XXXXXXX..XXXXXXX 100755
80
--- a/tests/qemu-iotests/130
81
+++ b/tests/qemu-iotests/130
82
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
83
84
_supported_fmt qcow2
85
_supported_proto generic
86
+_unsupported_proto vxhs
87
_supported_os Linux
88
89
qemu_comm_method="monitor"
90
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
91
index XXXXXXX..XXXXXXX 100755
92
--- a/tests/qemu-iotests/134
93
+++ b/tests/qemu-iotests/134
94
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
95
96
_supported_fmt qcow2
97
_supported_proto generic
98
+_unsupported_proto vxhs
99
_supported_os Linux
100
101
102
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
103
index XXXXXXX..XXXXXXX 100755
104
--- a/tests/qemu-iotests/156
105
+++ b/tests/qemu-iotests/156
106
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
107
108
_supported_fmt qcow2 qed
109
_supported_proto generic
110
+_unsupported_proto vxhs
111
_supported_os Linux
112
113
# Create source disk
114
diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158
115
index XXXXXXX..XXXXXXX 100755
116
--- a/tests/qemu-iotests/158
117
+++ b/tests/qemu-iotests/158
118
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
119
120
_supported_fmt qcow2
121
_supported_proto generic
122
+_unsupported_proto vxhs
123
_supported_os Linux
124
125
126
--
127
2.9.3
128
129
diff view generated by jsdifflib
Deleted patch
1
We have a helper wrapper for checking for the BDS read_only flag,
2
add a helper wrapper to set the read_only flag as well.
3
1
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
6
Reviewed-by: John Snow <jsnow@redhat.com>
7
Message-id: 9b18972d05f5fa2ac16c014f0af98d680553048d.1491597120.git.jcody@redhat.com
8
---
9
block.c | 5 +++++
10
block/bochs.c | 2 +-
11
block/cloop.c | 2 +-
12
block/dmg.c | 2 +-
13
block/rbd.c | 2 +-
14
block/vvfat.c | 4 ++--
15
include/block/block.h | 1 +
16
7 files changed, 12 insertions(+), 6 deletions(-)
17
18
diff --git a/block.c b/block.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
21
+++ b/block.c
22
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
23
}
24
}
25
26
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
27
+{
28
+ bs->read_only = read_only;
29
+}
30
+
31
void bdrv_get_full_backing_filename_from_filename(const char *backed,
32
const char *backing,
33
char *dest, size_t sz,
34
diff --git a/block/bochs.c b/block/bochs.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/bochs.c
37
+++ b/block/bochs.c
38
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
39
return -EINVAL;
40
}
41
42
- bs->read_only = true; /* no write support yet */
43
+ bdrv_set_read_only(bs, true); /* no write support yet */
44
45
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
46
if (ret < 0) {
47
diff --git a/block/cloop.c b/block/cloop.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/cloop.c
50
+++ b/block/cloop.c
51
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
52
return -EINVAL;
53
}
54
55
- bs->read_only = true;
56
+ bdrv_set_read_only(bs, true);
57
58
/* read header */
59
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
60
diff --git a/block/dmg.c b/block/dmg.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/dmg.c
63
+++ b/block/dmg.c
64
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
65
}
66
67
block_module_load_one("dmg-bz2");
68
- bs->read_only = true;
69
+ bdrv_set_read_only(bs, true);
70
71
s->n_chunks = 0;
72
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
73
diff --git a/block/rbd.c b/block/rbd.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/rbd.c
76
+++ b/block/rbd.c
77
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
78
goto failed_open;
79
}
80
81
- bs->read_only = (s->snap != NULL);
82
+ bdrv_set_read_only(bs, (s->snap != NULL));
83
84
qemu_opts_del(opts);
85
return 0;
86
diff --git a/block/vvfat.c b/block/vvfat.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/vvfat.c
89
+++ b/block/vvfat.c
90
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
91
s->current_cluster=0xffffffff;
92
93
/* read only is the default for safety */
94
- bs->read_only = true;
95
+ bdrv_set_read_only(bs, true);
96
s->qcow = NULL;
97
s->qcow_filename = NULL;
98
s->fat2 = NULL;
99
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
100
if (ret < 0) {
101
goto fail;
102
}
103
- bs->read_only = false;
104
+ bdrv_set_read_only(bs, false);
105
}
106
107
bs->total_sectors = cyls * heads * secs;
108
diff --git a/include/block/block.h b/include/block/block.h
109
index XXXXXXX..XXXXXXX 100644
110
--- a/include/block/block.h
111
+++ b/include/block/block.h
112
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
113
int64_t sector_num, int nb_sectors, int *pnum);
114
115
bool bdrv_is_read_only(BlockDriverState *bs);
116
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only);
117
bool bdrv_is_sg(BlockDriverState *bs);
118
bool bdrv_is_inserted(BlockDriverState *bs);
119
int bdrv_media_changed(BlockDriverState *bs);
120
--
121
2.9.3
122
123
diff view generated by jsdifflib
1
A few block drivers will set the BDS read_only flag from their
1
From: Nicolas Saenz Julienne <nsaenzju@redhat.com>
2
.bdrv_open() function. This means the bs->read_only flag could
2
3
be set after we enable copy_on_read, as the BDRV_O_COPY_ON_READ
3
'event-loop-base' provides basic property handling for all 'AioContext'
4
flag check occurs prior to the call to bdrv->bdrv_open().
4
based event loops. So let's define a new 'MainLoopClass' that inherits
5
5
from it. This will permit tweaking the main loop's properties through
6
This adds an error return to bdrv_set_read_only(), and an error will be
6
qapi as well as through the command line using the '-object' keyword[1].
7
return if we try to set the BDS to read_only while copy_on_read is
7
Only one instance of 'MainLoopClass' might be created at any time.
8
enabled.
8
9
9
'EventLoopBaseClass' learns a new callback, 'can_be_deleted()' so as to
10
This patch also changes the behavior of vvfat. Before, vvfat could
10
mark 'MainLoop' as non-deletable.
11
override the drive 'readonly' flag with its own, internal 'rw' flag.
11
12
12
[1] For example:
13
For instance, this -drive parameter would result in a writable image:
13
-object main-loop,id=main-loop,aio-max-batch=<value>
14
14
15
"-drive format=vvfat,dir=/tmp/vvfat,rw,if=virtio,readonly=on"
15
Signed-off-by: Nicolas Saenz Julienne <nsaenzju@redhat.com>
16
17
This is not correct. Now, attempting to use the above -drive parameter
18
will result in an error (i.e., 'rw' is incompatible with 'readonly=on').
19
20
Signed-off-by: Jeff Cody <jcody@redhat.com>
21
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
22
Reviewed-by: John Snow <jsnow@redhat.com>
17
Acked-by: Markus Armbruster <armbru@redhat.com>
23
Message-id: 0c5b4c1cc2c651471b131f21376dfd5ea24d2196.1491597120.git.jcody@redhat.com
18
Message-id: 20220425075723.20019-3-nsaenzju@redhat.com
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
24
---
20
---
25
block.c | 10 +++++++++-
21
qapi/qom.json | 13 ++++++++
26
block/bochs.c | 5 ++++-
22
meson.build | 3 +-
27
block/cloop.c | 5 ++++-
23
include/qemu/main-loop.h | 10 ++++++
28
block/dmg.c | 6 +++++-
24
include/sysemu/event-loop-base.h | 1 +
29
block/rbd.c | 11 ++++++++++-
25
event-loop-base.c | 13 ++++++++
30
block/vvfat.c | 19 +++++++++++++++----
26
util/main-loop.c | 56 ++++++++++++++++++++++++++++++++
31
include/block/block.h | 2 +-
27
6 files changed, 95 insertions(+), 1 deletion(-)
32
7 files changed, 48 insertions(+), 10 deletions(-)
28
33
29
diff --git a/qapi/qom.json b/qapi/qom.json
34
diff --git a/block.c b/block.c
30
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
31
--- a/qapi/qom.json
36
--- a/block.c
32
+++ b/qapi/qom.json
37
+++ b/block.c
33
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
34
'*poll-grow': 'int',
35
'*poll-shrink': 'int' } }
36
37
+##
38
+# @MainLoopProperties:
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)
39
}
122
}
40
}
123
}
41
124
42
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
125
+static bool event_loop_base_can_be_deleted(UserCreatable *uc)
43
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
126
+{
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)
44
{
138
{
45
+ /* Do not set read_only if copy_on_read is enabled */
139
UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
46
+ if (bs->copy_on_read && read_only) {
140
ucc->complete = event_loop_base_complete;
47
+ error_setg(errp, "Can't set node '%s' to r/o with copy-on-read enabled",
141
+ ucc->can_be_deleted = event_loop_base_can_be_deleted;
48
+ bdrv_get_device_or_node_name(bs));
142
49
+ return -EINVAL;
143
object_class_property_add(klass, "aio-max-batch", "int",
144
event_loop_base_get_param,
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;
50
+ }
166
+ }
51
+
167
+
52
bs->read_only = read_only;
168
+ aio_context_set_aio_params(qemu_aio_context, base->aio_max_batch, errp);
53
+ return 0;
169
+}
54
}
170
+
55
171
+MainLoop *mloop;
56
void bdrv_get_full_backing_filename_from_filename(const char *backed,
172
+
57
diff --git a/block/bochs.c b/block/bochs.c
173
+static void main_loop_init(EventLoopBase *base, Error **errp)
58
index XXXXXXX..XXXXXXX 100644
174
+{
59
--- a/block/bochs.c
175
+ MainLoop *m = MAIN_LOOP(base);
60
+++ b/block/bochs.c
176
+
61
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
177
+ if (mloop) {
62
return -EINVAL;
178
+ error_setg(errp, "only one main-loop instance allowed");
63
}
179
+ return;
64
65
- bdrv_set_read_only(bs, true); /* no write support yet */
66
+ ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
67
+ if (ret < 0) {
68
+ return ret;
69
+ }
180
+ }
70
181
+
71
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
182
+ main_loop_update_params(base, errp);
72
if (ret < 0) {
183
+
73
diff --git a/block/cloop.c b/block/cloop.c
184
+ mloop = m;
74
index XXXXXXX..XXXXXXX 100644
185
+ return;
75
--- a/block/cloop.c
186
+}
76
+++ b/block/cloop.c
187
+
77
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
188
+static bool main_loop_can_be_deleted(EventLoopBase *base)
78
return -EINVAL;
189
+{
79
}
190
+ return false;
80
191
+}
81
- bdrv_set_read_only(bs, true);
192
+
82
+ ret = bdrv_set_read_only(bs, true, errp);
193
+static void main_loop_class_init(ObjectClass *oc, void *class_data)
83
+ if (ret < 0) {
194
+{
84
+ return ret;
195
+ EventLoopBaseClass *bc = EVENT_LOOP_BASE_CLASS(oc);
85
+ }
196
+
86
197
+ bc->init = main_loop_init;
87
/* read header */
198
+ bc->update_params = main_loop_update_params;
88
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
199
+ bc->can_be_deleted = main_loop_can_be_deleted;
89
diff --git a/block/dmg.c b/block/dmg.c
200
+}
90
index XXXXXXX..XXXXXXX 100644
201
+
91
--- a/block/dmg.c
202
+static const TypeInfo main_loop_info = {
92
+++ b/block/dmg.c
203
+ .name = TYPE_MAIN_LOOP,
93
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
204
+ .parent = TYPE_EVENT_LOOP_BASE,
94
return -EINVAL;
205
+ .class_init = main_loop_class_init,
95
}
206
+ .instance_size = sizeof(MainLoop),
96
207
+};
97
+ ret = bdrv_set_read_only(bs, true, errp);
208
+
98
+ if (ret < 0) {
209
+static void main_loop_register_types(void)
99
+ return ret;
210
+{
100
+ }
211
+ type_register_static(&main_loop_info);
101
+
212
+}
102
block_module_load_one("dmg-bz2");
213
+
103
- bdrv_set_read_only(bs, true);
214
+type_init(main_loop_register_types)
104
215
+
105
s->n_chunks = 0;
216
static int max_priority;
106
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
217
107
diff --git a/block/rbd.c b/block/rbd.c
218
#ifndef _WIN32
108
index XXXXXXX..XXXXXXX 100644
109
--- a/block/rbd.c
110
+++ b/block/rbd.c
111
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
112
goto failed_shutdown;
113
}
114
115
+ /* rbd_open is always r/w */
116
r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
117
if (r < 0) {
118
error_setg_errno(errp, -r, "error reading header from %s", s->name);
119
goto failed_open;
120
}
121
122
- bdrv_set_read_only(bs, (s->snap != NULL));
123
+ /* If we are using an rbd snapshot, we must be r/o, otherwise
124
+ * leave as-is */
125
+ if (s->snap != NULL) {
126
+ r = bdrv_set_read_only(bs, true, &local_err);
127
+ if (r < 0) {
128
+ error_propagate(errp, local_err);
129
+ goto failed_open;
130
+ }
131
+ }
132
133
qemu_opts_del(opts);
134
return 0;
135
diff --git a/block/vvfat.c b/block/vvfat.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/block/vvfat.c
138
+++ b/block/vvfat.c
139
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
140
141
s->current_cluster=0xffffffff;
142
143
- /* read only is the default for safety */
144
- bdrv_set_read_only(bs, true);
145
s->qcow = NULL;
146
s->qcow_filename = NULL;
147
s->fat2 = NULL;
148
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
149
s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
150
151
if (qemu_opt_get_bool(opts, "rw", false)) {
152
- ret = enable_write_target(bs, errp);
153
+ if (!bdrv_is_read_only(bs)) {
154
+ ret = enable_write_target(bs, errp);
155
+ if (ret < 0) {
156
+ goto fail;
157
+ }
158
+ } else {
159
+ ret = -EPERM;
160
+ error_setg(errp,
161
+ "Unable to set VVFAT to 'rw' when drive is read-only");
162
+ goto fail;
163
+ }
164
+ } else {
165
+ /* read only is the default for safety */
166
+ ret = bdrv_set_read_only(bs, true, &local_err);
167
if (ret < 0) {
168
+ error_propagate(errp, local_err);
169
goto fail;
170
}
171
- bdrv_set_read_only(bs, false);
172
}
173
174
bs->total_sectors = cyls * heads * secs;
175
diff --git a/include/block/block.h b/include/block/block.h
176
index XXXXXXX..XXXXXXX 100644
177
--- a/include/block/block.h
178
+++ b/include/block/block.h
179
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
180
int64_t sector_num, int nb_sectors, int *pnum);
181
182
bool bdrv_is_read_only(BlockDriverState *bs);
183
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only);
184
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
185
bool bdrv_is_sg(BlockDriverState *bs);
186
bool bdrv_is_inserted(BlockDriverState *bs);
187
int bdrv_media_changed(BlockDriverState *bs);
188
--
219
--
189
2.9.3
220
2.35.1
190
191
diff view generated by jsdifflib
Deleted patch
1
The BDRV_O_ALLOW_RDWR flag allows / prohibits the changing of
2
the BDS 'read_only' state, but there are a few places where it
3
is ignored. In the bdrv_set_read_only() helper, make sure to
4
honor the flag.
5
1
6
Signed-off-by: Jeff Cody <jcody@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-id: be2e5fb2d285cbece2b6d06bed54a6f56520d251.1491597120.git.jcody@redhat.com
10
---
11
block.c | 7 +++++++
12
1 file changed, 7 insertions(+)
13
14
diff --git a/block.c b/block.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block.c
17
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
19
return -EINVAL;
20
}
21
22
+ /* Do not clear read_only if it is prohibited */
23
+ if (!read_only && !(bs->open_flags & BDRV_O_ALLOW_RDWR)) {
24
+ error_setg(errp, "Node '%s' is read only",
25
+ bdrv_get_device_or_node_name(bs));
26
+ return -EPERM;
27
+ }
28
+
29
bs->read_only = read_only;
30
return 0;
31
}
32
--
33
2.9.3
34
35
diff view generated by jsdifflib
Deleted patch
1
Move bdrv_is_read_only() up with its friends.
2
1
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4
Reviewed-by: John Snow <jsnow@redhat.com>
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
6
Message-id: 73b2399459760c32506f9407efb9dddb3a2789de.1491597120.git.jcody@redhat.com
7
---
8
block.c | 10 +++++-----
9
1 file changed, 5 insertions(+), 5 deletions(-)
10
11
diff --git a/block.c b/block.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
14
+++ b/block.c
15
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
16
}
17
}
18
19
+bool bdrv_is_read_only(BlockDriverState *bs)
20
+{
21
+ return bs->read_only;
22
+}
23
+
24
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
25
{
26
/* Do not set read_only if copy_on_read is enabled */
27
@@ -XXX,XX +XXX,XX @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
28
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
29
}
30
31
-bool bdrv_is_read_only(BlockDriverState *bs)
32
-{
33
- return bs->read_only;
34
-}
35
-
36
bool bdrv_is_sg(BlockDriverState *bs)
37
{
38
return bs->sg;
39
--
40
2.9.3
41
42
diff view generated by jsdifflib
1
Introduce check function for setting read_only flags. Will return < 0 on
1
From: Nicolas Saenz Julienne <nsaenzju@redhat.com>
2
error, with appropriate Error value set. Does not alter any flags.
3
2
4
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
The thread pool regulates itself: when idle, it kills threads until
4
empty, when in demand, it creates new threads until full. This behaviour
5
doesn't play well with latency sensitive workloads where the price of
6
creating a new thread is too high. For example, when paired with qemu's
7
'-mlock', or using safety features like SafeStack, creating a new thread
8
has been measured take multiple milliseconds.
9
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.
16
17
Signed-off-by: Nicolas Saenz Julienne <nsaenzju@redhat.com>
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
18
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: John Snow <jsnow@redhat.com>
19
Acked-by: Markus Armbruster <armbru@redhat.com>
7
Message-id: e2bba34ac3bc76a0c42adc390413f358ae0566e8.1491597120.git.jcody@redhat.com
20
Message-id: 20220425075723.20019-4-nsaenzju@redhat.com
21
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
22
---
9
block.c | 14 +++++++++++++-
23
qapi/qom.json | 10 +++++-
10
include/block/block.h | 1 +
24
include/block/aio.h | 10 ++++++
11
2 files changed, 14 insertions(+), 1 deletion(-)
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(-)
12
34
13
diff --git a/block.c b/block.c
35
diff --git a/qapi/qom.json b/qapi/qom.json
14
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
37
--- a/qapi/qom.json
16
+++ b/block.c
38
+++ b/qapi/qom.json
17
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
39
@@ -XXX,XX +XXX,XX @@
18
return bs->read_only;
40
# 0 means that the engine will use its default.
19
}
41
# (default: 0)
20
42
#
21
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
43
+# @thread-pool-min: minimum number of threads reserved in the thread pool
22
+int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
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)
23
{
252
{
24
/* Do not set read_only if copy_on_read is enabled */
253
+ ERRP_GUARD();
25
if (bs->copy_on_read && read_only) {
254
+
26
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
255
if (!qemu_aio_context) {
27
return -EPERM;
256
error_setg(errp, "qemu aio context not ready");
257
return;
28
}
258
}
29
259
30
+ return 0;
260
aio_context_set_aio_params(qemu_aio_context, base->aio_max_batch, errp);
261
+ if (*errp) {
262
+ return;
263
+ }
264
+
265
+ aio_context_set_thread_pool_params(qemu_aio_context, base->thread_pool_min,
266
+ base->thread_pool_max, errp);
267
}
268
269
MainLoop *mloop;
270
diff --git a/util/thread-pool.c b/util/thread-pool.c
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;
31
+}
305
+}
32
+
306
+
33
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
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)
34
+{
327
+{
35
+ int ret = 0;
328
+ qemu_mutex_lock(&pool->lock);
36
+
329
+
37
+ ret = bdrv_can_set_read_only(bs, read_only, errp);
330
+ pool->min_threads = ctx->thread_pool_min;
38
+ if (ret < 0) {
331
+ pool->max_threads = ctx->thread_pool_max;
39
+ return ret;
332
+
40
+ }
333
+ /*
41
+
334
+ * We either have to:
42
bs->read_only = read_only;
335
+ * - Increase the number available of threads until over the min_threads
43
return 0;
336
+ * threshold.
44
}
337
+ * - Decrease the number of available threads until under the max_threads
45
diff --git a/include/block/block.h b/include/block/block.h
338
+ * threshold.
46
index XXXXXXX..XXXXXXX 100644
339
+ * - Do nothing. The current number of threads fall in between the min and
47
--- a/include/block/block.h
340
+ * max thresholds. We'll let the pool manage itself.
48
+++ b/include/block/block.h
341
+ */
49
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
342
+ for (int i = pool->cur_threads; i < pool->min_threads; i++) {
50
int64_t sector_num, int nb_sectors, int *pnum);
343
+ spawn_thread(pool);
51
344
+ }
52
bool bdrv_is_read_only(BlockDriverState *bs);
345
+
53
+int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
346
+ for (int i = pool->cur_threads; i > pool->max_threads; i--) {
54
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
347
+ qemu_sem_post(&pool->sem);
55
bool bdrv_is_sg(BlockDriverState *bs);
348
+ }
56
bool bdrv_is_inserted(BlockDriverState *bs);
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)
57
--
370
--
58
2.9.3
371
2.35.1
59
60
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Jeff Cody <jcody@redhat.com>
2
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
3
Reviewed-by: John Snow <jsnow@redhat.com>
4
Message-id: 00aed7ffdd7be4b9ed9ce1007d50028a72b34ebe.1491597120.git.jcody@redhat.com
5
---
6
block.c | 14 ++++++++------
7
1 file changed, 8 insertions(+), 6 deletions(-)
8
1
9
diff --git a/block.c b/block.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/block.c
12
+++ b/block.c
13
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
14
BlockDriver *drv;
15
QemuOpts *opts;
16
const char *value;
17
+ bool read_only;
18
19
assert(reopen_state != NULL);
20
assert(reopen_state->bs->drv != NULL);
21
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
22
qdict_put(reopen_state->options, "driver", qstring_from_str(value));
23
}
24
25
- /* if we are to stay read-only, do not allow permission change
26
- * to r/w */
27
- if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) &&
28
- reopen_state->flags & BDRV_O_RDWR) {
29
- error_setg(errp, "Node '%s' is read only",
30
- bdrv_get_device_or_node_name(reopen_state->bs));
31
+ /* If we are to stay read-only, do not allow permission change
32
+ * to r/w. Attempting to set to r/w may fail if either BDRV_O_ALLOW_RDWR is
33
+ * not set, or if the BDS still has copy_on_read enabled */
34
+ read_only = !(reopen_state->flags & BDRV_O_RDWR);
35
+ ret = bdrv_can_set_read_only(reopen_state->bs, read_only, &local_err);
36
+ if (local_err) {
37
+ error_propagate(errp, local_err);
38
goto error;
39
}
40
41
--
42
2.9.3
43
44
diff view generated by jsdifflib
Deleted patch
1
Update 'clientname' to be 'user', which tracks better with both
2
the QAPI and rados variable naming.
3
1
4
Update 'name' to be 'image_name', as it indicates the rbd image.
5
Naming it 'image' would have been ideal, but we are using that for
6
the rados_image_t value returned by rbd_open().
7
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Jeff Cody <jcody@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
Message-id: b7ec1fb2e1cf36f9b6911631447a5b0422590b7d.1491597120.git.jcody@redhat.com
12
---
13
block/rbd.c | 33 +++++++++++++++++----------------
14
1 file changed, 17 insertions(+), 16 deletions(-)
15
16
diff --git a/block/rbd.c b/block/rbd.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/rbd.c
19
+++ b/block/rbd.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRBDState {
21
rados_t cluster;
22
rados_ioctx_t io_ctx;
23
rbd_image_t image;
24
- char *name;
25
+ char *image_name;
26
char *snap;
27
} BDRVRBDState;
28
29
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
30
int64_t bytes = 0;
31
int64_t objsize;
32
int obj_order = 0;
33
- const char *pool, *name, *conf, *clientname, *keypairs;
34
+ const char *pool, *image_name, *conf, *user, *keypairs;
35
const char *secretid;
36
rados_t cluster;
37
rados_ioctx_t io_ctx;
38
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
39
*/
40
pool = qdict_get_try_str(options, "pool");
41
conf = qdict_get_try_str(options, "conf");
42
- clientname = qdict_get_try_str(options, "user");
43
- name = qdict_get_try_str(options, "image");
44
+ user = qdict_get_try_str(options, "user");
45
+ image_name = qdict_get_try_str(options, "image");
46
keypairs = qdict_get_try_str(options, "=keyvalue-pairs");
47
48
- ret = rados_create(&cluster, clientname);
49
+ ret = rados_create(&cluster, user);
50
if (ret < 0) {
51
error_setg_errno(errp, -ret, "error initializing");
52
goto exit;
53
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
54
goto shutdown;
55
}
56
57
- ret = rbd_create(io_ctx, name, bytes, &obj_order);
58
+ ret = rbd_create(io_ctx, image_name, bytes, &obj_order);
59
if (ret < 0) {
60
error_setg_errno(errp, -ret, "error rbd create");
61
}
62
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
63
Error **errp)
64
{
65
BDRVRBDState *s = bs->opaque;
66
- const char *pool, *snap, *conf, *clientname, *name, *keypairs;
67
+ const char *pool, *snap, *conf, *user, *image_name, *keypairs;
68
const char *secretid;
69
QemuOpts *opts;
70
Error *local_err = NULL;
71
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
72
pool = qemu_opt_get(opts, "pool");
73
conf = qemu_opt_get(opts, "conf");
74
snap = qemu_opt_get(opts, "snapshot");
75
- clientname = qemu_opt_get(opts, "user");
76
- name = qemu_opt_get(opts, "image");
77
+ user = qemu_opt_get(opts, "user");
78
+ image_name = qemu_opt_get(opts, "image");
79
keypairs = qemu_opt_get(opts, "=keyvalue-pairs");
80
81
- if (!pool || !name) {
82
+ if (!pool || !image_name) {
83
error_setg(errp, "Parameters 'pool' and 'image' are required");
84
r = -EINVAL;
85
goto failed_opts;
86
}
87
88
- r = rados_create(&s->cluster, clientname);
89
+ r = rados_create(&s->cluster, user);
90
if (r < 0) {
91
error_setg_errno(errp, -r, "error initializing");
92
goto failed_opts;
93
}
94
95
s->snap = g_strdup(snap);
96
- s->name = g_strdup(name);
97
+ s->image_name = g_strdup(image_name);
98
99
/* try default location when conf=NULL, but ignore failure */
100
r = rados_conf_read_file(s->cluster, conf);
101
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
102
}
103
104
/* rbd_open is always r/w */
105
- r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
106
+ r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap);
107
if (r < 0) {
108
- error_setg_errno(errp, -r, "error reading header from %s", s->name);
109
+ error_setg_errno(errp, -r, "error reading header from %s",
110
+ s->image_name);
111
goto failed_open;
112
}
113
114
@@ -XXX,XX +XXX,XX @@ failed_open:
115
failed_shutdown:
116
rados_shutdown(s->cluster);
117
g_free(s->snap);
118
- g_free(s->name);
119
+ g_free(s->image_name);
120
failed_opts:
121
qemu_opts_del(opts);
122
g_free(mon_host);
123
@@ -XXX,XX +XXX,XX @@ static void qemu_rbd_close(BlockDriverState *bs)
124
rbd_close(s->image);
125
rados_ioctx_destroy(s->io_ctx);
126
g_free(s->snap);
127
- g_free(s->name);
128
+ g_free(s->image_name);
129
rados_shutdown(s->cluster);
130
}
131
132
--
133
2.9.3
134
135
diff view generated by jsdifflib
Deleted patch
1
This adds support for reopen in rbd, for changing between r/w and r/o.
2
1
3
Note, that this is only a flag change, but we will block a change from
4
r/o to r/w if we are using an RBD internal snapshot.
5
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-id: d4e87539167ec6527d44c97b164eabcccf96e4f3.1491597120.git.jcody@redhat.com
10
---
11
block/rbd.c | 21 +++++++++++++++++++++
12
1 file changed, 21 insertions(+)
13
14
diff --git a/block/rbd.c b/block/rbd.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/rbd.c
17
+++ b/block/rbd.c
18
@@ -XXX,XX +XXX,XX @@ failed_opts:
19
return r;
20
}
21
22
+
23
+/* Since RBD is currently always opened R/W via the API,
24
+ * we just need to check if we are using a snapshot or not, in
25
+ * order to determine if we will allow it to be R/W */
26
+static int qemu_rbd_reopen_prepare(BDRVReopenState *state,
27
+ BlockReopenQueue *queue, Error **errp)
28
+{
29
+ BDRVRBDState *s = state->bs->opaque;
30
+ int ret = 0;
31
+
32
+ if (s->snap && state->flags & BDRV_O_RDWR) {
33
+ error_setg(errp,
34
+ "Cannot change node '%s' to r/w when using RBD snapshot",
35
+ bdrv_get_device_or_node_name(state->bs));
36
+ ret = -EINVAL;
37
+ }
38
+
39
+ return ret;
40
+}
41
+
42
static void qemu_rbd_close(BlockDriverState *bs)
43
{
44
BDRVRBDState *s = bs->opaque;
45
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
46
.bdrv_parse_filename = qemu_rbd_parse_filename,
47
.bdrv_file_open = qemu_rbd_open,
48
.bdrv_close = qemu_rbd_close,
49
+ .bdrv_reopen_prepare = qemu_rbd_reopen_prepare,
50
.bdrv_create = qemu_rbd_create,
51
.bdrv_has_zero_init = bdrv_has_zero_init_1,
52
.bdrv_get_info = qemu_rbd_getinfo,
53
--
54
2.9.3
55
56
diff view generated by jsdifflib
Deleted patch
1
For the tests that use the common.qemu functions for running a QEMU
2
process, _cleanup_qemu must be called in the exit function.
3
1
4
If it is not, if the qemu process aborts, then not all of the droppings
5
are cleaned up (e.g. pidfile, fifos).
6
7
This updates those tests that did not have a cleanup in qemu-iotests.
8
9
(I swapped spaces for tabs in test 102 as well)
10
11
Reported-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Signed-off-by: Jeff Cody <jcody@redhat.com>
14
Message-id: d59c2f6ad6c1da8b9b3c7f357c94a7122ccfc55a.1492544096.git.jcody@redhat.com
15
---
16
tests/qemu-iotests/028 | 1 +
17
tests/qemu-iotests/094 | 11 ++++++++---
18
tests/qemu-iotests/102 | 5 +++--
19
tests/qemu-iotests/109 | 1 +
20
tests/qemu-iotests/117 | 1 +
21
tests/qemu-iotests/130 | 1 +
22
tests/qemu-iotests/140 | 1 +
23
tests/qemu-iotests/141 | 1 +
24
tests/qemu-iotests/143 | 1 +
25
tests/qemu-iotests/156 | 1 +
26
10 files changed, 19 insertions(+), 5 deletions(-)
27
28
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
29
index XXXXXXX..XXXXXXX 100755
30
--- a/tests/qemu-iotests/028
31
+++ b/tests/qemu-iotests/028
32
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
33
34
_cleanup()
35
{
36
+ _cleanup_qemu
37
rm -f "${TEST_IMG}.copy"
38
_cleanup_test_img
39
}
40
diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094
41
index XXXXXXX..XXXXXXX 100755
42
--- a/tests/qemu-iotests/094
43
+++ b/tests/qemu-iotests/094
44
@@ -XXX,XX +XXX,XX @@ echo "QA output created by $seq"
45
here="$PWD"
46
status=1    # failure is the default!
47
48
-trap "exit \$status" 0 1 2 3 15
49
+_cleanup()
50
+{
51
+ _cleanup_qemu
52
+ _cleanup_test_img
53
+ rm -f "$TEST_DIR/source.$IMGFMT"
54
+}
55
+
56
+trap "_cleanup; exit \$status" 0 1 2 3 15
57
58
# get standard environment, filters and checks
59
. ./common.rc
60
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE \
61
62
wait=1 _cleanup_qemu
63
64
-_cleanup_test_img
65
-rm -f "$TEST_DIR/source.$IMGFMT"
66
67
# success, all done
68
echo '*** done'
69
diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102
70
index XXXXXXX..XXXXXXX 100755
71
--- a/tests/qemu-iotests/102
72
+++ b/tests/qemu-iotests/102
73
@@ -XXX,XX +XXX,XX @@ seq=$(basename $0)
74
echo "QA output created by $seq"
75
76
here=$PWD
77
-status=1    # failure is the default!
78
+status=1 # failure is the default!
79
80
_cleanup()
81
{
82
-    _cleanup_test_img
83
+ _cleanup_qemu
84
+ _cleanup_test_img
85
}
86
trap "_cleanup; exit \$status" 0 1 2 3 15
87
88
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
89
index XXXXXXX..XXXXXXX 100755
90
--- a/tests/qemu-iotests/109
91
+++ b/tests/qemu-iotests/109
92
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
93
94
_cleanup()
95
{
96
+ _cleanup_qemu
97
rm -f $TEST_IMG.src
98
    _cleanup_test_img
99
}
100
diff --git a/tests/qemu-iotests/117 b/tests/qemu-iotests/117
101
index XXXXXXX..XXXXXXX 100755
102
--- a/tests/qemu-iotests/117
103
+++ b/tests/qemu-iotests/117
104
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
105
106
_cleanup()
107
{
108
+ _cleanup_qemu
109
    _cleanup_test_img
110
}
111
trap "_cleanup; exit \$status" 0 1 2 3 15
112
diff --git a/tests/qemu-iotests/130 b/tests/qemu-iotests/130
113
index XXXXXXX..XXXXXXX 100755
114
--- a/tests/qemu-iotests/130
115
+++ b/tests/qemu-iotests/130
116
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
117
118
_cleanup()
119
{
120
+ _cleanup_qemu
121
_cleanup_test_img
122
}
123
trap "_cleanup; exit \$status" 0 1 2 3 15
124
diff --git a/tests/qemu-iotests/140 b/tests/qemu-iotests/140
125
index XXXXXXX..XXXXXXX 100755
126
--- a/tests/qemu-iotests/140
127
+++ b/tests/qemu-iotests/140
128
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
129
130
_cleanup()
131
{
132
+ _cleanup_qemu
133
_cleanup_test_img
134
rm -f "$TEST_DIR/nbd"
135
}
136
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
137
index XXXXXXX..XXXXXXX 100755
138
--- a/tests/qemu-iotests/141
139
+++ b/tests/qemu-iotests/141
140
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
141
142
_cleanup()
143
{
144
+ _cleanup_qemu
145
_cleanup_test_img
146
rm -f "$TEST_DIR/{b,m,o}.$IMGFMT"
147
}
148
diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143
149
index XXXXXXX..XXXXXXX 100755
150
--- a/tests/qemu-iotests/143
151
+++ b/tests/qemu-iotests/143
152
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
153
154
_cleanup()
155
{
156
+ _cleanup_qemu
157
rm -f "$TEST_DIR/nbd"
158
}
159
trap "_cleanup; exit \$status" 0 1 2 3 15
160
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
161
index XXXXXXX..XXXXXXX 100755
162
--- a/tests/qemu-iotests/156
163
+++ b/tests/qemu-iotests/156
164
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
165
166
_cleanup()
167
{
168
+ _cleanup_qemu
169
rm -f "$TEST_IMG{,.target}{,.backing,.overlay}"
170
}
171
trap "_cleanup; exit \$status" 0 1 2 3 15
172
--
173
2.9.3
174
175
diff view generated by jsdifflib