1
The following changes since commit bfec359afba088aaacc7d316f43302f28c6e642a:
1
The following changes since commit 3fbd3405d2b0604ea530fc7a1828f19da1e95ff9:
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 remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2019-08-17' into staging (2019-08-19 14:14:09 +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/codyprime/qemu-kvm-jtc.git tags/block-pull-request
7
https://github.com/XanClic/qemu.git tags/pull-block-2019-08-19
8
8
9
for you to fetch changes up to 1507631e438930bc07f776f303af127a9cdb4d41:
9
for you to fetch changes up to fa27c478102a6b5d1c6b02c005607ad9404b915f:
10
10
11
qemu-iotests: _cleanup_qemu must be called on exit (2017-04-21 08:32:44 -0400)
11
doc: Preallocation does not require writing zeroes (2019-08-19 17:13:26 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
Block patches:
15
Block patches for 2.10
15
- preallocation=falloc/full support for LUKS
16
- Various minor fixes
16
17
17
----------------------------------------------------------------
18
----------------------------------------------------------------
19
Max Reitz (16):
20
qemu-img: Fix bdrv_has_zero_init() use in convert
21
mirror: Fix bdrv_has_zero_init() use
22
block: Add bdrv_has_zero_init_truncate()
23
block: Implement .bdrv_has_zero_init_truncate()
24
block: Use bdrv_has_zero_init_truncate()
25
qcow2: Fix .bdrv_has_zero_init()
26
vdi: Fix .bdrv_has_zero_init()
27
vhdx: Fix .bdrv_has_zero_init()
28
iotests: Convert to preallocated encrypted qcow2
29
iotests: Test convert -n to pre-filled image
30
iotests: Full mirror to existing non-zero image
31
vdi: Make block_status recurse for fixed images
32
vmdk: Make block_status recurse for flat extents
33
vpc: Do not return RAW from block_status
34
iotests: Fix 141 when run with qed
35
doc: Preallocation does not require writing zeroes
18
36
19
Ashish Mittal (2):
37
Maxim Levitsky (1):
20
block/vxhs.c: Add support for a new block device type called "vxhs"
38
LUKS: support preallocation
21
block/vxhs.c: Add qemu-iotests for new block device type "vxhs"
22
39
23
Jeff Cody (10):
40
qapi/block-core.json | 15 +++++---
24
qemu-iotests: exclude vxhs from image creation via protocol
41
include/block/block.h | 1 +
25
block: add bdrv_set_read_only() helper function
42
include/block/block_int.h | 9 +++++
26
block: do not set BDS read_only if copy_on_read enabled
43
block.c | 21 +++++++++++
27
block: honor BDRV_O_ALLOW_RDWR when clearing bs->read_only
44
block/crypto.c | 30 ++++++++++++++--
28
block: code movement
45
block/file-posix.c | 1 +
29
block: introduce bdrv_can_set_read_only()
46
block/file-win32.c | 1 +
30
block: use bdrv_can_set_read_only() during reopen
47
block/gluster.c | 4 +++
31
block/rbd - update variable names to more apt names
48
block/mirror.c | 11 ++++--
32
block/rbd: Add support for reopen()
49
block/nfs.c | 1 +
33
qemu-iotests: _cleanup_qemu must be called on exit
50
block/parallels.c | 2 +-
34
51
block/qcow2.c | 30 +++++++++++++++-
35
block.c | 56 +++-
52
block/qed.c | 1 +
36
block/Makefile.objs | 2 +
53
block/raw-format.c | 6 ++++
37
block/bochs.c | 5 +-
54
block/rbd.c | 1 +
38
block/cloop.c | 5 +-
55
block/sheepdog.c | 1 +
39
block/dmg.c | 6 +-
56
block/ssh.c | 1 +
40
block/rbd.c | 65 +++--
57
block/vdi.c | 16 +++++++--
41
block/trace-events | 17 ++
58
block/vhdx.c | 28 +++++++++++++--
42
block/vvfat.c | 19 +-
59
block/vmdk.c | 3 ++
43
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++
60
block/vpc.c | 2 +-
44
configure | 39 +++
61
blockdev.c | 16 +++++++--
45
include/block/block.h | 2 +
62
qemu-img.c | 11 ++++--
46
qapi/block-core.json | 23 +-
63
tests/test-block-iothread.c | 2 +-
47
tests/qemu-iotests/017 | 1 +
64
docs/qemu-block-drivers.texi | 4 +--
48
tests/qemu-iotests/020 | 1 +
65
qemu-img.texi | 4 +--
49
tests/qemu-iotests/028 | 1 +
66
tests/qemu-iotests/041 | 62 +++++++++++++++++++++++++++++---
50
tests/qemu-iotests/029 | 1 +
67
tests/qemu-iotests/041.out | 4 +--
51
tests/qemu-iotests/073 | 1 +
68
tests/qemu-iotests/122 | 17 +++++++++
52
tests/qemu-iotests/094 | 11 +-
69
tests/qemu-iotests/122.out | 8 +++++
53
tests/qemu-iotests/102 | 5 +-
70
tests/qemu-iotests/141 | 9 +++--
54
tests/qemu-iotests/109 | 1 +
71
tests/qemu-iotests/141.out | 5 ---
55
tests/qemu-iotests/114 | 1 +
72
tests/qemu-iotests/188 | 20 ++++++++++-
56
tests/qemu-iotests/117 | 1 +
73
tests/qemu-iotests/188.out | 4 +++
57
tests/qemu-iotests/130 | 2 +
74
tests/qemu-iotests/common.filter | 5 +++
58
tests/qemu-iotests/134 | 1 +
75
35 files changed, 313 insertions(+), 43 deletions(-)
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
76
71
--
77
--
72
2.9.3
78
2.21.0
73
79
74
80
diff view generated by jsdifflib
1
From: Ashish Mittal <ashmit602@gmail.com>
1
From: Maxim Levitsky <mlevitsk@redhat.com>
2
2
3
Source code for the qnio library that this code loads can be downloaded from:
3
preallocation=off and preallocation=metadata
4
https://github.com/VeritasHyperScale/libqnio.git
4
both allocate luks header only, and preallocation=falloc/full
5
is passed to underlying file.
5
6
6
Sample command line using JSON syntax:
7
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1534951
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
8
13
Sample command line using URI syntax:
9
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
14
qemu-img convert -f raw -O raw -n
10
Message-id: 20190716161901.1430-1-mlevitsk@redhat.com
15
/var/lib/nova/instances/_base/0c5eacd5ebea5ed914b6a3e7b18f1ce734c386ad
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
vxhs://192.168.0.1:9999/c6718f6b-0401-441d-a8c3-1f0064d75ee0
12
---
13
qapi/block-core.json | 6 +++++-
14
block/crypto.c | 30 +++++++++++++++++++++++++++---
15
2 files changed, 32 insertions(+), 4 deletions(-)
17
16
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
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
25
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
26
Reviewed-by: Jeff Cody <jcody@redhat.com>
27
Signed-off-by: Jeff Cody <jcody@redhat.com>
28
Message-id: 1491277689-24949-2-git-send-email-Ashish.Mittal@veritas.com
29
---
30
block/Makefile.objs | 2 +
31
block/trace-events | 17 ++
32
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++++++++++++++
33
configure | 39 ++++
34
qapi/block-core.json | 23 ++-
35
5 files changed, 654 insertions(+), 2 deletions(-)
36
create mode 100644 block/vxhs.c
37
38
diff --git a/block/Makefile.objs b/block/Makefile.objs
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/Makefile.objs
41
+++ b/block/Makefile.objs
42
@@ -XXX,XX +XXX,XX @@ block-obj-$(CONFIG_LIBNFS) += nfs.o
43
block-obj-$(CONFIG_CURL) += curl.o
44
block-obj-$(CONFIG_RBD) += rbd.o
45
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
46
+block-obj-$(CONFIG_VXHS) += vxhs.o
47
block-obj-$(CONFIG_LIBSSH2) += ssh.o
48
block-obj-y += accounting.o dirty-bitmap.o
49
block-obj-y += write-threshold.o
50
@@ -XXX,XX +XXX,XX @@ rbd.o-cflags := $(RBD_CFLAGS)
51
rbd.o-libs := $(RBD_LIBS)
52
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
53
gluster.o-libs := $(GLUSTERFS_LIBS)
54
+vxhs.o-libs := $(VXHS_LIBS)
55
ssh.o-cflags := $(LIBSSH2_CFLAGS)
56
ssh.o-libs := $(LIBSSH2_LIBS)
57
block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o
58
diff --git a/block/trace-events b/block/trace-events
59
index XXXXXXX..XXXXXXX 100644
60
--- a/block/trace-events
61
+++ b/block/trace-events
62
@@ -XXX,XX +XXX,XX @@ qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s
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
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
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"
66
+
67
+# block/vxhs.c
68
+vxhs_iio_callback(int error) "ctx is NULL: error %d"
69
+vxhs_iio_callback_chnfail(int err, int error) "QNIO channel failed, no i/o %d, %d"
70
+vxhs_iio_callback_unknwn(int opcode, int err) "unexpected opcode %d, errno %d"
71
+vxhs_aio_rw_invalid(int req) "Invalid I/O request iodir %d"
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"
73
+vxhs_get_vdisk_stat_err(char *guid, int ret, int err) "vDisk (%s) stat ioctl failed, ret = %d, errno = %d"
74
+vxhs_get_vdisk_stat(char *vdisk_guid, uint64_t vdisk_size) "vDisk %s stat ioctl returned size %lu"
75
+vxhs_complete_aio(void *acb, uint64_t ret) "aio failed acb %p ret %ld"
76
+vxhs_parse_uri_filename(const char *filename) "URI passed via bdrv_parse_filename %s"
77
+vxhs_open_vdiskid(const char *vdisk_id) "Opening vdisk-id %s"
78
+vxhs_open_hostinfo(char *of_vsa_addr, int port) "Adding host %s:%d to BDRVVXHSState"
79
+vxhs_open_iio_open(const char *host) "Failed to connect to storage agent on host %s"
80
+vxhs_parse_uri_hostinfo(char *host, int port) "Host: IP %s, Port %d"
81
+vxhs_close(char *vdisk_guid) "Closing vdisk %s"
82
+vxhs_get_creds(const char *cacert, const char *client_key, const char *client_cert) "cacert %s, client_key %s, client_cert %s"
83
diff --git a/block/vxhs.c b/block/vxhs.c
84
new file mode 100644
85
index XXXXXXX..XXXXXXX
86
--- /dev/null
87
+++ b/block/vxhs.c
88
@@ -XXX,XX +XXX,XX @@
89
+/*
90
+ * QEMU Block driver for Veritas HyperScale (VxHS)
91
+ *
92
+ * Copyright (c) 2017 Veritas Technologies LLC.
93
+ *
94
+ * 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.
96
+ *
97
+ */
98
+
99
+#include "qemu/osdep.h"
100
+#include <qnio/qnio_api.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"
109
+#include "qemu/uuid.h"
110
+#include "crypto/tlscredsx509.h"
111
+
112
+#define VXHS_OPT_FILENAME "filename"
113
+#define VXHS_OPT_VDISK_ID "vdisk-id"
114
+#define VXHS_OPT_SERVER "server"
115
+#define VXHS_OPT_HOST "host"
116
+#define VXHS_OPT_PORT "port"
117
+
118
+/* Only accessed under QEMU global mutex */
119
+static uint32_t vxhs_ref;
120
+
121
+typedef enum {
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
+{
151
+ VXHSAIOCB *acb = opaque;
152
+ BlockCompletionFunc *cb = acb->common.cb;
153
+ void *cb_opaque = acb->common.opaque;
154
+ int ret = 0;
155
+
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
+}
164
+
165
+/*
166
+ * Called from a libqnio thread
167
+ */
168
+static void vxhs_iio_callback(void *ctx, uint32_t opcode, uint32_t error)
169
+{
170
+ VXHSAIOCB *acb = NULL;
171
+
172
+ switch (opcode) {
173
+ case IRP_READ_REQUEST:
174
+ case IRP_WRITE_REQUEST:
175
+
176
+ /*
177
+ * ctx is VXHSAIOCB*
178
+ * ctx is NULL if error is QNIOERROR_CHANNEL_HUP
179
+ */
180
+ if (ctx) {
181
+ acb = ctx;
182
+ } else {
183
+ trace_vxhs_iio_callback(error);
184
+ goto out;
185
+ }
186
+
187
+ if (error) {
188
+ if (!acb->err) {
189
+ acb->err = error;
190
+ }
191
+ trace_vxhs_iio_callback(error);
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;
212
+}
213
+
214
+static QemuOptsList runtime_opts = {
215
+ .name = "vxhs",
216
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
217
+ .desc = {
218
+ {
219
+ .name = VXHS_OPT_FILENAME,
220
+ .type = QEMU_OPT_STRING,
221
+ .help = "URI to the Veritas HyperScale image",
222
+ },
223
+ {
224
+ .name = VXHS_OPT_VDISK_ID,
225
+ .type = QEMU_OPT_STRING,
226
+ .help = "UUID of the VxHS vdisk",
227
+ },
228
+ {
229
+ .name = "tls-creds",
230
+ .type = QEMU_OPT_STRING,
231
+ .help = "ID of the TLS/SSL credentials to use",
232
+ },
233
+ { /* end of list */ }
234
+ },
235
+};
236
+
237
+static QemuOptsList runtime_tcp_opts = {
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
+{
262
+ URI *uri = NULL;
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
+}
288
+
289
+static void vxhs_parse_filename(const char *filename, QDict *options,
290
+ Error **errp)
291
+{
292
+ if (qdict_haskey(options, "vdisk-id") || qdict_haskey(options, "server")) {
293
+ error_setg(errp, "vdisk-id/server and a file name may not be specified "
294
+ "at the same time");
295
+ return;
296
+ }
297
+
298
+ if (strstr(filename, "://")) {
299
+ int ret = vxhs_parse_uri(filename, options);
300
+ if (ret < 0) {
301
+ error_setg(errp, "Invalid URI. URI should be of the form "
302
+ " vxhs://<host_ip>:<port>/<vdisk-id>");
303
+ }
304
+ }
305
+}
306
+
307
+static int vxhs_init_and_ref(void)
308
+{
309
+ if (vxhs_ref++ == 0) {
310
+ if (iio_init(QNIO_VERSION, vxhs_iio_callback)) {
311
+ return -ENODEV;
312
+ }
313
+ }
314
+ return 0;
315
+}
316
+
317
+static void vxhs_unref(void)
318
+{
319
+ if (--vxhs_ref == 0) {
320
+ iio_fini();
321
+ }
322
+}
323
+
324
+static void vxhs_get_tls_creds(const char *id, char **cacert,
325
+ char **key, char **cert, Error **errp)
326
+{
327
+ Object *obj;
328
+ QCryptoTLSCreds *creds;
329
+ QCryptoTLSCredsX509 *creds_x509;
330
+
331
+ obj = object_resolve_path_component(
332
+ object_get_objects_root(), id);
333
+
334
+ if (!obj) {
335
+ error_setg(errp, "No TLS credentials with id '%s'",
336
+ id);
337
+ return;
338
+ }
339
+
340
+ creds_x509 = (QCryptoTLSCredsX509 *)
341
+ object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS_X509);
342
+
343
+ if (!creds_x509) {
344
+ error_setg(errp, "Object with id '%s' is not TLS credentials",
345
+ id);
346
+ return;
347
+ }
348
+
349
+ creds = &creds_x509->parent_obj;
350
+
351
+ if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
352
+ error_setg(errp,
353
+ "Expecting TLS credentials with a client endpoint");
354
+ return;
355
+ }
356
+
357
+ /*
358
+ * Get the cacert, client_cert and client_key file names.
359
+ */
360
+ if (!creds->dir) {
361
+ error_setg(errp, "TLS object missing 'dir' property value");
362
+ return;
363
+ }
364
+
365
+ *cacert = g_strdup_printf("%s/%s", creds->dir,
366
+ QCRYPTO_TLS_CREDS_X509_CA_CERT);
367
+ *cert = g_strdup_printf("%s/%s", creds->dir,
368
+ QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
369
+ *key = g_strdup_printf("%s/%s", creds->dir,
370
+ QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
371
+}
372
+
373
+static int vxhs_open(BlockDriverState *bs, QDict *options,
374
+ int bdrv_flags, Error **errp)
375
+{
376
+ BDRVVXHSState *s = bs->opaque;
377
+ void *dev_handlep;
378
+ QDict *backing_options = NULL;
379
+ QemuOpts *opts = NULL;
380
+ QemuOpts *tcp_opts = NULL;
381
+ char *of_vsa_addr = NULL;
382
+ Error *local_err = NULL;
383
+ const char *vdisk_id_opt;
384
+ const char *server_host_opt;
385
+ int ret = 0;
386
+ char *cacert = NULL;
387
+ char *client_key = NULL;
388
+ char *client_cert = NULL;
389
+
390
+ ret = vxhs_init_and_ref();
391
+ if (ret < 0) {
392
+ ret = -EINVAL;
393
+ goto out;
394
+ }
395
+
396
+ /* Create opts info from runtime_opts and runtime_tcp_opts list */
397
+ opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
398
+ tcp_opts = qemu_opts_create(&runtime_tcp_opts, NULL, 0, &error_abort);
399
+
400
+ qemu_opts_absorb_qdict(opts, options, &local_err);
401
+ if (local_err) {
402
+ ret = -EINVAL;
403
+ goto out;
404
+ }
405
+
406
+ /* vdisk-id is the disk UUID */
407
+ vdisk_id_opt = qemu_opt_get(opts, VXHS_OPT_VDISK_ID);
408
+ if (!vdisk_id_opt) {
409
+ error_setg(&local_err, QERR_MISSING_PARAMETER, VXHS_OPT_VDISK_ID);
410
+ ret = -EINVAL;
411
+ goto out;
412
+ }
413
+
414
+ /* vdisk-id may contain a leading '/' */
415
+ if (strlen(vdisk_id_opt) > UUID_FMT_LEN + 1) {
416
+ error_setg(&local_err, "vdisk-id cannot be more than %d characters",
417
+ UUID_FMT_LEN);
418
+ ret = -EINVAL;
419
+ goto out;
420
+ }
421
+
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
17
diff --git a/qapi/block-core.json b/qapi/block-core.json
750
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
751
--- a/qapi/block-core.json
19
--- a/qapi/block-core.json
752
+++ b/qapi/block-core.json
20
+++ b/qapi/block-core.json
753
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
754
#
22
#
755
# Drivers that are supported in block device operations.
23
# @file Node to create the image format on
24
# @size Size of the virtual disk in bytes
25
+# @preallocation Preallocation mode for the new image
26
+# (since: 4.2)
27
+# (default: off; allowed values: off, metadata, falloc, full)
756
#
28
#
757
+# @vxhs: Since 2.10
29
# Since: 2.12
758
+#
759
# Since: 2.9
760
##
30
##
761
{ 'enum': 'BlockdevDriver',
31
{ 'struct': 'BlockdevCreateOptionsLUKS',
762
@@ -XXX,XX +XXX,XX @@
32
'base': 'QCryptoBlockCreateOptionsLUKS',
763
'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
33
'data': { 'file': 'BlockdevRef',
764
'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
34
- 'size': 'size' } }
765
'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
35
+ 'size': 'size',
766
- 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
36
+ '*preallocation': 'PreallocMode' } }
767
+ 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
768
37
769
##
38
##
770
# @BlockdevOptionsFile:
39
# @BlockdevCreateOptionsNfs:
771
@@ -XXX,XX +XXX,XX @@
40
diff --git a/block/crypto.c b/block/crypto.c
772
'data': { '*offset': 'int', '*size': 'int' } }
41
index XXXXXXX..XXXXXXX 100644
773
42
--- a/block/crypto.c
774
##
43
+++ b/block/crypto.c
775
+# @BlockdevOptionsVxHS:
44
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
776
+#
45
struct BlockCryptoCreateData {
777
+# Driver specific block device options for VxHS
46
BlockBackend *blk;
778
+#
47
uint64_t size;
779
+# @vdisk-id: UUID of VxHS volume
48
+ PreallocMode prealloc;
780
+# @server: vxhs server IP, port
49
};
781
+# @tls-creds: TLS credentials ID
50
782
+#
51
783
+# Since: 2.10
52
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
784
+##
53
* available to the guest, so we must take account of that
785
+{ 'struct': 'BlockdevOptionsVxHS',
54
* which will be used by the crypto header
786
+ 'data': { 'vdisk-id': 'str',
55
*/
787
+ 'server': 'InetSocketAddressBase',
56
- return blk_truncate(data->blk, data->size + headerlen, PREALLOC_MODE_OFF,
788
+ '*tls-creds': 'str' } }
57
+ return blk_truncate(data->blk, data->size + headerlen, data->prealloc,
58
errp);
59
}
60
61
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
62
static int block_crypto_co_create_generic(BlockDriverState *bs,
63
int64_t size,
64
QCryptoBlockCreateOptions *opts,
65
+ PreallocMode prealloc,
66
Error **errp)
67
{
68
int ret;
69
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
70
goto cleanup;
71
}
72
73
+ if (prealloc == PREALLOC_MODE_METADATA) {
74
+ prealloc = PREALLOC_MODE_OFF;
75
+ }
789
+
76
+
790
+##
77
data = (struct BlockCryptoCreateData) {
791
# @BlockdevOptions:
78
.blk = blk,
792
#
79
.size = size,
793
# Options for creating a block device. Many options are available for all
80
+ .prealloc = prealloc,
794
@@ -XXX,XX +XXX,XX @@
81
};
795
'vhdx': 'BlockdevOptionsGenericFormat',
82
796
'vmdk': 'BlockdevOptionsGenericCOWFormat',
83
crypto = qcrypto_block_create(opts, NULL,
797
'vpc': 'BlockdevOptionsGenericFormat',
84
@@ -XXX,XX +XXX,XX @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
798
- 'vvfat': 'BlockdevOptionsVVFAT'
85
BlockdevCreateOptionsLUKS *luks_opts;
799
+ 'vvfat': 'BlockdevOptionsVVFAT',
86
BlockDriverState *bs = NULL;
800
+ 'vxhs': 'BlockdevOptionsVxHS'
87
QCryptoBlockCreateOptions create_opts;
801
} }
88
+ PreallocMode preallocation = PREALLOC_MODE_OFF;
802
89
int ret;
803
##
90
91
assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
92
@@ -XXX,XX +XXX,XX @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
93
.u.luks = *qapi_BlockdevCreateOptionsLUKS_base(luks_opts),
94
};
95
96
+ if (luks_opts->has_preallocation) {
97
+ preallocation = luks_opts->preallocation;
98
+ }
99
+
100
ret = block_crypto_co_create_generic(bs, luks_opts->size, &create_opts,
101
- errp);
102
+ preallocation, errp);
103
if (ret < 0) {
104
goto fail;
105
}
106
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
107
QCryptoBlockCreateOptions *create_opts = NULL;
108
BlockDriverState *bs = NULL;
109
QDict *cryptoopts;
110
+ PreallocMode prealloc;
111
+ char *buf = NULL;
112
int64_t size;
113
int ret;
114
+ Error *local_err = NULL;
115
116
/* Parse options */
117
size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
118
119
+ buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
120
+ prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
121
+ PREALLOC_MODE_OFF, &local_err);
122
+ g_free(buf);
123
+ if (local_err) {
124
+ error_propagate(errp, local_err);
125
+ return -EINVAL;
126
+ }
127
+
128
cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
129
&block_crypto_create_opts_luks,
130
true);
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
132
}
133
134
/* Create format layer */
135
- ret = block_crypto_co_create_generic(bs, size, create_opts, errp);
136
+ ret = block_crypto_co_create_generic(bs, size, create_opts, prealloc, errp);
137
if (ret < 0) {
138
goto fail;
139
}
804
--
140
--
805
2.9.3
141
2.21.0
806
142
807
143
diff view generated by jsdifflib
New patch
1
bdrv_has_zero_init() only has meaning for newly created images or image
2
areas. If qemu-img convert did not create the image itself, it cannot
3
rely on bdrv_has_zero_init()'s result to carry any meaning.
1
4
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Message-id: 20190724171239.8764-2-mreitz@redhat.com
7
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
8
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
qemu-img.c | 11 ++++++++---
12
1 file changed, 8 insertions(+), 3 deletions(-)
13
14
diff --git a/qemu-img.c b/qemu-img.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-img.c
17
+++ b/qemu-img.c
18
@@ -XXX,XX +XXX,XX @@ typedef struct ImgConvertState {
19
bool has_zero_init;
20
bool compressed;
21
bool unallocated_blocks_are_zero;
22
+ bool target_is_new;
23
bool target_has_backing;
24
int64_t target_backing_sectors; /* negative if unknown */
25
bool wr_in_order;
26
@@ -XXX,XX +XXX,XX @@ static int convert_do_copy(ImgConvertState *s)
27
int64_t sector_num = 0;
28
29
/* Check whether we have zero initialisation or can get it efficiently */
30
- s->has_zero_init = s->min_sparse && !s->target_has_backing
31
- ? bdrv_has_zero_init(blk_bs(s->target))
32
- : false;
33
+ if (s->target_is_new && s->min_sparse && !s->target_has_backing) {
34
+ s->has_zero_init = bdrv_has_zero_init(blk_bs(s->target));
35
+ } else {
36
+ s->has_zero_init = false;
37
+ }
38
39
if (!s->has_zero_init && !s->target_has_backing &&
40
bdrv_can_write_zeroes_with_unmap(blk_bs(s->target)))
41
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
42
}
43
}
44
45
+ s.target_is_new = !skip_create;
46
+
47
flags = s.min_sparse ? (BDRV_O_RDWR | BDRV_O_UNMAP) : BDRV_O_RDWR;
48
ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
49
if (ret < 0) {
50
--
51
2.21.0
52
53
diff view generated by jsdifflib
New patch
1
1
bdrv_has_zero_init() only has meaning for newly created images or image
2
areas. If the mirror job itself did not create the image, it cannot
3
rely on bdrv_has_zero_init()'s result to carry any meaning.
4
5
This is the case for drive-mirror with mode=existing and always for
6
blockdev-mirror.
7
8
Note that we only have to zero-initialize the target with sync=full,
9
because other modes actually do not promise that the target will contain
10
the same data as the source after the job -- sync=top only promises to
11
copy anything allocated in the top layer, and sync=none will only copy
12
new I/O. (Which is how mirror has always handled it.)
13
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Message-id: 20190724171239.8764-3-mreitz@redhat.com
16
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
include/block/block_int.h | 2 ++
20
block/mirror.c | 11 ++++++++---
21
blockdev.c | 16 +++++++++++++---
22
tests/test-block-iothread.c | 2 +-
23
4 files changed, 24 insertions(+), 7 deletions(-)
24
25
diff --git a/include/block/block_int.h b/include/block/block_int.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/block_int.h
28
+++ b/include/block/block_int.h
29
@@ -XXX,XX +XXX,XX @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
30
* @buf_size: The amount of data that can be in flight at one time.
31
* @mode: Whether to collapse all images in the chain to the target.
32
* @backing_mode: How to establish the target's backing chain after completion.
33
+ * @zero_target: Whether the target should be explicitly zero-initialized
34
* @on_source_error: The action to take upon error reading from the source.
35
* @on_target_error: The action to take upon error writing to the target.
36
* @unmap: Whether to unmap target where source sectors only contain zeroes.
37
@@ -XXX,XX +XXX,XX @@ void mirror_start(const char *job_id, BlockDriverState *bs,
38
int creation_flags, int64_t speed,
39
uint32_t granularity, int64_t buf_size,
40
MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
41
+ bool zero_target,
42
BlockdevOnError on_source_error,
43
BlockdevOnError on_target_error,
44
bool unmap, const char *filter_node_name,
45
diff --git a/block/mirror.c b/block/mirror.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/mirror.c
48
+++ b/block/mirror.c
49
@@ -XXX,XX +XXX,XX @@ typedef struct MirrorBlockJob {
50
Error *replace_blocker;
51
bool is_none_mode;
52
BlockMirrorBackingMode backing_mode;
53
+ /* Whether the target image requires explicit zero-initialization */
54
+ bool zero_target;
55
MirrorCopyMode copy_mode;
56
BlockdevOnError on_source_error, on_target_error;
57
bool synced;
58
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
59
int ret;
60
int64_t count;
61
62
- if (base == NULL && !bdrv_has_zero_init(target_bs)) {
63
+ if (s->zero_target) {
64
if (!bdrv_can_write_zeroes_with_unmap(target_bs)) {
65
bdrv_set_dirty_bitmap(s->dirty_bitmap, 0, s->bdev_length);
66
return 0;
67
@@ -XXX,XX +XXX,XX @@ static BlockJob *mirror_start_job(
68
const char *replaces, int64_t speed,
69
uint32_t granularity, int64_t buf_size,
70
BlockMirrorBackingMode backing_mode,
71
+ bool zero_target,
72
BlockdevOnError on_source_error,
73
BlockdevOnError on_target_error,
74
bool unmap,
75
@@ -XXX,XX +XXX,XX @@ static BlockJob *mirror_start_job(
76
s->on_target_error = on_target_error;
77
s->is_none_mode = is_none_mode;
78
s->backing_mode = backing_mode;
79
+ s->zero_target = zero_target;
80
s->copy_mode = copy_mode;
81
s->base = base;
82
s->granularity = granularity;
83
@@ -XXX,XX +XXX,XX @@ void mirror_start(const char *job_id, BlockDriverState *bs,
84
int creation_flags, int64_t speed,
85
uint32_t granularity, int64_t buf_size,
86
MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
87
+ bool zero_target,
88
BlockdevOnError on_source_error,
89
BlockdevOnError on_target_error,
90
bool unmap, const char *filter_node_name,
91
@@ -XXX,XX +XXX,XX @@ void mirror_start(const char *job_id, BlockDriverState *bs,
92
is_none_mode = mode == MIRROR_SYNC_MODE_NONE;
93
base = mode == MIRROR_SYNC_MODE_TOP ? backing_bs(bs) : NULL;
94
mirror_start_job(job_id, bs, creation_flags, target, replaces,
95
- speed, granularity, buf_size, backing_mode,
96
+ speed, granularity, buf_size, backing_mode, zero_target,
97
on_source_error, on_target_error, unmap, NULL, NULL,
98
&mirror_job_driver, is_none_mode, base, false,
99
filter_node_name, true, copy_mode, errp);
100
@@ -XXX,XX +XXX,XX @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
101
102
ret = mirror_start_job(
103
job_id, bs, creation_flags, base, NULL, speed, 0, 0,
104
- MIRROR_LEAVE_BACKING_CHAIN,
105
+ MIRROR_LEAVE_BACKING_CHAIN, false,
106
on_error, on_error, true, cb, opaque,
107
&commit_active_job_driver, false, base, auto_complete,
108
filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND,
109
diff --git a/blockdev.c b/blockdev.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/blockdev.c
112
+++ b/blockdev.c
113
@@ -XXX,XX +XXX,XX @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
114
bool has_replaces, const char *replaces,
115
enum MirrorSyncMode sync,
116
BlockMirrorBackingMode backing_mode,
117
+ bool zero_target,
118
bool has_speed, int64_t speed,
119
bool has_granularity, uint32_t granularity,
120
bool has_buf_size, int64_t buf_size,
121
@@ -XXX,XX +XXX,XX @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
122
*/
123
mirror_start(job_id, bs, target,
124
has_replaces ? replaces : NULL, job_flags,
125
- speed, granularity, buf_size, sync, backing_mode,
126
+ speed, granularity, buf_size, sync, backing_mode, zero_target,
127
on_source_error, on_target_error, unmap, filter_node_name,
128
copy_mode, errp);
129
}
130
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
131
int flags;
132
int64_t size;
133
const char *format = arg->format;
134
+ bool zero_target;
135
int ret;
136
137
bs = qmp_get_root_bs(arg->device, errp);
138
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
139
goto out;
140
}
141
142
+ zero_target = (arg->sync == MIRROR_SYNC_MODE_FULL &&
143
+ (arg->mode == NEW_IMAGE_MODE_EXISTING ||
144
+ !bdrv_has_zero_init(target_bs)));
145
+
146
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
147
if (ret < 0) {
148
bdrv_unref(target_bs);
149
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
150
151
blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
152
arg->has_replaces, arg->replaces, arg->sync,
153
- backing_mode, arg->has_speed, arg->speed,
154
+ backing_mode, zero_target,
155
+ arg->has_speed, arg->speed,
156
arg->has_granularity, arg->granularity,
157
arg->has_buf_size, arg->buf_size,
158
arg->has_on_source_error, arg->on_source_error,
159
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
160
AioContext *aio_context;
161
BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
162
Error *local_err = NULL;
163
+ bool zero_target;
164
int ret;
165
166
bs = qmp_get_root_bs(device, errp);
167
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
168
return;
169
}
170
171
+ zero_target = (sync == MIRROR_SYNC_MODE_FULL);
172
+
173
aio_context = bdrv_get_aio_context(bs);
174
aio_context_acquire(aio_context);
175
176
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
177
178
blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs,
179
has_replaces, replaces, sync, backing_mode,
180
- has_speed, speed,
181
+ zero_target, has_speed, speed,
182
has_granularity, granularity,
183
has_buf_size, buf_size,
184
has_on_source_error, on_source_error,
185
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/tests/test-block-iothread.c
188
+++ b/tests/test-block-iothread.c
189
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
190
191
/* Start a mirror job */
192
mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0,
193
- MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN,
194
+ MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false,
195
BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
196
false, "filter_node", MIRROR_COPY_MODE_BACKGROUND,
197
&error_abort);
198
--
199
2.21.0
200
201
diff view generated by jsdifflib
1
Introduce check function for setting read_only flags. Will return < 0 on
1
No .bdrv_has_zero_init() implementation returns 1 if growing the file
2
error, with appropriate Error value set. Does not alter any flags.
2
would add non-zero areas (at least with PREALLOC_MODE_OFF), so using it
3
in lieu of this new function was always safe.
3
4
4
Signed-off-by: Jeff Cody <jcody@redhat.com>
5
But on the other hand, it is possible that growing an image that is not
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
zero-initialized would still add a zero-initialized area, like when
6
Reviewed-by: John Snow <jsnow@redhat.com>
7
using nonpreallocating truncation on a preallocated image. For callers
7
Message-id: e2bba34ac3bc76a0c42adc390413f358ae0566e8.1491597120.git.jcody@redhat.com
8
that care only about truncation, not about creation with potential
9
preallocation, this new function is useful.
10
11
Alternatively, we could have added a PreallocMode parameter to
12
bdrv_has_zero_init(). But the only user would have been qemu-img
13
convert, which does not have a plain PreallocMode value right now -- it
14
would have to parse the creation option to obtain it. Therefore, the
15
simpler solution is to let bdrv_has_zero_init() inquire the
16
preallocation status and add the new bdrv_has_zero_init_truncate() that
17
presupposes PREALLOC_MODE_OFF.
18
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
Message-id: 20190724171239.8764-4-mreitz@redhat.com
21
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
22
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
24
---
9
block.c | 14 +++++++++++++-
25
include/block/block.h | 1 +
10
include/block/block.h | 1 +
26
include/block/block_int.h | 7 +++++++
11
2 files changed, 14 insertions(+), 1 deletion(-)
27
block.c | 21 +++++++++++++++++++++
28
3 files changed, 29 insertions(+)
12
29
30
diff --git a/include/block/block.h b/include/block/block.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/block.h
33
+++ b/include/block/block.h
34
@@ -XXX,XX +XXX,XX @@ int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
35
int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
36
int bdrv_has_zero_init_1(BlockDriverState *bs);
37
int bdrv_has_zero_init(BlockDriverState *bs);
38
+int bdrv_has_zero_init_truncate(BlockDriverState *bs);
39
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
40
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
41
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
42
diff --git a/include/block/block_int.h b/include/block/block_int.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/include/block/block_int.h
45
+++ b/include/block/block_int.h
46
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
47
/*
48
* Returns 1 if newly created images are guaranteed to contain only
49
* zeros, 0 otherwise.
50
+ * Must return 0 if .bdrv_has_zero_init_truncate() returns 0.
51
*/
52
int (*bdrv_has_zero_init)(BlockDriverState *bs);
53
54
+ /*
55
+ * Returns 1 if new areas added by growing the image with
56
+ * PREALLOC_MODE_OFF contain only zeros, 0 otherwise.
57
+ */
58
+ int (*bdrv_has_zero_init_truncate)(BlockDriverState *bs);
59
+
60
/* Remove fd handlers, timers, and other event loop callbacks so the event
61
* loop is no longer in use. Called with no in-flight requests and in
62
* depth-first traversal order with parents before child nodes.
13
diff --git a/block.c b/block.c
63
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
65
--- a/block.c
16
+++ b/block.c
66
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
67
@@ -XXX,XX +XXX,XX @@ int bdrv_has_zero_init(BlockDriverState *bs)
18
return bs->read_only;
68
return 0;
19
}
69
}
20
70
21
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
71
+int bdrv_has_zero_init_truncate(BlockDriverState *bs)
22
+int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
72
+{
23
{
73
+ if (!bs->drv) {
24
/* Do not set read_only if copy_on_read is enabled */
74
+ return 0;
25
if (bs->copy_on_read && read_only) {
75
+ }
26
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
76
+
27
return -EPERM;
77
+ if (bs->backing) {
28
}
78
+ /* Depends on the backing image length, but better safe than sorry */
29
79
+ return 0;
80
+ }
81
+ if (bs->drv->bdrv_has_zero_init_truncate) {
82
+ return bs->drv->bdrv_has_zero_init_truncate(bs);
83
+ }
84
+ if (bs->file && bs->drv->is_filter) {
85
+ return bdrv_has_zero_init_truncate(bs->file->bs);
86
+ }
87
+
88
+ /* safe default */
30
+ return 0;
89
+ return 0;
31
+}
90
+}
32
+
91
+
33
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
92
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs)
34
+{
93
{
35
+ int ret = 0;
94
BlockDriverInfo bdi;
36
+
37
+ ret = bdrv_can_set_read_only(bs, read_only, errp);
38
+ if (ret < 0) {
39
+ return ret;
40
+ }
41
+
42
bs->read_only = read_only;
43
return 0;
44
}
45
diff --git a/include/block/block.h b/include/block/block.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/block/block.h
48
+++ b/include/block/block.h
49
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
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);
57
--
95
--
58
2.9.3
96
2.21.0
59
97
60
98
diff view generated by jsdifflib
1
We have a helper wrapper for checking for the BDS read_only flag,
1
We need to implement .bdrv_has_zero_init_truncate() for every block
2
add a helper wrapper to set the read_only flag as well.
2
driver that supports truncation and has a .bdrv_has_zero_init()
3
implementation.
3
4
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Implement it the same way each driver implements .bdrv_has_zero_init().
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
6
This is at least not any more unsafe than what we had before.
6
Reviewed-by: John Snow <jsnow@redhat.com>
7
7
Message-id: 9b18972d05f5fa2ac16c014f0af98d680553048d.1491597120.git.jcody@redhat.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20190724171239.8764-5-mreitz@redhat.com
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
11
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
13
---
9
block.c | 5 +++++
14
block/file-posix.c | 1 +
10
block/bochs.c | 2 +-
15
block/file-win32.c | 1 +
11
block/cloop.c | 2 +-
16
block/gluster.c | 4 ++++
12
block/dmg.c | 2 +-
17
block/nfs.c | 1 +
13
block/rbd.c | 2 +-
18
block/qcow2.c | 1 +
14
block/vvfat.c | 4 ++--
19
block/qed.c | 1 +
15
include/block/block.h | 1 +
20
block/raw-format.c | 6 ++++++
16
7 files changed, 12 insertions(+), 6 deletions(-)
21
block/rbd.c | 1 +
22
block/sheepdog.c | 1 +
23
block/ssh.c | 1 +
24
10 files changed, 18 insertions(+)
17
25
18
diff --git a/block.c b/block.c
26
diff --git a/block/file-posix.c b/block/file-posix.c
19
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
28
--- a/block/file-posix.c
21
+++ b/block.c
29
+++ b/block/file-posix.c
22
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
30
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
23
}
31
.bdrv_co_create = raw_co_create,
32
.bdrv_co_create_opts = raw_co_create_opts,
33
.bdrv_has_zero_init = bdrv_has_zero_init_1,
34
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
35
.bdrv_co_block_status = raw_co_block_status,
36
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
37
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
38
diff --git a/block/file-win32.c b/block/file-win32.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/file-win32.c
41
+++ b/block/file-win32.c
42
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
43
.bdrv_close = raw_close,
44
.bdrv_co_create_opts = raw_co_create_opts,
45
.bdrv_has_zero_init = bdrv_has_zero_init_1,
46
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
47
48
.bdrv_aio_preadv = raw_aio_preadv,
49
.bdrv_aio_pwritev = raw_aio_pwritev,
50
diff --git a/block/gluster.c b/block/gluster.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/block/gluster.c
53
+++ b/block/gluster.c
54
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
55
.bdrv_co_writev = qemu_gluster_co_writev,
56
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
57
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
58
+ .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
59
#ifdef CONFIG_GLUSTERFS_DISCARD
60
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
61
#endif
62
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
63
.bdrv_co_writev = qemu_gluster_co_writev,
64
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
65
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
66
+ .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
67
#ifdef CONFIG_GLUSTERFS_DISCARD
68
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
69
#endif
70
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
71
.bdrv_co_writev = qemu_gluster_co_writev,
72
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
73
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
74
+ .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
75
#ifdef CONFIG_GLUSTERFS_DISCARD
76
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
77
#endif
78
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
79
.bdrv_co_writev = qemu_gluster_co_writev,
80
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
81
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
82
+ .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
83
#ifdef CONFIG_GLUSTERFS_DISCARD
84
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
85
#endif
86
diff --git a/block/nfs.c b/block/nfs.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/nfs.c
89
+++ b/block/nfs.c
90
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
91
.create_opts = &nfs_create_opts,
92
93
.bdrv_has_zero_init = nfs_has_zero_init,
94
+ .bdrv_has_zero_init_truncate = nfs_has_zero_init,
95
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
96
.bdrv_co_truncate = nfs_file_co_truncate,
97
98
diff --git a/block/qcow2.c b/block/qcow2.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/qcow2.c
101
+++ b/block/qcow2.c
102
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
103
.bdrv_co_create_opts = qcow2_co_create_opts,
104
.bdrv_co_create = qcow2_co_create,
105
.bdrv_has_zero_init = bdrv_has_zero_init_1,
106
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
107
.bdrv_co_block_status = qcow2_co_block_status,
108
109
.bdrv_co_preadv = qcow2_co_preadv,
110
diff --git a/block/qed.c b/block/qed.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/block/qed.c
113
+++ b/block/qed.c
114
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
115
.bdrv_co_create = bdrv_qed_co_create,
116
.bdrv_co_create_opts = bdrv_qed_co_create_opts,
117
.bdrv_has_zero_init = bdrv_has_zero_init_1,
118
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
119
.bdrv_co_block_status = bdrv_qed_co_block_status,
120
.bdrv_co_readv = bdrv_qed_co_readv,
121
.bdrv_co_writev = bdrv_qed_co_writev,
122
diff --git a/block/raw-format.c b/block/raw-format.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/block/raw-format.c
125
+++ b/block/raw-format.c
126
@@ -XXX,XX +XXX,XX @@ static int raw_has_zero_init(BlockDriverState *bs)
127
return bdrv_has_zero_init(bs->file->bs);
24
}
128
}
25
129
26
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
130
+static int raw_has_zero_init_truncate(BlockDriverState *bs)
27
+{
131
+{
28
+ bs->read_only = read_only;
132
+ return bdrv_has_zero_init_truncate(bs->file->bs);
29
+}
133
+}
30
+
134
+
31
void bdrv_get_full_backing_filename_from_filename(const char *backed,
135
static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
32
const char *backing,
136
Error **errp)
33
char *dest, size_t sz,
137
{
34
diff --git a/block/bochs.c b/block/bochs.c
138
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
35
index XXXXXXX..XXXXXXX 100644
139
.bdrv_co_ioctl = &raw_co_ioctl,
36
--- a/block/bochs.c
140
.create_opts = &raw_create_opts,
37
+++ b/block/bochs.c
141
.bdrv_has_zero_init = &raw_has_zero_init,
38
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
142
+ .bdrv_has_zero_init_truncate = &raw_has_zero_init_truncate,
39
return -EINVAL;
143
.strong_runtime_opts = raw_strong_runtime_opts,
40
}
144
.mutable_opts = mutable_opts,
41
145
};
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
146
diff --git a/block/rbd.c b/block/rbd.c
74
index XXXXXXX..XXXXXXX 100644
147
index XXXXXXX..XXXXXXX 100644
75
--- a/block/rbd.c
148
--- a/block/rbd.c
76
+++ b/block/rbd.c
149
+++ b/block/rbd.c
77
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
150
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
78
goto failed_open;
151
.bdrv_co_create = qemu_rbd_co_create,
79
}
152
.bdrv_co_create_opts = qemu_rbd_co_create_opts,
80
153
.bdrv_has_zero_init = bdrv_has_zero_init_1,
81
- bs->read_only = (s->snap != NULL);
154
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
82
+ bdrv_set_read_only(bs, (s->snap != NULL));
155
.bdrv_get_info = qemu_rbd_getinfo,
83
156
.create_opts = &qemu_rbd_create_opts,
84
qemu_opts_del(opts);
157
.bdrv_getlength = qemu_rbd_getlength,
85
return 0;
158
diff --git a/block/sheepdog.c b/block/sheepdog.c
86
diff --git a/block/vvfat.c b/block/vvfat.c
87
index XXXXXXX..XXXXXXX 100644
159
index XXXXXXX..XXXXXXX 100644
88
--- a/block/vvfat.c
160
--- a/block/sheepdog.c
89
+++ b/block/vvfat.c
161
+++ b/block/sheepdog.c
90
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
162
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
91
s->current_cluster=0xffffffff;
163
.bdrv_co_create = sd_co_create,
92
164
.bdrv_co_create_opts = sd_co_create_opts,
93
/* read only is the default for safety */
165
.bdrv_has_zero_init = bdrv_has_zero_init_1,
94
- bs->read_only = true;
166
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
95
+ bdrv_set_read_only(bs, true);
167
.bdrv_getlength = sd_getlength,
96
s->qcow = NULL;
168
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
97
s->qcow_filename = NULL;
169
.bdrv_co_truncate = sd_co_truncate,
98
s->fat2 = NULL;
170
diff --git a/block/ssh.c b/block/ssh.c
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
171
index XXXXXXX..XXXXXXX 100644
110
--- a/include/block/block.h
172
--- a/block/ssh.c
111
+++ b/include/block/block.h
173
+++ b/block/ssh.c
112
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
174
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
113
int64_t sector_num, int nb_sectors, int *pnum);
175
.bdrv_co_create_opts = ssh_co_create_opts,
114
176
.bdrv_close = ssh_close,
115
bool bdrv_is_read_only(BlockDriverState *bs);
177
.bdrv_has_zero_init = ssh_has_zero_init,
116
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only);
178
+ .bdrv_has_zero_init_truncate = ssh_has_zero_init,
117
bool bdrv_is_sg(BlockDriverState *bs);
179
.bdrv_co_readv = ssh_co_readv,
118
bool bdrv_is_inserted(BlockDriverState *bs);
180
.bdrv_co_writev = ssh_co_writev,
119
int bdrv_media_changed(BlockDriverState *bs);
181
.bdrv_getlength = ssh_getlength,
120
--
182
--
121
2.9.3
183
2.21.0
122
184
123
185
diff view generated by jsdifflib
1
Signed-off-by: Jeff Cody <jcody@redhat.com>
1
vhdx and parallels call bdrv_has_zero_init() when they do not really
2
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2
care about an image's post-create state but only about what happens when
3
Reviewed-by: John Snow <jsnow@redhat.com>
3
you grow an image. That is a bit ugly, and also overly safe when
4
Message-id: 00aed7ffdd7be4b9ed9ce1007d50028a72b34ebe.1491597120.git.jcody@redhat.com
4
growing preallocated images without preallocating the new areas.
5
6
Let them use bdrv_has_zero_init_truncate() instead.
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20190724171239.8764-6-mreitz@redhat.com
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
11
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
12
[mreitz: Added commit message]
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
14
---
6
block.c | 14 ++++++++------
15
block/parallels.c | 2 +-
7
1 file changed, 8 insertions(+), 6 deletions(-)
16
block/vhdx.c | 2 +-
17
2 files changed, 2 insertions(+), 2 deletions(-)
8
18
9
diff --git a/block.c b/block.c
19
diff --git a/block/parallels.c b/block/parallels.c
10
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
11
--- a/block.c
21
--- a/block/parallels.c
12
+++ b/block.c
22
+++ b/block/parallels.c
13
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
23
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
14
BlockDriver *drv;
24
goto fail_options;
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
}
25
}
24
26
25
- /* if we are to stay read-only, do not allow permission change
27
- if (!bdrv_has_zero_init(bs->file->bs)) {
26
- * to r/w */
28
+ if (!bdrv_has_zero_init_truncate(bs->file->bs)) {
27
- if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) &&
29
s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
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
}
30
}
40
31
32
diff --git a/block/vhdx.c b/block/vhdx.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/vhdx.c
35
+++ b/block/vhdx.c
36
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
37
/* Queue another write of zero buffers if the underlying file
38
* does not zero-fill on file extension */
39
40
- if (bdrv_has_zero_init(bs->file->bs) == 0) {
41
+ if (bdrv_has_zero_init_truncate(bs->file->bs) == 0) {
42
use_zero_buffers = true;
43
44
/* zero fill the front, if any */
41
--
45
--
42
2.9.3
46
2.21.0
43
47
44
48
diff view generated by jsdifflib
1
This adds support for reopen in rbd, for changing between r/w and r/o.
1
If a qcow2 file is preallocated, it can no longer guarantee that it
2
initially appears as filled with zeroes.
2
3
3
Note, that this is only a flag change, but we will block a change from
4
So implement .bdrv_has_zero_init() by checking whether the file is
4
r/o to r/w if we are using an RBD internal snapshot.
5
preallocated; if so, forward the call to the underlying storage node,
6
except for when it is encrypted: Encrypted preallocated images always
7
return effectively random data, so .bdrv_has_zero_init() must always
8
return 0 for them.
5
9
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
.bdrv_has_zero_init_truncate() can remain bdrv_has_zero_init_1(),
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
11
because it presupposes PREALLOC_MODE_OFF.
8
Reviewed-by: John Snow <jsnow@redhat.com>
12
9
Message-id: d4e87539167ec6527d44c97b164eabcccf96e4f3.1491597120.git.jcody@redhat.com
13
Reported-by: Stefano Garzarella <sgarzare@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Message-id: 20190724171239.8764-7-mreitz@redhat.com
16
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
18
---
11
block/rbd.c | 21 +++++++++++++++++++++
19
block/qcow2.c | 29 ++++++++++++++++++++++++++++-
12
1 file changed, 21 insertions(+)
20
1 file changed, 28 insertions(+), 1 deletion(-)
13
21
14
diff --git a/block/rbd.c b/block/rbd.c
22
diff --git a/block/qcow2.c b/block/qcow2.c
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/block/rbd.c
24
--- a/block/qcow2.c
17
+++ b/block/rbd.c
25
+++ b/block/qcow2.c
18
@@ -XXX,XX +XXX,XX @@ failed_opts:
26
@@ -XXX,XX +XXX,XX @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
19
return r;
27
return spec_info;
20
}
28
}
21
29
30
+static int qcow2_has_zero_init(BlockDriverState *bs)
31
+{
32
+ BDRVQcow2State *s = bs->opaque;
33
+ bool preallocated;
22
+
34
+
23
+/* Since RBD is currently always opened R/W via the API,
35
+ if (qemu_in_coroutine()) {
24
+ * we just need to check if we are using a snapshot or not, in
36
+ qemu_co_mutex_lock(&s->lock);
25
+ * order to determine if we will allow it to be R/W */
37
+ }
26
+static int qemu_rbd_reopen_prepare(BDRVReopenState *state,
38
+ /*
27
+ BlockReopenQueue *queue, Error **errp)
39
+ * Check preallocation status: Preallocated images have all L2
28
+{
40
+ * tables allocated, nonpreallocated images have none. It is
29
+ BDRVRBDState *s = state->bs->opaque;
41
+ * therefore enough to check the first one.
30
+ int ret = 0;
42
+ */
31
+
43
+ preallocated = s->l1_size > 0 && s->l1_table[0] != 0;
32
+ if (s->snap && state->flags & BDRV_O_RDWR) {
44
+ if (qemu_in_coroutine()) {
33
+ error_setg(errp,
45
+ qemu_co_mutex_unlock(&s->lock);
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
+ }
46
+ }
38
+
47
+
39
+ return ret;
48
+ if (!preallocated) {
49
+ return 1;
50
+ } else if (bs->encrypted) {
51
+ return 0;
52
+ } else {
53
+ return bdrv_has_zero_init(s->data_file->bs);
54
+ }
40
+}
55
+}
41
+
56
+
42
static void qemu_rbd_close(BlockDriverState *bs)
57
static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
58
int64_t pos)
43
{
59
{
44
BDRVRBDState *s = bs->opaque;
60
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
45
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
61
.bdrv_child_perm = bdrv_format_default_perms,
46
.bdrv_parse_filename = qemu_rbd_parse_filename,
62
.bdrv_co_create_opts = qcow2_co_create_opts,
47
.bdrv_file_open = qemu_rbd_open,
63
.bdrv_co_create = qcow2_co_create,
48
.bdrv_close = qemu_rbd_close,
64
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
49
+ .bdrv_reopen_prepare = qemu_rbd_reopen_prepare,
65
+ .bdrv_has_zero_init = qcow2_has_zero_init,
50
.bdrv_create = qemu_rbd_create,
66
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
51
.bdrv_has_zero_init = bdrv_has_zero_init_1,
67
.bdrv_co_block_status = qcow2_co_block_status,
52
.bdrv_get_info = qemu_rbd_getinfo,
68
53
--
69
--
54
2.9.3
70
2.21.0
55
71
56
72
diff view generated by jsdifflib
1
Move bdrv_is_read_only() up with its friends.
1
Static VDI images cannot guarantee to be zero-initialized. If the image
2
has been statically allocated, forward the call to the underlying
3
storage node.
2
4
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reported-by: Stefano Garzarella <sgarzare@redhat.com>
4
Reviewed-by: John Snow <jsnow@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
7
Reviewed-by: Stefan Weil <sw@weilnetz.de>
6
Message-id: 73b2399459760c32506f9407efb9dddb3a2789de.1491597120.git.jcody@redhat.com
8
Acked-by: Stefano Garzarella <sgarzare@redhat.com>
9
Tested-by: Stefano Garzarella <sgarzare@redhat.com>
10
Message-id: 20190724171239.8764-8-mreitz@redhat.com
11
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
13
---
8
block.c | 10 +++++-----
14
block/vdi.c | 13 ++++++++++++-
9
1 file changed, 5 insertions(+), 5 deletions(-)
15
1 file changed, 12 insertions(+), 1 deletion(-)
10
16
11
diff --git a/block.c b/block.c
17
diff --git a/block/vdi.c b/block/vdi.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
19
--- a/block/vdi.c
14
+++ b/block.c
20
+++ b/block/vdi.c
15
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
21
@@ -XXX,XX +XXX,XX @@ static void vdi_close(BlockDriverState *bs)
16
}
22
error_free(s->migration_blocker);
17
}
23
}
18
24
19
+bool bdrv_is_read_only(BlockDriverState *bs)
25
+static int vdi_has_zero_init(BlockDriverState *bs)
20
+{
26
+{
21
+ return bs->read_only;
27
+ BDRVVdiState *s = bs->opaque;
28
+
29
+ if (s->header.image_type == VDI_TYPE_STATIC) {
30
+ return bdrv_has_zero_init(bs->file->bs);
31
+ } else {
32
+ return 1;
33
+ }
22
+}
34
+}
23
+
35
+
24
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
36
static QemuOptsList vdi_create_opts = {
25
{
37
.name = "vdi-create-opts",
26
/* Do not set read_only if copy_on_read is enabled */
38
.head = QTAILQ_HEAD_INITIALIZER(vdi_create_opts.head),
27
@@ -XXX,XX +XXX,XX @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
39
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
28
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
40
.bdrv_child_perm = bdrv_format_default_perms,
29
}
41
.bdrv_co_create = vdi_co_create,
30
42
.bdrv_co_create_opts = vdi_co_create_opts,
31
-bool bdrv_is_read_only(BlockDriverState *bs)
43
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
32
-{
44
+ .bdrv_has_zero_init = vdi_has_zero_init,
33
- return bs->read_only;
45
.bdrv_co_block_status = vdi_co_block_status,
34
-}
46
.bdrv_make_empty = vdi_make_empty,
35
-
47
36
bool bdrv_is_sg(BlockDriverState *bs)
37
{
38
return bs->sg;
39
--
48
--
40
2.9.3
49
2.21.0
41
50
42
51
diff view generated by jsdifflib
1
A few block drivers will set the BDS read_only flag from their
1
Fixed VHDX images cannot guarantee to be zero-initialized. If the image
2
.bdrv_open() function. This means the bs->read_only flag could
2
has the "fixed" subformat, forward the call to the underlying storage
3
be set after we enable copy_on_read, as the BDRV_O_COPY_ON_READ
3
node.
4
flag check occurs prior to the call to bdrv->bdrv_open().
5
4
6
This adds an error return to bdrv_set_read_only(), and an error will be
5
Reported-by: Stefano Garzarella <sgarzare@redhat.com>
7
return if we try to set the BDS to read_only while copy_on_read is
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
enabled.
7
Message-id: 20190724171239.8764-9-mreitz@redhat.com
8
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/vhdx.c | 26 +++++++++++++++++++++++++-
12
1 file changed, 25 insertions(+), 1 deletion(-)
9
13
10
This patch also changes the behavior of vvfat. Before, vvfat could
14
diff --git a/block/vhdx.c b/block/vhdx.c
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
15
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
16
--- a/block/vhdx.c
37
+++ b/block.c
17
+++ b/block/vhdx.c
38
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_check(BlockDriverState *bs,
39
}
19
return 0;
40
}
20
}
41
21
42
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
22
+static int vhdx_has_zero_init(BlockDriverState *bs)
43
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
23
+{
44
{
24
+ BDRVVHDXState *s = bs->opaque;
45
+ /* Do not set read_only if copy_on_read is enabled */
25
+ int state;
46
+ if (bs->copy_on_read && read_only) {
26
+
47
+ error_setg(errp, "Can't set node '%s' to r/o with copy-on-read enabled",
27
+ /*
48
+ bdrv_get_device_or_node_name(bs));
28
+ * Check the subformat: Fixed images have all BAT entries present,
49
+ return -EINVAL;
29
+ * dynamic images have none (right after creation). It is
30
+ * therefore enough to check the first BAT entry.
31
+ */
32
+ if (!s->bat_entries) {
33
+ return 1;
50
+ }
34
+ }
51
+
35
+
52
bs->read_only = read_only;
36
+ state = s->bat[0] & VHDX_BAT_STATE_BIT_MASK;
53
+ return 0;
37
+ if (state == PAYLOAD_BLOCK_FULLY_PRESENT) {
54
}
38
+ /* Fixed subformat */
55
39
+ return bdrv_has_zero_init(bs->file->bs);
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
+ }
40
+ }
101
+
41
+
102
block_module_load_one("dmg-bz2");
42
+ /* Dynamic subformat */
103
- bdrv_set_read_only(bs, true);
43
+ return 1;
104
44
+}
105
s->n_chunks = 0;
45
+
106
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
46
static QemuOptsList vhdx_create_opts = {
107
diff --git a/block/rbd.c b/block/rbd.c
47
.name = "vhdx-create-opts",
108
index XXXXXXX..XXXXXXX 100644
48
.head = QTAILQ_HEAD_INITIALIZER(vhdx_create_opts.head),
109
--- a/block/rbd.c
49
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = {
110
+++ b/block/rbd.c
50
.bdrv_co_create_opts = vhdx_co_create_opts,
111
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
51
.bdrv_get_info = vhdx_get_info,
112
goto failed_shutdown;
52
.bdrv_co_check = vhdx_co_check,
113
}
53
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
114
54
+ .bdrv_has_zero_init = vhdx_has_zero_init,
115
+ /* rbd_open is always r/w */
55
116
r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
56
.create_opts = &vhdx_create_opts,
117
if (r < 0) {
57
};
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
--
58
--
189
2.9.3
59
2.21.0
190
60
191
61
diff view generated by jsdifflib
New patch
1
Add a test case for converting an empty image (which only returns zeroes
2
when read) to a preallocated encrypted qcow2 image.
3
qcow2_has_zero_init() should return 0 then, thus forcing qemu-img
4
convert to create zero clusters.
1
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Acked-by: Stefano Garzarella <sgarzare@redhat.com>
8
Tested-by: Stefano Garzarella <sgarzare@redhat.com>
9
Message-id: 20190724171239.8764-10-mreitz@redhat.com
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/188 | 20 +++++++++++++++++++-
14
tests/qemu-iotests/188.out | 4 ++++
15
2 files changed, 23 insertions(+), 1 deletion(-)
16
17
diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/188
20
+++ b/tests/qemu-iotests/188
21
@@ -XXX,XX +XXX,XX @@ SECRETALT="secret,id=sec0,data=platypus"
22
23
_make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10" $size
24
25
-IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0"
26
+IMGSPEC="driver=$IMGFMT,encrypt.key-secret=sec0,file.filename=$TEST_IMG"
27
28
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
29
30
@@ -XXX,XX +XXX,XX @@ echo
31
echo "== verify open failure with wrong password =="
32
$QEMU_IO --object $SECRETALT -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
33
34
+_cleanup_test_img
35
+
36
+echo
37
+echo "== verify that has_zero_init returns false when preallocating =="
38
+
39
+# Empty source file
40
+if [ -n "$TEST_IMG_FILE" ]; then
41
+ TEST_IMG_FILE="${TEST_IMG_FILE}.orig" _make_test_img $size
42
+else
43
+ TEST_IMG="${TEST_IMG}.orig" _make_test_img $size
44
+fi
45
+
46
+$QEMU_IMG convert -O "$IMGFMT" --object $SECRET \
47
+ -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10,preallocation=metadata" \
48
+ "${TEST_IMG}.orig" "$TEST_IMG"
49
+
50
+$QEMU_IMG compare --object $SECRET --image-opts "${IMGSPEC}.orig" "$IMGSPEC"
51
+
52
53
# success, all done
54
echo "*** done"
55
diff --git a/tests/qemu-iotests/188.out b/tests/qemu-iotests/188.out
56
index XXXXXXX..XXXXXXX 100644
57
--- a/tests/qemu-iotests/188.out
58
+++ b/tests/qemu-iotests/188.out
59
@@ -XXX,XX +XXX,XX @@ read 16777216/16777216 bytes at offset 0
60
61
== verify open failure with wrong password ==
62
qemu-io: can't open: Invalid password, cannot unlock any keyslot
63
+
64
+== verify that has_zero_init returns false when preallocating ==
65
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=16777216
66
+Images are identical.
67
*** done
68
--
69
2.21.0
70
71
diff view generated by jsdifflib
1
For the tests that use the common.qemu functions for running a QEMU
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
2
process, _cleanup_qemu must be called in the exit function.
2
Message-id: 20190724171239.8764-11-mreitz@redhat.com
3
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
6
tests/qemu-iotests/122 | 17 +++++++++++++++++
7
tests/qemu-iotests/122.out | 8 ++++++++
8
2 files changed, 25 insertions(+)
3
9
4
If it is not, if the qemu process aborts, then not all of the droppings
10
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
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
11
index XXXXXXX..XXXXXXX 100755
30
--- a/tests/qemu-iotests/028
12
--- a/tests/qemu-iotests/122
31
+++ b/tests/qemu-iotests/028
13
+++ b/tests/qemu-iotests/122
32
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
14
@@ -XXX,XX +XXX,XX @@ for min_sparse in 4k 8k; do
33
15
$QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map
34
_cleanup()
16
done
35
{
17
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
+
18
+
56
+trap "_cleanup; exit \$status" 0 1 2 3 15
19
+echo
57
20
+echo '=== -n to a non-zero image ==='
58
# get standard environment, filters and checks
21
+echo
59
. ./common.rc
22
+
60
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE \
23
+# Keep source zero
61
24
+_make_test_img 64M
62
wait=1 _cleanup_qemu
25
+
63
26
+# Output is not zero, but has bdrv_has_zero_init() == 1
64
-_cleanup_test_img
27
+TEST_IMG="$TEST_IMG".orig _make_test_img 64M
65
-rm -f "$TEST_DIR/source.$IMGFMT"
28
+$QEMU_IO -c "write -P 42 0 64k" "$TEST_IMG".orig | _filter_qemu_io
66
29
+
30
+# Convert with -n, which should not assume that the target is zeroed
31
+$QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG".orig
32
+
33
+$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG".orig
34
+
67
# success, all done
35
# success, all done
68
echo '*** done'
36
echo '*** done'
69
diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102
37
rm -f $seq.full
70
index XXXXXXX..XXXXXXX 100755
38
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
71
--- a/tests/qemu-iotests/102
39
index XXXXXXX..XXXXXXX 100644
72
+++ b/tests/qemu-iotests/102
40
--- a/tests/qemu-iotests/122.out
73
@@ -XXX,XX +XXX,XX @@ seq=$(basename $0)
41
+++ b/tests/qemu-iotests/122.out
74
echo "QA output created by $seq"
42
@@ -XXX,XX +XXX,XX @@ convert -c -S 8k
75
43
{ "start": 9216, "length": 8192, "depth": 0, "zero": true, "data": false},
76
here=$PWD
44
{ "start": 17408, "length": 1024, "depth": 0, "zero": false, "data": true},
77
-status=1    # failure is the default!
45
{ "start": 18432, "length": 67090432, "depth": 0, "zero": true, "data": false}]
78
+status=1 # failure is the default!
46
+
79
47
+=== -n to a non-zero image ===
80
_cleanup()
48
+
81
{
49
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
82
-    _cleanup_test_img
50
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864
83
+ _cleanup_qemu
51
+wrote 65536/65536 bytes at offset 0
84
+ _cleanup_test_img
52
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
85
}
53
+Images are identical.
86
trap "_cleanup; exit \$status" 0 1 2 3 15
54
*** done
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
--
55
--
173
2.9.3
56
2.21.0
174
57
175
58
diff view generated by jsdifflib
New patch
1
The result of a sync=full mirror should always be the equal to the
2
input. Therefore, existing images should be treated as potentially
3
non-zero and thus should be explicitly initialized to be zero
4
beforehand.
1
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20190724171239.8764-12-mreitz@redhat.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/041 | 62 +++++++++++++++++++++++++++++++++++---
11
tests/qemu-iotests/041.out | 4 +--
12
2 files changed, 60 insertions(+), 6 deletions(-)
13
14
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/041
17
+++ b/tests/qemu-iotests/041
18
@@ -XXX,XX +XXX,XX @@ class TestUnbackedSource(iotests.QMPTestCase):
19
def setUp(self):
20
qemu_img('create', '-f', iotests.imgfmt, test_img,
21
str(TestUnbackedSource.image_len))
22
- self.vm = iotests.VM().add_drive(test_img)
23
+ self.vm = iotests.VM()
24
self.vm.launch()
25
+ result = self.vm.qmp('blockdev-add', node_name='drive0',
26
+ driver=iotests.imgfmt,
27
+ file={
28
+ 'driver': 'file',
29
+ 'filename': test_img,
30
+ })
31
+ self.assert_qmp(result, 'return', {})
32
33
def tearDown(self):
34
self.vm.shutdown()
35
@@ -XXX,XX +XXX,XX @@ class TestUnbackedSource(iotests.QMPTestCase):
36
37
def test_absolute_paths_full(self):
38
self.assert_no_active_block_jobs()
39
- result = self.vm.qmp('drive-mirror', device='drive0',
40
+ result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
41
sync='full', target=target_img,
42
mode='absolute-paths')
43
self.assert_qmp(result, 'return', {})
44
@@ -XXX,XX +XXX,XX @@ class TestUnbackedSource(iotests.QMPTestCase):
45
46
def test_absolute_paths_top(self):
47
self.assert_no_active_block_jobs()
48
- result = self.vm.qmp('drive-mirror', device='drive0',
49
+ result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
50
sync='top', target=target_img,
51
mode='absolute-paths')
52
self.assert_qmp(result, 'return', {})
53
@@ -XXX,XX +XXX,XX @@ class TestUnbackedSource(iotests.QMPTestCase):
54
55
def test_absolute_paths_none(self):
56
self.assert_no_active_block_jobs()
57
- result = self.vm.qmp('drive-mirror', device='drive0',
58
+ result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
59
sync='none', target=target_img,
60
mode='absolute-paths')
61
self.assert_qmp(result, 'return', {})
62
self.complete_and_wait()
63
self.assert_no_active_block_jobs()
64
65
+ def test_existing_full(self):
66
+ qemu_img('create', '-f', iotests.imgfmt, target_img,
67
+ str(self.image_len))
68
+ qemu_io('-c', 'write -P 42 0 64k', target_img)
69
+
70
+ self.assert_no_active_block_jobs()
71
+ result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
72
+ sync='full', target=target_img, mode='existing')
73
+ self.assert_qmp(result, 'return', {})
74
+ self.complete_and_wait()
75
+ self.assert_no_active_block_jobs()
76
+
77
+ result = self.vm.qmp('blockdev-del', node_name='drive0')
78
+ self.assert_qmp(result, 'return', {})
79
+
80
+ self.assertTrue(iotests.compare_images(test_img, target_img),
81
+ 'target image does not match source after mirroring')
82
+
83
+ def test_blockdev_full(self):
84
+ qemu_img('create', '-f', iotests.imgfmt, target_img,
85
+ str(self.image_len))
86
+ qemu_io('-c', 'write -P 42 0 64k', target_img)
87
+
88
+ result = self.vm.qmp('blockdev-add', node_name='target',
89
+ driver=iotests.imgfmt,
90
+ file={
91
+ 'driver': 'file',
92
+ 'filename': target_img,
93
+ })
94
+ self.assert_qmp(result, 'return', {})
95
+
96
+ self.assert_no_active_block_jobs()
97
+ result = self.vm.qmp('blockdev-mirror', job_id='drive0', device='drive0',
98
+ sync='full', target='target')
99
+ self.assert_qmp(result, 'return', {})
100
+ self.complete_and_wait()
101
+ self.assert_no_active_block_jobs()
102
+
103
+ result = self.vm.qmp('blockdev-del', node_name='drive0')
104
+ self.assert_qmp(result, 'return', {})
105
+
106
+ result = self.vm.qmp('blockdev-del', node_name='target')
107
+ self.assert_qmp(result, 'return', {})
108
+
109
+ self.assertTrue(iotests.compare_images(test_img, target_img),
110
+ 'target image does not match source after mirroring')
111
+
112
class TestGranularity(iotests.QMPTestCase):
113
image_len = 10 * 1024 * 1024 # MB
114
115
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
116
index XXXXXXX..XXXXXXX 100644
117
--- a/tests/qemu-iotests/041.out
118
+++ b/tests/qemu-iotests/041.out
119
@@ -XXX,XX +XXX,XX @@
120
-........................................................................................
121
+..........................................................................................
122
----------------------------------------------------------------------
123
-Ran 88 tests
124
+Ran 90 tests
125
126
OK
127
--
128
2.21.0
129
130
diff view generated by jsdifflib
1
Update 'clientname' to be 'user', which tracks better with both
1
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
the QAPI and rados variable naming.
2
Fixes: 69f47505ee66afaa513305de0c1895a224e52c45
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Message-id: 20190725155512.9827-2-mreitz@redhat.com
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: John Snow <jsnow@redhat.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
block/vdi.c | 3 ++-
10
1 file changed, 2 insertions(+), 1 deletion(-)
3
11
4
Update 'name' to be 'image_name', as it indicates the rbd image.
12
diff --git a/block/vdi.c b/block/vdi.c
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
13
index XXXXXXX..XXXXXXX 100644
18
--- a/block/rbd.c
14
--- a/block/vdi.c
19
+++ b/block/rbd.c
15
+++ b/block/vdi.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRBDState {
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_block_status(BlockDriverState *bs,
21
rados_t cluster;
17
*map = s->header.offset_data + (uint64_t)bmap_entry * s->block_size +
22
rados_ioctx_t io_ctx;
18
index_in_block;
23
rbd_image_t image;
19
*file = bs->file->bs;
24
- char *name;
20
- return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
25
+ char *image_name;
21
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID |
26
char *snap;
22
+ (s->header.image_type == VDI_TYPE_STATIC ? BDRV_BLOCK_RECURSE : 0);
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
}
23
}
131
24
25
static int coroutine_fn
132
--
26
--
133
2.9.3
27
2.21.0
134
28
135
29
diff view generated by jsdifflib
New patch
1
Fixes: 69f47505ee66afaa513305de0c1895a224e52c45
2
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Message-id: 20190725155512.9827-3-mreitz@redhat.com
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
block/vmdk.c | 3 +++
9
1 file changed, 3 insertions(+)
1
10
11
diff --git a/block/vmdk.c b/block/vmdk.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/vmdk.c
14
+++ b/block/vmdk.c
15
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
16
if (!extent->compressed) {
17
ret |= BDRV_BLOCK_OFFSET_VALID;
18
*map = cluster_offset + index_in_cluster;
19
+ if (extent->flat) {
20
+ ret |= BDRV_BLOCK_RECURSE;
21
+ }
22
}
23
*file = extent->file->bs;
24
break;
25
--
26
2.21.0
27
28
diff view generated by jsdifflib
1
The BDRV_O_ALLOW_RDWR flag allows / prohibits the changing of
1
vpc is not really a passthrough driver, even when using the fixed
2
the BDS 'read_only' state, but there are a few places where it
2
subformat (where host and guest offsets are equal). It should handle
3
is ignored. In the bdrv_set_read_only() helper, make sure to
3
preallocation like all other drivers do, namely by returning
4
honor the flag.
4
DATA | RECURSE instead of RAW.
5
5
6
Signed-off-by: Jeff Cody <jcody@redhat.com>
6
There is no tangible difference but the fact that bdrv_is_allocated() no
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
longer falls through to the protocol layer.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 20190725155512.9827-4-mreitz@redhat.com
8
Reviewed-by: John Snow <jsnow@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-id: be2e5fb2d285cbece2b6d06bed54a6f56520d251.1491597120.git.jcody@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
13
---
11
block.c | 7 +++++++
14
block/vpc.c | 2 +-
12
1 file changed, 7 insertions(+)
15
1 file changed, 1 insertion(+), 1 deletion(-)
13
16
14
diff --git a/block.c b/block.c
17
diff --git a/block/vpc.c b/block/vpc.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/block.c
19
--- a/block/vpc.c
17
+++ b/block.c
20
+++ b/block/vpc.c
18
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
21
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vpc_co_block_status(BlockDriverState *bs,
19
return -EINVAL;
22
*pnum = bytes;
23
*map = offset;
24
*file = bs->file->bs;
25
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
26
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_RECURSE;
20
}
27
}
21
28
22
+ /* Do not clear read_only if it is prohibited */
29
qemu_co_mutex_lock(&s->lock);
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
--
30
--
33
2.9.3
31
2.21.0
34
32
35
33
diff view generated by jsdifflib
1
From: Ashish Mittal <ashmit602@gmail.com>
1
69f47505ee has changed qcow2 in such a way that the commit job run in
2
test 141 (and 144[1]) returns before it emits the READY event. However,
3
141 also runs with qed, where the order is still the other way around.
4
Just filter out the {"return": {}} so the test passes for qed again.
2
5
3
These changes use a vxhs test server that is a part of the following
6
[1] 144 only runs with qcow2, so it is fine as it is.
4
repository:
5
https://github.com/VeritasHyperScale/libqnio.git
6
7
7
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
8
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Fixes: 69f47505ee66afaa513305de0c1895a224e52c45
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Jeff Cody <jcody@redhat.com>
11
Message-id: 20190809185253.17535-1-mreitz@redhat.com
11
Message-id: 1491277689-24949-3-git-send-email-Ashish.Mittal@veritas.com
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: John Snow <jsnow@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
15
---
13
tests/qemu-iotests/common | 6 ++++++
16
tests/qemu-iotests/141 | 9 +++++++--
14
tests/qemu-iotests/common.config | 13 +++++++++++++
17
tests/qemu-iotests/141.out | 5 -----
15
tests/qemu-iotests/common.filter | 1 +
18
tests/qemu-iotests/common.filter | 5 +++++
16
tests/qemu-iotests/common.rc | 19 +++++++++++++++++++
19
3 files changed, 12 insertions(+), 7 deletions(-)
17
4 files changed, 39 insertions(+)
18
20
19
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
21
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
22
index XXXXXXX..XXXXXXX 100755
23
--- a/tests/qemu-iotests/141
24
+++ b/tests/qemu-iotests/141
25
@@ -XXX,XX +XXX,XX @@ test_blockjob()
26
}}}" \
27
'return'
28
29
+ # If "$2" is an event, we may or may not see it before the
30
+ # {"return": {}}. Therefore, filter the {"return": {}} out both
31
+ # here and in the next command. (Naturally, if we do not see it
32
+ # here, we will see it before the next command can be executed,
33
+ # so it will appear in the next _send_qemu_cmd's output.)
34
_send_qemu_cmd $QEMU_HANDLE \
35
"$1" \
36
"$2" \
37
- | _filter_img_create
38
+ | _filter_img_create | _filter_qmp_empty_return
39
40
# We want this to return an error because the block job is still running
41
_send_qemu_cmd $QEMU_HANDLE \
42
"{'execute': 'blockdev-del',
43
'arguments': {'node-name': 'drv0'}}" \
44
- 'error' | _filter_generated_node_ids
45
+ 'error' | _filter_generated_node_ids | _filter_qmp_empty_return
46
47
_send_qemu_cmd $QEMU_HANDLE \
48
"{'execute': 'block-job-cancel',
49
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
20
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/common
51
--- a/tests/qemu-iotests/141.out
22
+++ b/tests/qemu-iotests/common
52
+++ b/tests/qemu-iotests/141.out
23
@@ -XXX,XX +XXX,XX @@ check options
53
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.
24
-ssh test ssh
54
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
25
-nfs test nfs
55
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
26
-luks test luks
56
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
27
+ -vxhs test vxhs
57
-{"return": {}}
28
-xdiff graphical mode diff
58
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
29
-nocache use O_DIRECT on backing file
59
{"return": {}}
30
-misalign misalign memory allocations
60
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
31
@@ -XXX,XX +XXX,XX @@ testlist options
61
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
32
xpand=false
62
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
33
;;
63
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
34
64
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
35
+ -vxhs)
65
-{"return": {}}
36
+ IMGPROTO=vxhs
66
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
37
+ xpand=false
67
{"return": {}}
38
+ ;;
68
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
39
+
69
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
40
-ssh)
70
{"return": {}}
41
IMGPROTO=ssh
71
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
42
xpand=false
72
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
43
diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
73
-{"return": {}}
44
index XXXXXXX..XXXXXXX 100644
74
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
45
--- a/tests/qemu-iotests/common.config
75
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
46
+++ b/tests/qemu-iotests/common.config
76
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
47
@@ -XXX,XX +XXX,XX @@ if [ -z "$QEMU_NBD_PROG" ]; then
77
@@ -XXX,XX +XXX,XX @@ wrote 1048576/1048576 bytes at offset 0
48
export QEMU_NBD_PROG="`set_prog_path qemu-nbd`"
78
{"return": {}}
49
fi
79
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
50
80
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
51
+if [ -z "$QEMU_VXHS_PROG" ]; then
81
-{"return": {}}
52
+ export QEMU_VXHS_PROG="`set_prog_path qnio_server`"
82
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
53
+fi
83
{"return": {}}
54
+
84
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
55
_qemu_wrapper()
85
@@ -XXX,XX +XXX,XX @@ wrote 1048576/1048576 bytes at offset 0
56
{
86
{"return": {}}
57
(
87
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
58
@@ -XXX,XX +XXX,XX @@ _qemu_nbd_wrapper()
88
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
59
)
89
-{"return": {}}
60
}
90
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
61
91
{"return": {}}
62
+_qemu_vxhs_wrapper()
92
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
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
93
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
79
index XXXXXXX..XXXXXXX 100644
94
index XXXXXXX..XXXXXXX 100644
80
--- a/tests/qemu-iotests/common.filter
95
--- a/tests/qemu-iotests/common.filter
81
+++ b/tests/qemu-iotests/common.filter
96
+++ b/tests/qemu-iotests/common.filter
82
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
97
@@ -XXX,XX +XXX,XX @@ _filter_nbd()
83
-e "s#$TEST_DIR#TEST_DIR#g" \
98
-e 's#\(foo\|PORT/\?\|.sock\): Failed to .*$#\1#'
84
-e "s#$IMGFMT#IMGFMT#g" \
99
}
85
-e 's#nbd://127.0.0.1:10810$#TEST_DIR/t.IMGFMT#g' \
100
86
+ -e 's#json.*vdisk-id.*vxhs"}}#TEST_DIR/t.IMGFMT#' \
101
+_filter_qmp_empty_return()
87
-e "/encrypted: yes/d" \
102
+{
88
-e "/cluster_size: [0-9]\\+/d" \
103
+ grep -v '{"return": {}}'
89
-e "/table_size: [0-9]\\+/d" \
104
+}
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
+
105
+
109
+ # Start QNIO server on image directory for vxhs protocol
106
# make sure this script returns success
110
+ if [ $IMGPROTO = "vxhs" ]; then
107
true
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
--
108
--
135
2.9.3
109
2.21.0
136
110
137
111
diff view generated by jsdifflib
1
The protocol VXHS does not support image creation. Some tests expect
1
When preallocating an encrypted qcow2 image, it just lets the protocol
2
to be able to create images through the protocol. Exclude VXHS from
2
driver write data and then does not mark the clusters as zero.
3
these tests.
3
Therefore, reading this image will yield effectively random data.
4
4
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
5
As such, we have not fulfilled the promise of always writing zeroes when
6
preallocating an image in a while. It seems that nobody has really
7
cared, so change the documentation to conform to qemu's actual behavior.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 20190711132935.13070-1-mreitz@redhat.com
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
13
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
---
15
---
7
tests/qemu-iotests/017 | 1 +
16
qapi/block-core.json | 9 +++++----
8
tests/qemu-iotests/020 | 1 +
17
docs/qemu-block-drivers.texi | 4 ++--
9
tests/qemu-iotests/029 | 1 +
18
qemu-img.texi | 4 ++--
10
tests/qemu-iotests/073 | 1 +
19
3 files changed, 9 insertions(+), 8 deletions(-)
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
20
18
diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017
21
diff --git a/qapi/block-core.json b/qapi/block-core.json
19
index XXXXXXX..XXXXXXX 100755
22
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/017
23
--- a/qapi/block-core.json
21
+++ b/tests/qemu-iotests/017
24
+++ b/qapi/block-core.json
22
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
25
@@ -XXX,XX +XXX,XX @@
23
# Any format supporting backing files
26
# @off: no preallocation
24
_supported_fmt qcow qcow2 vmdk qed
27
# @metadata: preallocate only for metadata
25
_supported_proto generic
28
# @falloc: like @full preallocation but allocate disk space by
26
+_unsupported_proto vxhs
29
-# posix_fallocate() rather than writing zeros.
27
_supported_os Linux
30
-# @full: preallocate all data by writing zeros to device to ensure disk
28
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
31
-# space is really available. @full preallocation also sets up
29
32
-# metadata correctly.
30
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
33
+# posix_fallocate() rather than writing data.
31
index XXXXXXX..XXXXXXX 100755
34
+# @full: preallocate all data by writing it to the device to ensure
32
--- a/tests/qemu-iotests/020
35
+# disk space is really available. This data may or may not be
33
+++ b/tests/qemu-iotests/020
36
+# zero, depending on the image format and storage.
34
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
37
+# @full preallocation also sets up metadata correctly.
35
# Any format supporting backing files
38
#
36
_supported_fmt qcow qcow2 vmdk qed
39
# Since: 2.2
37
_supported_proto generic
40
##
38
+_unsupported_proto vxhs
41
diff --git a/docs/qemu-block-drivers.texi b/docs/qemu-block-drivers.texi
39
_supported_os Linux
42
index XXXXXXX..XXXXXXX 100644
40
_unsupported_imgopts "subformat=monolithicFlat" \
43
--- a/docs/qemu-block-drivers.texi
41
"subformat=twoGbMaxExtentFlat" \
44
+++ b/docs/qemu-block-drivers.texi
42
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
45
@@ -XXX,XX +XXX,XX @@ Supported options:
43
index XXXXXXX..XXXXXXX 100755
46
@item preallocation
44
--- a/tests/qemu-iotests/029
47
Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}).
45
+++ b/tests/qemu-iotests/029
48
@code{falloc} mode preallocates space for image by calling posix_fallocate().
46
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
49
-@code{full} mode preallocates space for image by writing zeros to underlying
47
# Any format supporting intenal snapshots
50
-storage.
48
_supported_fmt qcow2
51
+@code{full} mode preallocates space for image by writing data to underlying
49
_supported_proto generic
52
+storage. This data may or may not be zero, depending on the storage location.
50
+_unsupported_proto vxhs
53
@end table
51
_supported_os Linux
54
52
# Internal snapshots are (currently) impossible with refcount_bits=1
55
@item qcow2
53
_unsupported_imgopts 'refcount_bits=1[^0-9]'
56
diff --git a/qemu-img.texi b/qemu-img.texi
54
diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073
57
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100755
58
--- a/qemu-img.texi
56
--- a/tests/qemu-iotests/073
59
+++ b/qemu-img.texi
57
+++ b/tests/qemu-iotests/073
60
@@ -XXX,XX +XXX,XX @@ Supported options:
58
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
61
@item preallocation
59
62
Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}).
60
_supported_fmt qcow2
63
@code{falloc} mode preallocates space for image by calling posix_fallocate().
61
_supported_proto generic
64
-@code{full} mode preallocates space for image by writing zeros to underlying
62
+_unsupported_proto vxhs
65
-storage.
63
_supported_os Linux
66
+@code{full} mode preallocates space for image by writing data to underlying
64
67
+storage. This data may or may not be zero, depending on the storage location.
65
CLUSTER_SIZE=64k
68
@end table
66
diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114
69
67
index XXXXXXX..XXXXXXX 100755
70
@item qcow2
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
--
71
--
127
2.9.3
72
2.21.0
128
73
129
74
diff view generated by jsdifflib