1
The following changes since commit 0ab4537f08e09b13788db67efd760592fb7db769:
1
The following changes since commit 4c55b1d0bad8a703f0499fe62e3761a0cd288da3:
2
2
3
Merge remote-tracking branch 'remotes/stefanberger/tags/pull-tpm-2018-03-07-1' into staging (2018-03-08 12:56:39 +0000)
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-error-2017-04-24' into staging (2017-04-24 14:49:48 +0100)
4
4
5
are available in the Git repository at:
5
are available in the git repository at:
6
6
7
git://github.com/stefanha/qemu.git tags/block-pull-request
7
git://github.com/codyprime/qemu-kvm-jtc.git tags/block-pull-request
8
8
9
for you to fetch changes up to 4486e89c219c0d1b9bd8dfa0b1dd5b0d51ff2268:
9
for you to fetch changes up to ecfa185400ade2abc9915efa924cbad1e15a21a4:
10
10
11
vl: introduce vm_shutdown() (2018-03-08 17:38:51 +0000)
11
qemu-iotests: _cleanup_qemu must be called on exit (2017-04-24 15:09:33 -0400)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
Pull v2, with 32-bit errors fixed. I don't have OS X to test compile on,
15
but I think it is safe to assume the cause of the compile error was the same.
15
----------------------------------------------------------------
16
----------------------------------------------------------------
16
17
17
Deepa Srinivasan (1):
18
Ashish Mittal (2):
18
block: Fix qemu crash when using scsi-block
19
block/vxhs.c: Add support for a new block device type called "vxhs"
20
block/vxhs.c: Add qemu-iotests for new block device type "vxhs"
19
21
20
Fam Zheng (1):
22
Jeff Cody (10):
21
README: Fix typo 'git-publish'
23
qemu-iotests: exclude vxhs from image creation via protocol
24
block: add bdrv_set_read_only() helper function
25
block: do not set BDS read_only if copy_on_read enabled
26
block: honor BDRV_O_ALLOW_RDWR when clearing bs->read_only
27
block: code movement
28
block: introduce bdrv_can_set_read_only()
29
block: use bdrv_can_set_read_only() during reopen
30
block/rbd - update variable names to more apt names
31
block/rbd: Add support for reopen()
32
qemu-iotests: _cleanup_qemu must be called on exit
22
33
23
Sergio Lopez (1):
34
block.c | 56 +++-
24
virtio-blk: dataplane: Don't batch notifications if EVENT_IDX is
35
block/Makefile.objs | 2 +
25
present
36
block/bochs.c | 5 +-
26
37
block/cloop.c | 5 +-
27
Stefan Hajnoczi (4):
38
block/dmg.c | 6 +-
28
block: add aio_wait_bh_oneshot()
39
block/rbd.c | 65 +++--
29
virtio-blk: fix race between .ioeventfd_stop() and vq handler
40
block/trace-events | 17 ++
30
virtio-scsi: fix race between .ioeventfd_stop() and vq handler
41
block/vvfat.c | 19 +-
31
vl: introduce vm_shutdown()
42
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++
32
43
configure | 39 +++
33
include/block/aio-wait.h | 13 +++++++++++
44
include/block/block.h | 2 +
34
include/sysemu/iothread.h | 1 -
45
qapi/block-core.json | 23 +-
35
include/sysemu/sysemu.h | 1 +
46
tests/qemu-iotests/017 | 1 +
36
block/block-backend.c | 51 ++++++++++++++++++++---------------------
47
tests/qemu-iotests/020 | 1 +
37
cpus.c | 16 ++++++++++---
48
tests/qemu-iotests/028 | 1 +
38
hw/block/dataplane/virtio-blk.c | 39 +++++++++++++++++++++++--------
49
tests/qemu-iotests/029 | 1 +
39
hw/scsi/virtio-scsi-dataplane.c | 9 ++++----
50
tests/qemu-iotests/073 | 1 +
40
iothread.c | 31 -------------------------
51
tests/qemu-iotests/094 | 11 +-
41
util/aio-wait.c | 31 +++++++++++++++++++++++++
52
tests/qemu-iotests/102 | 5 +-
42
vl.c | 13 +++--------
53
tests/qemu-iotests/109 | 1 +
43
README | 2 +-
54
tests/qemu-iotests/114 | 1 +
44
11 files changed, 122 insertions(+), 85 deletions(-)
55
tests/qemu-iotests/117 | 1 +
56
tests/qemu-iotests/130 | 2 +
57
tests/qemu-iotests/134 | 1 +
58
tests/qemu-iotests/140 | 1 +
59
tests/qemu-iotests/141 | 1 +
60
tests/qemu-iotests/143 | 1 +
61
tests/qemu-iotests/156 | 2 +
62
tests/qemu-iotests/158 | 1 +
63
tests/qemu-iotests/common | 6 +
64
tests/qemu-iotests/common.config | 13 +
65
tests/qemu-iotests/common.filter | 1 +
66
tests/qemu-iotests/common.rc | 19 ++
67
33 files changed, 844 insertions(+), 42 deletions(-)
68
create mode 100644 block/vxhs.c
45
69
46
--
70
--
47
2.14.3
71
2.9.3
48
72
49
73
diff view generated by jsdifflib
New patch
1
From: Ashish Mittal <ashmit602@gmail.com>
1
2
3
Source code for the qnio library that this code loads can be downloaded from:
4
https://github.com/VeritasHyperScale/libqnio.git
5
6
Sample command line using JSON syntax:
7
./x86_64-softmmu/qemu-system-x86_64 -name instance-00000008 -S -vnc 0.0.0.0:0
8
-k en-us -vga cirrus -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
9
-msg timestamp=on
10
'json:{"driver":"vxhs","vdisk-id":"c3e9095a-a5ee-4dce-afeb-2a59fb387410",
11
"server":{"host":"172.172.17.4","port":"9999"}}'
12
13
Sample command line using URI syntax:
14
qemu-img convert -f raw -O raw -n
15
/var/lib/nova/instances/_base/0c5eacd5ebea5ed914b6a3e7b18f1ce734c386ad
16
vxhs://192.168.0.1:9999/c6718f6b-0401-441d-a8c3-1f0064d75ee0
17
18
Sample command line using TLS credentials (run in secure mode):
19
./qemu-io --object
20
tls-creds-x509,id=tls0,dir=/etc/pki/qemu/vxhs,endpoint=client -c 'read
21
-v 66000 2.5k' 'json:{"server.host": "127.0.0.1", "server.port": "9999",
22
"vdisk-id": "/test.raw", "driver": "vxhs", "tls-creds":"tls0"}'
23
24
[Jeff: Modified trace-events with the correct string formatting]
25
26
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
27
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
28
Reviewed-by: Jeff Cody <jcody@redhat.com>
29
Signed-off-by: Jeff Cody <jcody@redhat.com>
30
Message-id: 1491277689-24949-2-git-send-email-Ashish.Mittal@veritas.com
31
---
32
block/Makefile.objs | 2 +
33
block/trace-events | 17 ++
34
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++++++++++++++
35
configure | 39 ++++
36
qapi/block-core.json | 23 ++-
37
5 files changed, 654 insertions(+), 2 deletions(-)
38
create mode 100644 block/vxhs.c
39
40
diff --git a/block/Makefile.objs b/block/Makefile.objs
41
index XXXXXXX..XXXXXXX 100644
42
--- a/block/Makefile.objs
43
+++ b/block/Makefile.objs
44
@@ -XXX,XX +XXX,XX @@ block-obj-$(CONFIG_LIBNFS) += nfs.o
45
block-obj-$(CONFIG_CURL) += curl.o
46
block-obj-$(CONFIG_RBD) += rbd.o
47
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
48
+block-obj-$(CONFIG_VXHS) += vxhs.o
49
block-obj-$(CONFIG_LIBSSH2) += ssh.o
50
block-obj-y += accounting.o dirty-bitmap.o
51
block-obj-y += write-threshold.o
52
@@ -XXX,XX +XXX,XX @@ rbd.o-cflags := $(RBD_CFLAGS)
53
rbd.o-libs := $(RBD_LIBS)
54
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
55
gluster.o-libs := $(GLUSTERFS_LIBS)
56
+vxhs.o-libs := $(VXHS_LIBS)
57
ssh.o-cflags := $(LIBSSH2_CFLAGS)
58
ssh.o-libs := $(LIBSSH2_LIBS)
59
block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o
60
diff --git a/block/trace-events b/block/trace-events
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/trace-events
63
+++ b/block/trace-events
64
@@ -XXX,XX +XXX,XX @@ qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s
65
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
66
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
67
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"
68
+
69
+# block/vxhs.c
70
+vxhs_iio_callback(int error) "ctx is NULL: error %d"
71
+vxhs_iio_callback_chnfail(int err, int error) "QNIO channel failed, no i/o %d, %d"
72
+vxhs_iio_callback_unknwn(int opcode, int err) "unexpected opcode %d, errno %d"
73
+vxhs_aio_rw_invalid(int req) "Invalid I/O request iodir %d"
74
+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 = %"PRIu64" offset = %"PRIu64" ACB = %p. Error = %d, errno = %d"
75
+vxhs_get_vdisk_stat_err(char *guid, int ret, int err) "vDisk (%s) stat ioctl failed, ret = %d, errno = %d"
76
+vxhs_get_vdisk_stat(char *vdisk_guid, uint64_t vdisk_size) "vDisk %s stat ioctl returned size %"PRIu64
77
+vxhs_complete_aio(void *acb, uint64_t ret) "aio failed acb %p ret %"PRIu64
78
+vxhs_parse_uri_filename(const char *filename) "URI passed via bdrv_parse_filename %s"
79
+vxhs_open_vdiskid(const char *vdisk_id) "Opening vdisk-id %s"
80
+vxhs_open_hostinfo(char *of_vsa_addr, int port) "Adding host %s:%d to BDRVVXHSState"
81
+vxhs_open_iio_open(const char *host) "Failed to connect to storage agent on host %s"
82
+vxhs_parse_uri_hostinfo(char *host, int port) "Host: IP %s, Port %d"
83
+vxhs_close(char *vdisk_guid) "Closing vdisk %s"
84
+vxhs_get_creds(const char *cacert, const char *client_key, const char *client_cert) "cacert %s, client_key %s, client_cert %s"
85
diff --git a/block/vxhs.c b/block/vxhs.c
86
new file mode 100644
87
index XXXXXXX..XXXXXXX
88
--- /dev/null
89
+++ b/block/vxhs.c
90
@@ -XXX,XX +XXX,XX @@
91
+/*
92
+ * QEMU Block driver for Veritas HyperScale (VxHS)
93
+ *
94
+ * Copyright (c) 2017 Veritas Technologies LLC.
95
+ *
96
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
97
+ * See the COPYING file in the top-level directory.
98
+ *
99
+ */
100
+
101
+#include "qemu/osdep.h"
102
+#include <qnio/qnio_api.h>
103
+#include <sys/param.h>
104
+#include "block/block_int.h"
105
+#include "qapi/qmp/qerror.h"
106
+#include "qapi/qmp/qdict.h"
107
+#include "qapi/qmp/qstring.h"
108
+#include "trace.h"
109
+#include "qemu/uri.h"
110
+#include "qapi/error.h"
111
+#include "qemu/uuid.h"
112
+#include "crypto/tlscredsx509.h"
113
+
114
+#define VXHS_OPT_FILENAME "filename"
115
+#define VXHS_OPT_VDISK_ID "vdisk-id"
116
+#define VXHS_OPT_SERVER "server"
117
+#define VXHS_OPT_HOST "host"
118
+#define VXHS_OPT_PORT "port"
119
+
120
+/* Only accessed under QEMU global mutex */
121
+static uint32_t vxhs_ref;
122
+
123
+typedef enum {
124
+ VDISK_AIO_READ,
125
+ VDISK_AIO_WRITE,
126
+} VDISKAIOCmd;
127
+
128
+/*
129
+ * HyperScale AIO callbacks structure
130
+ */
131
+typedef struct VXHSAIOCB {
132
+ BlockAIOCB common;
133
+ int err;
134
+} VXHSAIOCB;
135
+
136
+typedef struct VXHSvDiskHostsInfo {
137
+ void *dev_handle; /* Device handle */
138
+ char *host; /* Host name or IP */
139
+ int port; /* Host's port number */
140
+} VXHSvDiskHostsInfo;
141
+
142
+/*
143
+ * Structure per vDisk maintained for state
144
+ */
145
+typedef struct BDRVVXHSState {
146
+ VXHSvDiskHostsInfo vdisk_hostinfo; /* Per host info */
147
+ char *vdisk_guid;
148
+ char *tlscredsid; /* tlscredsid */
149
+} BDRVVXHSState;
150
+
151
+static void vxhs_complete_aio_bh(void *opaque)
152
+{
153
+ VXHSAIOCB *acb = opaque;
154
+ BlockCompletionFunc *cb = acb->common.cb;
155
+ void *cb_opaque = acb->common.opaque;
156
+ int ret = 0;
157
+
158
+ if (acb->err != 0) {
159
+ trace_vxhs_complete_aio(acb, acb->err);
160
+ ret = (-EIO);
161
+ }
162
+
163
+ qemu_aio_unref(acb);
164
+ cb(cb_opaque, ret);
165
+}
166
+
167
+/*
168
+ * Called from a libqnio thread
169
+ */
170
+static void vxhs_iio_callback(void *ctx, uint32_t opcode, uint32_t error)
171
+{
172
+ VXHSAIOCB *acb = NULL;
173
+
174
+ switch (opcode) {
175
+ case IRP_READ_REQUEST:
176
+ case IRP_WRITE_REQUEST:
177
+
178
+ /*
179
+ * ctx is VXHSAIOCB*
180
+ * ctx is NULL if error is QNIOERROR_CHANNEL_HUP
181
+ */
182
+ if (ctx) {
183
+ acb = ctx;
184
+ } else {
185
+ trace_vxhs_iio_callback(error);
186
+ goto out;
187
+ }
188
+
189
+ if (error) {
190
+ if (!acb->err) {
191
+ acb->err = error;
192
+ }
193
+ trace_vxhs_iio_callback(error);
194
+ }
195
+
196
+ aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
197
+ vxhs_complete_aio_bh, acb);
198
+ break;
199
+
200
+ default:
201
+ if (error == QNIOERROR_HUP) {
202
+ /*
203
+ * Channel failed, spontaneous notification,
204
+ * not in response to I/O
205
+ */
206
+ trace_vxhs_iio_callback_chnfail(error, errno);
207
+ } else {
208
+ trace_vxhs_iio_callback_unknwn(opcode, error);
209
+ }
210
+ break;
211
+ }
212
+out:
213
+ return;
214
+}
215
+
216
+static QemuOptsList runtime_opts = {
217
+ .name = "vxhs",
218
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
219
+ .desc = {
220
+ {
221
+ .name = VXHS_OPT_FILENAME,
222
+ .type = QEMU_OPT_STRING,
223
+ .help = "URI to the Veritas HyperScale image",
224
+ },
225
+ {
226
+ .name = VXHS_OPT_VDISK_ID,
227
+ .type = QEMU_OPT_STRING,
228
+ .help = "UUID of the VxHS vdisk",
229
+ },
230
+ {
231
+ .name = "tls-creds",
232
+ .type = QEMU_OPT_STRING,
233
+ .help = "ID of the TLS/SSL credentials to use",
234
+ },
235
+ { /* end of list */ }
236
+ },
237
+};
238
+
239
+static QemuOptsList runtime_tcp_opts = {
240
+ .name = "vxhs_tcp",
241
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_tcp_opts.head),
242
+ .desc = {
243
+ {
244
+ .name = VXHS_OPT_HOST,
245
+ .type = QEMU_OPT_STRING,
246
+ .help = "host address (ipv4 addresses)",
247
+ },
248
+ {
249
+ .name = VXHS_OPT_PORT,
250
+ .type = QEMU_OPT_NUMBER,
251
+ .help = "port number on which VxHSD is listening (default 9999)",
252
+ .def_value_str = "9999"
253
+ },
254
+ { /* end of list */ }
255
+ },
256
+};
257
+
258
+/*
259
+ * Parse incoming URI and populate *options with the host
260
+ * and device information
261
+ */
262
+static int vxhs_parse_uri(const char *filename, QDict *options)
263
+{
264
+ URI *uri = NULL;
265
+ char *port;
266
+ int ret = 0;
267
+
268
+ trace_vxhs_parse_uri_filename(filename);
269
+ uri = uri_parse(filename);
270
+ if (!uri || !uri->server || !uri->path) {
271
+ uri_free(uri);
272
+ return -EINVAL;
273
+ }
274
+
275
+ qdict_put(options, VXHS_OPT_SERVER".host", qstring_from_str(uri->server));
276
+
277
+ if (uri->port) {
278
+ port = g_strdup_printf("%d", uri->port);
279
+ qdict_put(options, VXHS_OPT_SERVER".port", qstring_from_str(port));
280
+ g_free(port);
281
+ }
282
+
283
+ qdict_put(options, "vdisk-id", qstring_from_str(uri->path));
284
+
285
+ trace_vxhs_parse_uri_hostinfo(uri->server, uri->port);
286
+ uri_free(uri);
287
+
288
+ return ret;
289
+}
290
+
291
+static void vxhs_parse_filename(const char *filename, QDict *options,
292
+ Error **errp)
293
+{
294
+ if (qdict_haskey(options, "vdisk-id") || qdict_haskey(options, "server")) {
295
+ error_setg(errp, "vdisk-id/server and a file name may not be specified "
296
+ "at the same time");
297
+ return;
298
+ }
299
+
300
+ if (strstr(filename, "://")) {
301
+ int ret = vxhs_parse_uri(filename, options);
302
+ if (ret < 0) {
303
+ error_setg(errp, "Invalid URI. URI should be of the form "
304
+ " vxhs://<host_ip>:<port>/<vdisk-id>");
305
+ }
306
+ }
307
+}
308
+
309
+static int vxhs_init_and_ref(void)
310
+{
311
+ if (vxhs_ref++ == 0) {
312
+ if (iio_init(QNIO_VERSION, vxhs_iio_callback)) {
313
+ return -ENODEV;
314
+ }
315
+ }
316
+ return 0;
317
+}
318
+
319
+static void vxhs_unref(void)
320
+{
321
+ if (--vxhs_ref == 0) {
322
+ iio_fini();
323
+ }
324
+}
325
+
326
+static void vxhs_get_tls_creds(const char *id, char **cacert,
327
+ char **key, char **cert, Error **errp)
328
+{
329
+ Object *obj;
330
+ QCryptoTLSCreds *creds;
331
+ QCryptoTLSCredsX509 *creds_x509;
332
+
333
+ obj = object_resolve_path_component(
334
+ object_get_objects_root(), id);
335
+
336
+ if (!obj) {
337
+ error_setg(errp, "No TLS credentials with id '%s'",
338
+ id);
339
+ return;
340
+ }
341
+
342
+ creds_x509 = (QCryptoTLSCredsX509 *)
343
+ object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS_X509);
344
+
345
+ if (!creds_x509) {
346
+ error_setg(errp, "Object with id '%s' is not TLS credentials",
347
+ id);
348
+ return;
349
+ }
350
+
351
+ creds = &creds_x509->parent_obj;
352
+
353
+ if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
354
+ error_setg(errp,
355
+ "Expecting TLS credentials with a client endpoint");
356
+ return;
357
+ }
358
+
359
+ /*
360
+ * Get the cacert, client_cert and client_key file names.
361
+ */
362
+ if (!creds->dir) {
363
+ error_setg(errp, "TLS object missing 'dir' property value");
364
+ return;
365
+ }
366
+
367
+ *cacert = g_strdup_printf("%s/%s", creds->dir,
368
+ QCRYPTO_TLS_CREDS_X509_CA_CERT);
369
+ *cert = g_strdup_printf("%s/%s", creds->dir,
370
+ QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
371
+ *key = g_strdup_printf("%s/%s", creds->dir,
372
+ QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
373
+}
374
+
375
+static int vxhs_open(BlockDriverState *bs, QDict *options,
376
+ int bdrv_flags, Error **errp)
377
+{
378
+ BDRVVXHSState *s = bs->opaque;
379
+ void *dev_handlep;
380
+ QDict *backing_options = NULL;
381
+ QemuOpts *opts = NULL;
382
+ QemuOpts *tcp_opts = NULL;
383
+ char *of_vsa_addr = NULL;
384
+ Error *local_err = NULL;
385
+ const char *vdisk_id_opt;
386
+ const char *server_host_opt;
387
+ int ret = 0;
388
+ char *cacert = NULL;
389
+ char *client_key = NULL;
390
+ char *client_cert = NULL;
391
+
392
+ ret = vxhs_init_and_ref();
393
+ if (ret < 0) {
394
+ ret = -EINVAL;
395
+ goto out;
396
+ }
397
+
398
+ /* Create opts info from runtime_opts and runtime_tcp_opts list */
399
+ opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
400
+ tcp_opts = qemu_opts_create(&runtime_tcp_opts, NULL, 0, &error_abort);
401
+
402
+ qemu_opts_absorb_qdict(opts, options, &local_err);
403
+ if (local_err) {
404
+ ret = -EINVAL;
405
+ goto out;
406
+ }
407
+
408
+ /* vdisk-id is the disk UUID */
409
+ vdisk_id_opt = qemu_opt_get(opts, VXHS_OPT_VDISK_ID);
410
+ if (!vdisk_id_opt) {
411
+ error_setg(&local_err, QERR_MISSING_PARAMETER, VXHS_OPT_VDISK_ID);
412
+ ret = -EINVAL;
413
+ goto out;
414
+ }
415
+
416
+ /* vdisk-id may contain a leading '/' */
417
+ if (strlen(vdisk_id_opt) > UUID_FMT_LEN + 1) {
418
+ error_setg(&local_err, "vdisk-id cannot be more than %d characters",
419
+ UUID_FMT_LEN);
420
+ ret = -EINVAL;
421
+ goto out;
422
+ }
423
+
424
+ s->vdisk_guid = g_strdup(vdisk_id_opt);
425
+ trace_vxhs_open_vdiskid(vdisk_id_opt);
426
+
427
+ /* get the 'server.' arguments */
428
+ qdict_extract_subqdict(options, &backing_options, VXHS_OPT_SERVER".");
429
+
430
+ qemu_opts_absorb_qdict(tcp_opts, backing_options, &local_err);
431
+ if (local_err != NULL) {
432
+ ret = -EINVAL;
433
+ goto out;
434
+ }
435
+
436
+ server_host_opt = qemu_opt_get(tcp_opts, VXHS_OPT_HOST);
437
+ if (!server_host_opt) {
438
+ error_setg(&local_err, QERR_MISSING_PARAMETER,
439
+ VXHS_OPT_SERVER"."VXHS_OPT_HOST);
440
+ ret = -EINVAL;
441
+ goto out;
442
+ }
443
+
444
+ if (strlen(server_host_opt) > MAXHOSTNAMELEN) {
445
+ error_setg(&local_err, "server.host cannot be more than %d characters",
446
+ MAXHOSTNAMELEN);
447
+ ret = -EINVAL;
448
+ goto out;
449
+ }
450
+
451
+ /* check if we got tls-creds via the --object argument */
452
+ s->tlscredsid = g_strdup(qemu_opt_get(opts, "tls-creds"));
453
+ if (s->tlscredsid) {
454
+ vxhs_get_tls_creds(s->tlscredsid, &cacert, &client_key,
455
+ &client_cert, &local_err);
456
+ if (local_err != NULL) {
457
+ ret = -EINVAL;
458
+ goto out;
459
+ }
460
+ trace_vxhs_get_creds(cacert, client_key, client_cert);
461
+ }
462
+
463
+ s->vdisk_hostinfo.host = g_strdup(server_host_opt);
464
+ s->vdisk_hostinfo.port = g_ascii_strtoll(qemu_opt_get(tcp_opts,
465
+ VXHS_OPT_PORT),
466
+ NULL, 0);
467
+
468
+ trace_vxhs_open_hostinfo(s->vdisk_hostinfo.host,
469
+ s->vdisk_hostinfo.port);
470
+
471
+ of_vsa_addr = g_strdup_printf("of://%s:%d",
472
+ s->vdisk_hostinfo.host,
473
+ s->vdisk_hostinfo.port);
474
+
475
+ /*
476
+ * Open qnio channel to storage agent if not opened before
477
+ */
478
+ dev_handlep = iio_open(of_vsa_addr, s->vdisk_guid, 0,
479
+ cacert, client_key, client_cert);
480
+ if (dev_handlep == NULL) {
481
+ trace_vxhs_open_iio_open(of_vsa_addr);
482
+ ret = -ENODEV;
483
+ goto out;
484
+ }
485
+ s->vdisk_hostinfo.dev_handle = dev_handlep;
486
+
487
+out:
488
+ g_free(of_vsa_addr);
489
+ QDECREF(backing_options);
490
+ qemu_opts_del(tcp_opts);
491
+ qemu_opts_del(opts);
492
+ g_free(cacert);
493
+ g_free(client_key);
494
+ g_free(client_cert);
495
+
496
+ if (ret < 0) {
497
+ vxhs_unref();
498
+ error_propagate(errp, local_err);
499
+ g_free(s->vdisk_hostinfo.host);
500
+ g_free(s->vdisk_guid);
501
+ g_free(s->tlscredsid);
502
+ s->vdisk_guid = NULL;
503
+ }
504
+
505
+ return ret;
506
+}
507
+
508
+static const AIOCBInfo vxhs_aiocb_info = {
509
+ .aiocb_size = sizeof(VXHSAIOCB)
510
+};
511
+
512
+/*
513
+ * This allocates QEMU-VXHS callback for each IO
514
+ * and is passed to QNIO. When QNIO completes the work,
515
+ * it will be passed back through the callback.
516
+ */
517
+static BlockAIOCB *vxhs_aio_rw(BlockDriverState *bs, int64_t sector_num,
518
+ QEMUIOVector *qiov, int nb_sectors,
519
+ BlockCompletionFunc *cb, void *opaque,
520
+ VDISKAIOCmd iodir)
521
+{
522
+ VXHSAIOCB *acb = NULL;
523
+ BDRVVXHSState *s = bs->opaque;
524
+ size_t size;
525
+ uint64_t offset;
526
+ int iio_flags = 0;
527
+ int ret = 0;
528
+ void *dev_handle = s->vdisk_hostinfo.dev_handle;
529
+
530
+ offset = sector_num * BDRV_SECTOR_SIZE;
531
+ size = nb_sectors * BDRV_SECTOR_SIZE;
532
+ acb = qemu_aio_get(&vxhs_aiocb_info, bs, cb, opaque);
533
+
534
+ /*
535
+ * Initialize VXHSAIOCB.
536
+ */
537
+ acb->err = 0;
538
+
539
+ iio_flags = IIO_FLAG_ASYNC;
540
+
541
+ switch (iodir) {
542
+ case VDISK_AIO_WRITE:
543
+ ret = iio_writev(dev_handle, acb, qiov->iov, qiov->niov,
544
+ offset, (uint64_t)size, iio_flags);
545
+ break;
546
+ case VDISK_AIO_READ:
547
+ ret = iio_readv(dev_handle, acb, qiov->iov, qiov->niov,
548
+ offset, (uint64_t)size, iio_flags);
549
+ break;
550
+ default:
551
+ trace_vxhs_aio_rw_invalid(iodir);
552
+ goto errout;
553
+ }
554
+
555
+ if (ret != 0) {
556
+ trace_vxhs_aio_rw_ioerr(s->vdisk_guid, iodir, size, offset,
557
+ acb, ret, errno);
558
+ goto errout;
559
+ }
560
+ return &acb->common;
561
+
562
+errout:
563
+ qemu_aio_unref(acb);
564
+ return NULL;
565
+}
566
+
567
+static BlockAIOCB *vxhs_aio_readv(BlockDriverState *bs,
568
+ int64_t sector_num, QEMUIOVector *qiov,
569
+ int nb_sectors,
570
+ BlockCompletionFunc *cb, void *opaque)
571
+{
572
+ return vxhs_aio_rw(bs, sector_num, qiov, nb_sectors, cb,
573
+ opaque, VDISK_AIO_READ);
574
+}
575
+
576
+static BlockAIOCB *vxhs_aio_writev(BlockDriverState *bs,
577
+ int64_t sector_num, QEMUIOVector *qiov,
578
+ int nb_sectors,
579
+ BlockCompletionFunc *cb, void *opaque)
580
+{
581
+ return vxhs_aio_rw(bs, sector_num, qiov, nb_sectors,
582
+ cb, opaque, VDISK_AIO_WRITE);
583
+}
584
+
585
+static void vxhs_close(BlockDriverState *bs)
586
+{
587
+ BDRVVXHSState *s = bs->opaque;
588
+
589
+ trace_vxhs_close(s->vdisk_guid);
590
+
591
+ g_free(s->vdisk_guid);
592
+ s->vdisk_guid = NULL;
593
+
594
+ /*
595
+ * Close vDisk device
596
+ */
597
+ if (s->vdisk_hostinfo.dev_handle) {
598
+ iio_close(s->vdisk_hostinfo.dev_handle);
599
+ s->vdisk_hostinfo.dev_handle = NULL;
600
+ }
601
+
602
+ vxhs_unref();
603
+
604
+ /*
605
+ * Free the dynamically allocated host string etc
606
+ */
607
+ g_free(s->vdisk_hostinfo.host);
608
+ g_free(s->tlscredsid);
609
+ s->tlscredsid = NULL;
610
+ s->vdisk_hostinfo.host = NULL;
611
+ s->vdisk_hostinfo.port = 0;
612
+}
613
+
614
+static int64_t vxhs_get_vdisk_stat(BDRVVXHSState *s)
615
+{
616
+ int64_t vdisk_size = -1;
617
+ int ret = 0;
618
+ void *dev_handle = s->vdisk_hostinfo.dev_handle;
619
+
620
+ ret = iio_ioctl(dev_handle, IOR_VDISK_STAT, &vdisk_size, 0);
621
+ if (ret < 0) {
622
+ trace_vxhs_get_vdisk_stat_err(s->vdisk_guid, ret, errno);
623
+ return -EIO;
624
+ }
625
+
626
+ trace_vxhs_get_vdisk_stat(s->vdisk_guid, vdisk_size);
627
+ return vdisk_size;
628
+}
629
+
630
+/*
631
+ * Returns the size of vDisk in bytes. This is required
632
+ * by QEMU block upper block layer so that it is visible
633
+ * to guest.
634
+ */
635
+static int64_t vxhs_getlength(BlockDriverState *bs)
636
+{
637
+ BDRVVXHSState *s = bs->opaque;
638
+ int64_t vdisk_size;
639
+
640
+ vdisk_size = vxhs_get_vdisk_stat(s);
641
+ if (vdisk_size < 0) {
642
+ return -EIO;
643
+ }
644
+
645
+ return vdisk_size;
646
+}
647
+
648
+static BlockDriver bdrv_vxhs = {
649
+ .format_name = "vxhs",
650
+ .protocol_name = "vxhs",
651
+ .instance_size = sizeof(BDRVVXHSState),
652
+ .bdrv_file_open = vxhs_open,
653
+ .bdrv_parse_filename = vxhs_parse_filename,
654
+ .bdrv_close = vxhs_close,
655
+ .bdrv_getlength = vxhs_getlength,
656
+ .bdrv_aio_readv = vxhs_aio_readv,
657
+ .bdrv_aio_writev = vxhs_aio_writev,
658
+};
659
+
660
+static void bdrv_vxhs_init(void)
661
+{
662
+ bdrv_register(&bdrv_vxhs);
663
+}
664
+
665
+block_init(bdrv_vxhs_init);
666
diff --git a/configure b/configure
667
index XXXXXXX..XXXXXXX 100755
668
--- a/configure
669
+++ b/configure
670
@@ -XXX,XX +XXX,XX @@ numa=""
671
tcmalloc="no"
672
jemalloc="no"
673
replication="yes"
674
+vxhs=""
675
676
supported_cpu="no"
677
supported_os="no"
678
@@ -XXX,XX +XXX,XX @@ for opt do
679
;;
680
--enable-replication) replication="yes"
681
;;
682
+ --disable-vxhs) vxhs="no"
683
+ ;;
684
+ --enable-vxhs) vxhs="yes"
685
+ ;;
686
*)
687
echo "ERROR: unknown option $opt"
688
echo "Try '$0 --help' for more information"
689
@@ -XXX,XX +XXX,XX @@ disabled with --disable-FEATURE, default is enabled if available:
690
xfsctl xfsctl support
691
qom-cast-debug cast debugging support
692
tools build qemu-io, qemu-nbd and qemu-image tools
693
+ vxhs Veritas HyperScale vDisk backend support
694
695
NOTE: The object files are built at the place where configure is launched
696
EOF
697
@@ -XXX,XX +XXX,XX @@ if compile_prog "" "" ; then
698
fi
699
700
##########################################
701
+# Veritas HyperScale block driver VxHS
702
+# Check if libvxhs is installed
703
+
704
+if test "$vxhs" != "no" ; then
705
+ cat > $TMPC <<EOF
706
+#include <stdint.h>
707
+#include <qnio/qnio_api.h>
708
+
709
+void *vxhs_callback;
710
+
711
+int main(void) {
712
+ iio_init(QNIO_VERSION, vxhs_callback);
713
+ return 0;
714
+}
715
+EOF
716
+ vxhs_libs="-lvxhs -lssl"
717
+ if compile_prog "" "$vxhs_libs" ; then
718
+ vxhs=yes
719
+ else
720
+ if test "$vxhs" = "yes" ; then
721
+ feature_not_found "vxhs block device" "Install libvxhs See github"
722
+ fi
723
+ vxhs=no
724
+ fi
725
+fi
726
+
727
+##########################################
728
# End of CC checks
729
# After here, no more $cc or $ld runs
730
731
@@ -XXX,XX +XXX,XX @@ echo "tcmalloc support $tcmalloc"
732
echo "jemalloc support $jemalloc"
733
echo "avx2 optimization $avx2_opt"
734
echo "replication support $replication"
735
+echo "VxHS block device $vxhs"
736
737
if test "$sdl_too_old" = "yes"; then
738
echo "-> Your SDL version is too old - please upgrade to have SDL support"
739
@@ -XXX,XX +XXX,XX @@ if test "$pthread_setname_np" = "yes" ; then
740
echo "CONFIG_PTHREAD_SETNAME_NP=y" >> $config_host_mak
741
fi
742
743
+if test "$vxhs" = "yes" ; then
744
+ echo "CONFIG_VXHS=y" >> $config_host_mak
745
+ echo "VXHS_LIBS=$vxhs_libs" >> $config_host_mak
746
+fi
747
+
748
if test "$tcg_interpreter" = "yes"; then
749
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
750
elif test "$ARCH" = "sparc64" ; then
751
diff --git a/qapi/block-core.json b/qapi/block-core.json
752
index XXXXXXX..XXXXXXX 100644
753
--- a/qapi/block-core.json
754
+++ b/qapi/block-core.json
755
@@ -XXX,XX +XXX,XX @@
756
#
757
# Drivers that are supported in block device operations.
758
#
759
+# @vxhs: Since 2.10
760
+#
761
# Since: 2.9
762
##
763
{ 'enum': 'BlockdevDriver',
764
@@ -XXX,XX +XXX,XX @@
765
'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
766
'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
767
'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
768
- 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
769
+ 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
770
771
##
772
# @BlockdevOptionsFile:
773
@@ -XXX,XX +XXX,XX @@
774
'data': { '*offset': 'int', '*size': 'int' } }
775
776
##
777
+# @BlockdevOptionsVxHS:
778
+#
779
+# Driver specific block device options for VxHS
780
+#
781
+# @vdisk-id: UUID of VxHS volume
782
+# @server: vxhs server IP, port
783
+# @tls-creds: TLS credentials ID
784
+#
785
+# Since: 2.10
786
+##
787
+{ 'struct': 'BlockdevOptionsVxHS',
788
+ 'data': { 'vdisk-id': 'str',
789
+ 'server': 'InetSocketAddressBase',
790
+ '*tls-creds': 'str' } }
791
+
792
+##
793
# @BlockdevOptions:
794
#
795
# Options for creating a block device. Many options are available for all
796
@@ -XXX,XX +XXX,XX @@
797
'vhdx': 'BlockdevOptionsGenericFormat',
798
'vmdk': 'BlockdevOptionsGenericCOWFormat',
799
'vpc': 'BlockdevOptionsGenericFormat',
800
- 'vvfat': 'BlockdevOptionsVVFAT'
801
+ 'vvfat': 'BlockdevOptionsVVFAT',
802
+ 'vxhs': 'BlockdevOptionsVxHS'
803
} }
804
805
##
806
--
807
2.9.3
808
809
diff view generated by jsdifflib
1
From: Deepa Srinivasan <deepa.srinivasan@oracle.com>
1
From: Ashish Mittal <ashmit602@gmail.com>
2
2
3
Starting qemu with the following arguments causes qemu to segfault:
3
These changes use a vxhs test server that is a part of the following
4
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
4
repository:
5
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
5
https://github.com/VeritasHyperScale/libqnio.git
6
6
7
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
7
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
8
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
details about the bug follow.
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(+)
10
18
11
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
19
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
12
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
13
14
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
15
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
16
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
17
18
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
19
....
20
BlkRwCo *rwco = &acb->rwco;
21
22
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
23
rwco->qiov->iov[0].iov_base); <--- qiov is
24
invalid here
25
...
26
27
In the case when blk_aio_ioctl() is called from a non-coroutine context,
28
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
29
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
30
execution is complete, control returns to blk_aio_ioctl_entry() after the call
31
to blk_co_ioctl(). There is no invalid reference after this point, but the
32
function is still holding on to invalid pointers.
33
34
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
35
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
36
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
37
38
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
39
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
40
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
41
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
42
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
43
---
44
block/block-backend.c | 51 +++++++++++++++++++++++++--------------------------
45
1 file changed, 25 insertions(+), 26 deletions(-)
46
47
diff --git a/block/block-backend.c b/block/block-backend.c
48
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
49
--- a/block/block-backend.c
21
--- a/tests/qemu-iotests/common
50
+++ b/block/block-backend.c
22
+++ b/tests/qemu-iotests/common
51
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
23
@@ -XXX,XX +XXX,XX @@ check options
52
typedef struct BlkRwCo {
24
-ssh test ssh
53
BlockBackend *blk;
25
-nfs test nfs
54
int64_t offset;
26
-luks test luks
55
- QEMUIOVector *qiov;
27
+ -vxhs test vxhs
56
+ void *iobuf;
28
-xdiff graphical mode diff
57
int ret;
29
-nocache use O_DIRECT on backing file
58
BdrvRequestFlags flags;
30
-misalign misalign memory allocations
59
} BlkRwCo;
31
@@ -XXX,XX +XXX,XX @@ testlist options
60
@@ -XXX,XX +XXX,XX @@ typedef struct BlkRwCo {
32
xpand=false
61
static void blk_read_entry(void *opaque)
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()
62
{
56
{
63
BlkRwCo *rwco = opaque;
57
(
64
+ QEMUIOVector *qiov = rwco->iobuf;
58
@@ -XXX,XX +XXX,XX @@ _qemu_nbd_wrapper()
65
59
)
66
- rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, rwco->qiov->size,
67
- rwco->qiov, rwco->flags);
68
+ rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, qiov->size,
69
+ qiov, rwco->flags);
70
}
60
}
71
61
72
static void blk_write_entry(void *opaque)
62
+_qemu_vxhs_wrapper()
73
{
63
+{
74
BlkRwCo *rwco = opaque;
64
+ (
75
+ QEMUIOVector *qiov = rwco->iobuf;
65
+ echo $BASHPID > "${TEST_DIR}/qemu-vxhs.pid"
76
66
+ exec "$QEMU_VXHS_PROG" $QEMU_VXHS_OPTIONS "$@"
77
- rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, rwco->qiov->size,
67
+ )
78
- rwco->qiov, rwco->flags);
68
+}
79
+ rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, qiov->size,
69
+
80
+ qiov, rwco->flags);
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
81
}
114
}
82
115
83
static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
116
_rm_test_img()
84
@@ -XXX,XX +XXX,XX @@ static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
117
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img()
85
rwco = (BlkRwCo) {
118
fi
86
.blk = blk,
119
rm -f "$TEST_IMG_FILE"
87
.offset = offset,
120
;;
88
- .qiov = &qiov,
121
+ vxhs)
89
+ .iobuf = &qiov,
122
+ if [ -f "${TEST_DIR}/qemu-vxhs.pid" ]; then
90
.flags = flags,
123
+ local QEMU_VXHS_PID
91
.ret = NOT_DONE,
124
+ read QEMU_VXHS_PID < "${TEST_DIR}/qemu-vxhs.pid"
92
};
125
+ kill ${QEMU_VXHS_PID} >/dev/null 2>&1
93
@@ -XXX,XX +XXX,XX @@ static void blk_aio_complete_bh(void *opaque)
126
+ rm -f "${TEST_DIR}/qemu-vxhs.pid"
94
}
127
+ fi
95
128
+ rm -f "$TEST_IMG_FILE"
96
static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
129
+ ;;
97
- QEMUIOVector *qiov, CoroutineEntry co_entry,
98
+ void *iobuf, CoroutineEntry co_entry,
99
BdrvRequestFlags flags,
100
BlockCompletionFunc *cb, void *opaque)
101
{
102
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
103
acb->rwco = (BlkRwCo) {
104
.blk = blk,
105
.offset = offset,
106
- .qiov = qiov,
107
+ .iobuf = iobuf,
108
.flags = flags,
109
.ret = NOT_DONE,
110
};
111
@@ -XXX,XX +XXX,XX @@ static void blk_aio_read_entry(void *opaque)
112
{
113
BlkAioEmAIOCB *acb = opaque;
114
BlkRwCo *rwco = &acb->rwco;
115
+ QEMUIOVector *qiov = rwco->iobuf;
116
117
- assert(rwco->qiov->size == acb->bytes);
118
+ assert(qiov->size == acb->bytes);
119
rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, acb->bytes,
120
- rwco->qiov, rwco->flags);
121
+ qiov, rwco->flags);
122
blk_aio_complete(acb);
123
}
124
125
@@ -XXX,XX +XXX,XX @@ static void blk_aio_write_entry(void *opaque)
126
{
127
BlkAioEmAIOCB *acb = opaque;
128
BlkRwCo *rwco = &acb->rwco;
129
+ QEMUIOVector *qiov = rwco->iobuf;
130
131
- assert(!rwco->qiov || rwco->qiov->size == acb->bytes);
132
+ assert(!qiov || qiov->size == acb->bytes);
133
rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, acb->bytes,
134
- rwco->qiov, rwco->flags);
135
+ qiov, rwco->flags);
136
blk_aio_complete(acb);
137
}
138
139
@@ -XXX,XX +XXX,XX @@ int blk_co_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
140
static void blk_ioctl_entry(void *opaque)
141
{
142
BlkRwCo *rwco = opaque;
143
+ QEMUIOVector *qiov = rwco->iobuf;
144
+
130
+
145
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
131
file)
146
- rwco->qiov->iov[0].iov_base);
132
_rm_test_img "$TEST_DIR/t.$IMGFMT"
147
+ qiov->iov[0].iov_base);
133
_rm_test_img "$TEST_DIR/t.$IMGFMT.orig"
148
}
149
150
int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
151
@@ -XXX,XX +XXX,XX @@ static void blk_aio_ioctl_entry(void *opaque)
152
BlkAioEmAIOCB *acb = opaque;
153
BlkRwCo *rwco = &acb->rwco;
154
155
- rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
156
- rwco->qiov->iov[0].iov_base);
157
+ rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset, rwco->iobuf);
158
+
159
blk_aio_complete(acb);
160
}
161
162
BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
163
BlockCompletionFunc *cb, void *opaque)
164
{
165
- QEMUIOVector qiov;
166
- struct iovec iov;
167
-
168
- iov = (struct iovec) {
169
- .iov_base = buf,
170
- .iov_len = 0,
171
- };
172
- qemu_iovec_init_external(&qiov, &iov, 1);
173
-
174
- return blk_aio_prwv(blk, req, 0, &qiov, blk_aio_ioctl_entry, 0, cb, opaque);
175
+ return blk_aio_prwv(blk, req, 0, buf, blk_aio_ioctl_entry, 0, cb, opaque);
176
}
177
178
int blk_co_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
179
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, PreallocMode prealloc,
180
static void blk_pdiscard_entry(void *opaque)
181
{
182
BlkRwCo *rwco = opaque;
183
- rwco->ret = blk_co_pdiscard(rwco->blk, rwco->offset, rwco->qiov->size);
184
+ QEMUIOVector *qiov = rwco->iobuf;
185
+
186
+ rwco->ret = blk_co_pdiscard(rwco->blk, rwco->offset, qiov->size);
187
}
188
189
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
190
--
134
--
191
2.14.3
135
2.9.3
192
136
193
137
diff view generated by jsdifflib
New 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.
1
4
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
1
Sometimes it's necessary for the main loop thread to run a BH in an
1
We have a helper wrapper for checking for the BDS read_only flag,
2
IOThread and wait for its completion. This primitive is useful during
2
add a helper wrapper to set the read_only flag as well.
3
startup/shutdown to synchronize and avoid race conditions.
4
3
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: Fam Zheng <famz@redhat.com>
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
7
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
6
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-id: 20180307144205.20619-2-stefanha@redhat.com
7
Message-id: 9b18972d05f5fa2ac16c014f0af98d680553048d.1491597120.git.jcody@redhat.com
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
8
---
11
include/block/aio-wait.h | 13 +++++++++++++
9
block.c | 5 +++++
12
util/aio-wait.c | 31 +++++++++++++++++++++++++++++++
10
block/bochs.c | 2 +-
13
2 files changed, 44 insertions(+)
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(-)
14
17
15
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
18
diff --git a/block.c b/block.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/include/block/aio-wait.h
20
--- a/block.c
18
+++ b/include/block/aio-wait.h
21
+++ b/block.c
19
@@ -XXX,XX +XXX,XX @@ typedef struct {
22
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
20
*/
21
void aio_wait_kick(AioWait *wait);
22
23
+/**
24
+ * aio_wait_bh_oneshot:
25
+ * @ctx: the aio context
26
+ * @cb: the BH callback function
27
+ * @opaque: user data for the BH callback function
28
+ *
29
+ * Run a BH in @ctx and wait for it to complete.
30
+ *
31
+ * Must be called from the main loop thread with @ctx acquired exactly once.
32
+ * Note that main loop event processing may occur.
33
+ */
34
+void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
35
+
36
#endif /* QEMU_AIO_WAIT */
37
diff --git a/util/aio-wait.c b/util/aio-wait.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/util/aio-wait.c
40
+++ b/util/aio-wait.c
41
@@ -XXX,XX +XXX,XX @@ void aio_wait_kick(AioWait *wait)
42
aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL);
43
}
23
}
44
}
24
}
45
+
25
46
+typedef struct {
26
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
47
+ AioWait wait;
48
+ bool done;
49
+ QEMUBHFunc *cb;
50
+ void *opaque;
51
+} AioWaitBHData;
52
+
53
+/* Context: BH in IOThread */
54
+static void aio_wait_bh(void *opaque)
55
+{
27
+{
56
+ AioWaitBHData *data = opaque;
28
+ bs->read_only = read_only;
57
+
58
+ data->cb(data->opaque);
59
+
60
+ data->done = true;
61
+ aio_wait_kick(&data->wait);
62
+}
29
+}
63
+
30
+
64
+void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
31
void bdrv_get_full_backing_filename_from_filename(const char *backed,
65
+{
32
const char *backing,
66
+ AioWaitBHData data = {
33
char *dest, size_t sz,
67
+ .cb = cb,
34
diff --git a/block/bochs.c b/block/bochs.c
68
+ .opaque = opaque,
35
index XXXXXXX..XXXXXXX 100644
69
+ };
36
--- a/block/bochs.c
70
+
37
+++ b/block/bochs.c
71
+ assert(qemu_get_current_aio_context() == qemu_get_aio_context());
38
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
72
+
39
return -EINVAL;
73
+ aio_bh_schedule_oneshot(ctx, aio_wait_bh, &data);
40
}
74
+ AIO_WAIT_WHILE(&data.wait, ctx, !data.done);
41
75
+}
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);
76
--
120
--
77
2.14.3
121
2.9.3
78
122
79
123
diff view generated by jsdifflib
New patch
1
A few block drivers will set the BDS read_only flag from their
2
.bdrv_open() function. This means the bs->read_only flag could
3
be set after we enable copy_on_read, as the BDRV_O_COPY_ON_READ
4
flag check occurs prior to the call to bdrv->bdrv_open().
1
5
6
This adds an error return to bdrv_set_read_only(), and an error will be
7
return if we try to set the BDS to read_only while copy_on_read is
8
enabled.
9
10
This patch also changes the behavior of vvfat. Before, vvfat could
11
override the drive 'readonly' flag with its own, internal 'rw' flag.
12
13
For instance, this -drive parameter would result in a writable image:
14
15
"-drive format=vvfat,dir=/tmp/vvfat,rw,if=virtio,readonly=on"
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>
22
Reviewed-by: John Snow <jsnow@redhat.com>
23
Message-id: 0c5b4c1cc2c651471b131f21376dfd5ea24d2196.1491597120.git.jcody@redhat.com
24
---
25
block.c | 10 +++++++++-
26
block/bochs.c | 5 ++++-
27
block/cloop.c | 5 ++++-
28
block/dmg.c | 6 +++++-
29
block/rbd.c | 11 ++++++++++-
30
block/vvfat.c | 19 +++++++++++++++----
31
include/block/block.h | 2 +-
32
7 files changed, 48 insertions(+), 10 deletions(-)
33
34
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
37
+++ b/block.c
38
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
39
}
40
}
41
42
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
43
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
44
{
45
+ /* Do not set read_only if copy_on_read is enabled */
46
+ if (bs->copy_on_read && read_only) {
47
+ error_setg(errp, "Can't set node '%s' to r/o with copy-on-read enabled",
48
+ bdrv_get_device_or_node_name(bs));
49
+ return -EINVAL;
50
+ }
51
+
52
bs->read_only = read_only;
53
+ return 0;
54
}
55
56
void bdrv_get_full_backing_filename_from_filename(const char *backed,
57
diff --git a/block/bochs.c b/block/bochs.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/block/bochs.c
60
+++ b/block/bochs.c
61
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
62
return -EINVAL;
63
}
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
+ }
70
71
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
72
if (ret < 0) {
73
diff --git a/block/cloop.c b/block/cloop.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/cloop.c
76
+++ b/block/cloop.c
77
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
78
return -EINVAL;
79
}
80
81
- bdrv_set_read_only(bs, true);
82
+ ret = bdrv_set_read_only(bs, true, errp);
83
+ if (ret < 0) {
84
+ return ret;
85
+ }
86
87
/* read header */
88
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
89
diff --git a/block/dmg.c b/block/dmg.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/block/dmg.c
92
+++ b/block/dmg.c
93
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
94
return -EINVAL;
95
}
96
97
+ ret = bdrv_set_read_only(bs, true, errp);
98
+ if (ret < 0) {
99
+ return ret;
100
+ }
101
+
102
block_module_load_one("dmg-bz2");
103
- bdrv_set_read_only(bs, true);
104
105
s->n_chunks = 0;
106
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
107
diff --git a/block/rbd.c b/block/rbd.c
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
--
189
2.9.3
190
191
diff view generated by jsdifflib
New 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.
1
5
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
1
Commit 00d09fdbbae5f7864ce754913efc84c12fdf9f1a ("vl: pause vcpus before
1
Move bdrv_is_read_only() up with its friends.
2
stopping iothreads") and commit dce8921b2baaf95974af8176406881872067adfa
3
("iothread: Stop threads before main() quits") tried to work around the
4
fact that emulation was still active during termination by stopping
5
iothreads. They suffer from race conditions:
6
1. virtio_scsi_handle_cmd_vq() racing with iothread_stop_all() hits the
7
virtio_scsi_ctx_check() assertion failure because the BDS AioContext
8
has been modified by iothread_stop_all().
9
2. Guest vq kick racing with main loop termination leaves a readable
10
ioeventfd that is handled by the next aio_poll() when external
11
clients are enabled again, resulting in unwanted emulation activity.
12
2
13
This patch obsoletes those commits by fully disabling emulation activity
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
when vcpus are stopped.
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(-)
15
10
16
Use the new vm_shutdown() function instead of pause_all_vcpus() so that
11
diff --git a/block.c b/block.c
17
vm change state handlers are invoked too. Virtio devices will now stop
18
their ioeventfds, preventing further emulation activity after vm_stop().
19
20
Note that vm_stop(RUN_STATE_SHUTDOWN) cannot be used because it emits a
21
QMP STOP event that may affect existing clients.
22
23
It is no longer necessary to call replay_disable_events() directly since
24
vm_shutdown() does so already.
25
26
Drop iothread_stop_all() since it is no longer used.
27
28
Cc: Fam Zheng <famz@redhat.com>
29
Cc: Kevin Wolf <kwolf@redhat.com>
30
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
31
Reviewed-by: Fam Zheng <famz@redhat.com>
32
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
33
Message-id: 20180307144205.20619-5-stefanha@redhat.com
34
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
35
---
36
include/sysemu/iothread.h | 1 -
37
include/sysemu/sysemu.h | 1 +
38
cpus.c | 16 +++++++++++++---
39
iothread.c | 31 -------------------------------
40
vl.c | 13 +++----------
41
5 files changed, 17 insertions(+), 45 deletions(-)
42
43
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
44
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
45
--- a/include/sysemu/iothread.h
13
--- a/block.c
46
+++ b/include/sysemu/iothread.h
14
+++ b/block.c
47
@@ -XXX,XX +XXX,XX @@ typedef struct {
15
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
48
char *iothread_get_id(IOThread *iothread);
49
IOThread *iothread_by_id(const char *id);
50
AioContext *iothread_get_aio_context(IOThread *iothread);
51
-void iothread_stop_all(void);
52
GMainContext *iothread_get_g_main_context(IOThread *iothread);
53
54
/*
55
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/include/sysemu/sysemu.h
58
+++ b/include/sysemu/sysemu.h
59
@@ -XXX,XX +XXX,XX @@ void vm_start(void);
60
int vm_prepare_start(void);
61
int vm_stop(RunState state);
62
int vm_stop_force_state(RunState state);
63
+int vm_shutdown(void);
64
65
typedef enum WakeupReason {
66
/* Always keep QEMU_WAKEUP_REASON_NONE = 0 */
67
diff --git a/cpus.c b/cpus.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/cpus.c
70
+++ b/cpus.c
71
@@ -XXX,XX +XXX,XX @@ void cpu_synchronize_all_pre_loadvm(void)
72
}
16
}
73
}
17
}
74
18
75
-static int do_vm_stop(RunState state)
19
+bool bdrv_is_read_only(BlockDriverState *bs)
76
+static int do_vm_stop(RunState state, bool send_stop)
77
{
78
int ret = 0;
79
80
@@ -XXX,XX +XXX,XX @@ static int do_vm_stop(RunState state)
81
pause_all_vcpus();
82
runstate_set(state);
83
vm_state_notify(0, state);
84
- qapi_event_send_stop(&error_abort);
85
+ if (send_stop) {
86
+ qapi_event_send_stop(&error_abort);
87
+ }
88
}
89
90
bdrv_drain_all();
91
@@ -XXX,XX +XXX,XX @@ static int do_vm_stop(RunState state)
92
return ret;
93
}
94
95
+/* Special vm_stop() variant for terminating the process. Historically clients
96
+ * did not expect a QMP STOP event and so we need to retain compatibility.
97
+ */
98
+int vm_shutdown(void)
99
+{
20
+{
100
+ return do_vm_stop(RUN_STATE_SHUTDOWN, false);
21
+ return bs->read_only;
101
+}
22
+}
102
+
23
+
103
static bool cpu_can_run(CPUState *cpu)
24
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
104
{
25
{
105
if (cpu->stop) {
26
/* Do not set read_only if copy_on_read is enabled */
106
@@ -XXX,XX +XXX,XX @@ int vm_stop(RunState state)
27
@@ -XXX,XX +XXX,XX @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
107
return 0;
28
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
108
}
109
110
- return do_vm_stop(state);
111
+ return do_vm_stop(state, true);
112
}
29
}
113
30
114
/**
31
-bool bdrv_is_read_only(BlockDriverState *bs)
115
diff --git a/iothread.c b/iothread.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/iothread.c
118
+++ b/iothread.c
119
@@ -XXX,XX +XXX,XX @@ void iothread_stop(IOThread *iothread)
120
qemu_thread_join(&iothread->thread);
121
}
122
123
-static int iothread_stop_iter(Object *object, void *opaque)
124
-{
32
-{
125
- IOThread *iothread;
33
- return bs->read_only;
126
-
127
- iothread = (IOThread *)object_dynamic_cast(object, TYPE_IOTHREAD);
128
- if (!iothread) {
129
- return 0;
130
- }
131
- iothread_stop(iothread);
132
- return 0;
133
-}
34
-}
134
-
35
-
135
static void iothread_instance_init(Object *obj)
36
bool bdrv_is_sg(BlockDriverState *bs)
136
{
37
{
137
IOThread *iothread = IOTHREAD(obj);
38
return bs->sg;
138
@@ -XXX,XX +XXX,XX @@ IOThreadInfoList *qmp_query_iothreads(Error **errp)
139
return head;
140
}
141
142
-void iothread_stop_all(void)
143
-{
144
- Object *container = object_get_objects_root();
145
- BlockDriverState *bs;
146
- BdrvNextIterator it;
147
-
148
- for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
149
- AioContext *ctx = bdrv_get_aio_context(bs);
150
- if (ctx == qemu_get_aio_context()) {
151
- continue;
152
- }
153
- aio_context_acquire(ctx);
154
- bdrv_set_aio_context(bs, qemu_get_aio_context());
155
- aio_context_release(ctx);
156
- }
157
-
158
- object_child_foreach(container, iothread_stop_iter, NULL);
159
-}
160
-
161
static gpointer iothread_g_main_context_init(gpointer opaque)
162
{
163
AioContext *ctx;
164
diff --git a/vl.c b/vl.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/vl.c
167
+++ b/vl.c
168
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
169
os_setup_post();
170
171
main_loop();
172
- replay_disable_events();
173
174
- /* The ordering of the following is delicate. Stop vcpus to prevent new
175
- * I/O requests being queued by the guest. Then stop IOThreads (this
176
- * includes a drain operation and completes all request processing). At
177
- * this point emulated devices are still associated with their IOThreads
178
- * (if any) but no longer have any work to do. Only then can we close
179
- * block devices safely because we know there is no more I/O coming.
180
- */
181
- pause_all_vcpus();
182
- iothread_stop_all();
183
+ /* No more vcpu or device emulation activity beyond this point */
184
+ vm_shutdown();
185
+
186
bdrv_close_all();
187
188
res_free();
189
--
39
--
190
2.14.3
40
2.9.3
191
41
192
42
diff view generated by jsdifflib
1
If the main loop thread invokes .ioeventfd_stop() just as the vq handler
1
Introduce check function for setting read_only flags. Will return < 0 on
2
function begins in the IOThread then the handler may lose the race for
2
error, with appropriate Error value set. Does not alter any flags.
3
the AioContext lock. By the time the vq handler is able to acquire the
4
AioContext lock the ioeventfd has already been removed and the handler
5
isn't supposed to run anymore!
6
3
7
Use the new aio_wait_bh_oneshot() function to perform ioeventfd removal
4
Signed-off-by: Jeff Cody <jcody@redhat.com>
8
from within the IOThread. This way no races with the vq handler are
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
possible.
6
Reviewed-by: John Snow <jsnow@redhat.com>
7
Message-id: e2bba34ac3bc76a0c42adc390413f358ae0566e8.1491597120.git.jcody@redhat.com
8
---
9
block.c | 14 +++++++++++++-
10
include/block/block.h | 1 +
11
2 files changed, 14 insertions(+), 1 deletion(-)
10
12
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
diff --git a/block.c b/block.c
12
Reviewed-by: Fam Zheng <famz@redhat.com>
13
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
14
Message-id: 20180307144205.20619-3-stefanha@redhat.com
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
17
hw/block/dataplane/virtio-blk.c | 24 +++++++++++++++++-------
18
1 file changed, 17 insertions(+), 7 deletions(-)
19
20
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
21
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/block/dataplane/virtio-blk.c
15
--- a/block.c
23
+++ b/hw/block/dataplane/virtio-blk.c
16
+++ b/block.c
24
@@ -XXX,XX +XXX,XX @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
17
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
25
return -ENOSYS;
18
return bs->read_only;
26
}
19
}
27
20
28
+/* Stop notifications for new requests from guest.
21
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
29
+ *
22
+int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
30
+ * Context: BH in IOThread
23
{
31
+ */
24
/* Do not set read_only if copy_on_read is enabled */
32
+static void virtio_blk_data_plane_stop_bh(void *opaque)
25
if (bs->copy_on_read && read_only) {
33
+{
26
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
34
+ VirtIOBlockDataPlane *s = opaque;
27
return -EPERM;
35
+ unsigned i;
28
}
36
+
29
37
+ for (i = 0; i < s->conf->num_queues; i++) {
30
+ return 0;
38
+ VirtQueue *vq = virtio_get_queue(s->vdev, i);
39
+
40
+ virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, NULL);
41
+ }
42
+}
31
+}
43
+
32
+
44
/* Context: QEMU global mutex held */
33
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
45
void virtio_blk_data_plane_stop(VirtIODevice *vdev)
34
+{
46
{
35
+ int ret = 0;
47
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev)
36
+
48
trace_virtio_blk_data_plane_stop(s);
37
+ ret = bdrv_can_set_read_only(bs, read_only, errp);
49
38
+ if (ret < 0) {
50
aio_context_acquire(s->ctx);
39
+ return ret;
51
-
40
+ }
52
- /* Stop notifications for new requests from guest */
41
+
53
- for (i = 0; i < nvqs; i++) {
42
bs->read_only = read_only;
54
- VirtQueue *vq = virtio_get_queue(s->vdev, i);
43
return 0;
55
-
44
}
56
- virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, NULL);
45
diff --git a/include/block/block.h b/include/block/block.h
57
- }
46
index XXXXXXX..XXXXXXX 100644
58
+ aio_wait_bh_oneshot(s->ctx, virtio_blk_data_plane_stop_bh, s);
47
--- a/include/block/block.h
59
48
+++ b/include/block/block.h
60
/* Drain and switch bs back to the QEMU main loop */
49
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
61
blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context());
50
int64_t sector_num, int nb_sectors, int *pnum);
51
52
bool bdrv_is_read_only(BlockDriverState *bs);
53
+int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
54
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
55
bool bdrv_is_sg(BlockDriverState *bs);
56
bool bdrv_is_inserted(BlockDriverState *bs);
62
--
57
--
63
2.14.3
58
2.9.3
64
59
65
60
diff view generated by jsdifflib
New 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(-)
1
8
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
1
If the main loop thread invokes .ioeventfd_stop() just as the vq handler
1
Update 'clientname' to be 'user', which tracks better with both
2
function begins in the IOThread then the handler may lose the race for
2
the QAPI and rados variable naming.
3
the AioContext lock. By the time the vq handler is able to acquire the
4
AioContext lock the ioeventfd has already been removed and the handler
5
isn't supposed to run anymore!
6
3
7
Use the new aio_wait_bh_oneshot() function to perform ioeventfd removal
4
Update 'name' to be 'image_name', as it indicates the rbd image.
8
from within the IOThread. This way no races with the vq handler are
5
Naming it 'image' would have been ideal, but we are using that for
9
possible.
6
the rados_image_t value returned by rbd_open().
10
7
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Reviewed-by: Fam Zheng <famz@redhat.com>
9
Signed-off-by: Jeff Cody <jcody@redhat.com>
13
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
14
Message-id: 20180307144205.20619-4-stefanha@redhat.com
11
Message-id: b7ec1fb2e1cf36f9b6911631447a5b0422590b7d.1491597120.git.jcody@redhat.com
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
12
---
17
hw/scsi/virtio-scsi-dataplane.c | 9 +++++----
13
block/rbd.c | 33 +++++++++++++++++----------------
18
1 file changed, 5 insertions(+), 4 deletions(-)
14
1 file changed, 17 insertions(+), 16 deletions(-)
19
15
20
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
16
diff --git a/block/rbd.c b/block/rbd.c
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/scsi/virtio-scsi-dataplane.c
18
--- a/block/rbd.c
23
+++ b/hw/scsi/virtio-scsi-dataplane.c
19
+++ b/block/rbd.c
24
@@ -XXX,XX +XXX,XX @@ static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue *vq, int n,
20
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRBDState {
25
return 0;
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);
26
}
130
}
27
131
28
-/* assumes s->ctx held */
29
-static void virtio_scsi_clear_aio(VirtIOSCSI *s)
30
+/* Context: BH in IOThread */
31
+static void virtio_scsi_dataplane_stop_bh(void *opaque)
32
{
33
+ VirtIOSCSI *s = opaque;
34
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
35
int i;
36
37
@@ -XXX,XX +XXX,XX @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev)
38
return 0;
39
40
fail_vrings:
41
- virtio_scsi_clear_aio(s);
42
+ aio_wait_bh_oneshot(s->ctx, virtio_scsi_dataplane_stop_bh, s);
43
aio_context_release(s->ctx);
44
for (i = 0; i < vs->conf.num_queues + 2; i++) {
45
virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
46
@@ -XXX,XX +XXX,XX @@ void virtio_scsi_dataplane_stop(VirtIODevice *vdev)
47
s->dataplane_stopping = true;
48
49
aio_context_acquire(s->ctx);
50
- virtio_scsi_clear_aio(s);
51
+ aio_wait_bh_oneshot(s->ctx, virtio_scsi_dataplane_stop_bh, s);
52
aio_context_release(s->ctx);
53
54
blk_drain_all(); /* ensure there are no in-flight requests */
55
--
132
--
56
2.14.3
133
2.9.3
57
134
58
135
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
This adds support for reopen in rbd, for changing between r/w and r/o.
2
2
3
Commit 5b2ffbe4d99843fd8305c573a100047a8c962327 ("virtio-blk: dataplane:
3
Note, that this is only a flag change, but we will block a change from
4
notify guest as a batch") deferred guest notification to a BH in order
4
r/o to r/w if we are using an RBD internal snapshot.
5
batch notifications, with purpose of avoiding flooding the guest with
6
interruptions.
7
5
8
This optimization came with a cost. The average latency perceived in the
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
guest is increased by a few microseconds, but also when multiple IO
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
10
operations finish at the same time, the guest won't be notified until
8
Reviewed-by: John Snow <jsnow@redhat.com>
11
all completions from each operation has been run. On the contrary,
9
Message-id: d4e87539167ec6527d44c97b164eabcccf96e4f3.1491597120.git.jcody@redhat.com
12
virtio-scsi issues the notification at the end of each completion.
10
---
11
block/rbd.c | 21 +++++++++++++++++++++
12
1 file changed, 21 insertions(+)
13
13
14
On the other hand, nowadays we have the EVENT_IDX feature that allows a
14
diff --git a/block/rbd.c b/block/rbd.c
15
better coordination between QEMU and the Guest OS to avoid sending
16
unnecessary interruptions.
17
18
With this change, virtio-blk/dataplane only batches notifications if the
19
EVENT_IDX feature is not present.
20
21
Some numbers obtained with fio (ioengine=sync, iodepth=1, direct=1):
22
- Test specs:
23
* fio-3.4 (ioengine=sync, iodepth=1, direct=1)
24
* qemu master
25
* virtio-blk with a dedicated iothread (default poll-max-ns)
26
* backend: null_blk nr_devices=1 irqmode=2 completion_nsec=280000
27
* 8 vCPUs pinned to isolated physical cores
28
* Emulator and iothread also pinned to separate isolated cores
29
* variance between runs < 1%
30
31
- Not patched
32
* numjobs=1: lat_avg=327.32 irqs=29998
33
* numjobs=4: lat_avg=337.89 irqs=29073
34
* numjobs=8: lat_avg=342.98 irqs=28643
35
36
- Patched:
37
* numjobs=1: lat_avg=323.92 irqs=30262
38
* numjobs=4: lat_avg=332.65 irqs=29520
39
* numjobs=8: lat_avg=335.54 irqs=29323
40
41
Signed-off-by: Sergio Lopez <slp@redhat.com>
42
Message-id: 20180307114459.26636-1-slp@redhat.com
43
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
44
---
45
hw/block/dataplane/virtio-blk.c | 15 +++++++++++++--
46
1 file changed, 13 insertions(+), 2 deletions(-)
47
48
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
49
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/block/dataplane/virtio-blk.c
16
--- a/block/rbd.c
51
+++ b/hw/block/dataplane/virtio-blk.c
17
+++ b/block/rbd.c
52
@@ -XXX,XX +XXX,XX @@ struct VirtIOBlockDataPlane {
18
@@ -XXX,XX +XXX,XX @@ failed_opts:
53
VirtIODevice *vdev;
19
return r;
54
QEMUBH *bh; /* bh for guest notification */
55
unsigned long *batch_notify_vqs;
56
+ bool batch_notifications;
57
58
/* Note that these EventNotifiers are assigned by value. This is
59
* fine as long as you do not call event_notifier_cleanup on them
60
@@ -XXX,XX +XXX,XX @@ struct VirtIOBlockDataPlane {
61
/* Raise an interrupt to signal guest, if necessary */
62
void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s, VirtQueue *vq)
63
{
64
- set_bit(virtio_get_queue_index(vq), s->batch_notify_vqs);
65
- qemu_bh_schedule(s->bh);
66
+ if (s->batch_notifications) {
67
+ set_bit(virtio_get_queue_index(vq), s->batch_notify_vqs);
68
+ qemu_bh_schedule(s->bh);
69
+ } else {
70
+ virtio_notify_irqfd(s->vdev, vq);
71
+ }
72
}
20
}
73
21
74
static void notify_guest_bh(void *opaque)
22
+
75
@@ -XXX,XX +XXX,XX @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
23
+/* Since RBD is currently always opened R/W via the API,
76
24
+ * we just need to check if we are using a snapshot or not, in
77
s->starting = true;
25
+ * order to determine if we will allow it to be R/W */
78
26
+static int qemu_rbd_reopen_prepare(BDRVReopenState *state,
79
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
27
+ BlockReopenQueue *queue, Error **errp)
80
+ s->batch_notifications = true;
28
+{
81
+ } else {
29
+ BDRVRBDState *s = state->bs->opaque;
82
+ s->batch_notifications = false;
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;
83
+ }
37
+ }
84
+
38
+
85
/* Set up guest notifier (irq) */
39
+ return ret;
86
r = k->set_guest_notifiers(qbus->parent, nvqs, true);
40
+}
87
if (r != 0) {
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,
88
--
53
--
89
2.14.3
54
2.9.3
90
55
91
56
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
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.
2
3
3
Reported-by: Alberto Garcia <berto@igalia.com>
4
If it is not, if the qemu process aborts, then not all of the droppings
4
Signed-off-by: Fam Zheng <famz@redhat.com>
5
are cleaned up (e.g. pidfile, fifos).
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
6
Message-id: 20180306024328.19195-1-famz@redhat.com
7
This updates those tests that did not have a cleanup in qemu-iotests.
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
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
8
---
15
---
9
README | 2 +-
16
tests/qemu-iotests/028 | 1 +
10
1 file changed, 1 insertion(+), 1 deletion(-)
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(-)
11
27
12
diff --git a/README b/README
28
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
13
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100755
14
--- a/README
30
--- a/tests/qemu-iotests/028
15
+++ b/README
31
+++ b/tests/qemu-iotests/028
16
@@ -XXX,XX +XXX,XX @@ The QEMU website is also maintained under source control.
32
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
17
git clone git://git.qemu.org/qemu-web.git
33
18
https://www.qemu.org/2017/02/04/the-new-qemu-website-is-up/
34
_cleanup()
19
35
{
20
-A 'git-profile' utility was created to make above process less
36
+ _cleanup_qemu
21
+A 'git-publish' utility was created to make above process less
37
rm -f "${TEST_IMG}.copy"
22
cumbersome, and is highly recommended for making regular contributions,
38
_cleanup_test_img
23
or even just for sending consecutive patch series revisions. It also
39
}
24
requires a working 'git send-email' setup, and by default doesn't
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
25
--
172
--
26
2.14.3
173
2.9.3
27
174
28
175
diff view generated by jsdifflib