1
The following changes since commit bfec359afba088aaacc7d316f43302f28c6e642a:
1
The following changes since commit dac03af5d5482ec7ee9c23db467bb7230b33c0d9:
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/rth/tags/pull-axp-20190825' into staging (2019-08-27 10:00:51 +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/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 1507631e438930bc07f776f303af127a9cdb4d41:
9
for you to fetch changes up to 5396234b96a2ac743f48644529771498e036e698:
10
10
11
qemu-iotests: _cleanup_qemu must be called on exit (2017-04-21 08:32:44 -0400)
11
block/qcow2: implement .bdrv_co_pwritev(_compressed)_part (2019-08-27 14:58:42 +0100)
12
13
----------------------------------------------------------------
14
Pull request
12
15
13
----------------------------------------------------------------
16
----------------------------------------------------------------
14
17
15
Block patches for 2.10
18
Vladimir Sementsov-Ogievskiy (12):
19
util/iov: introduce qemu_iovec_init_extended
20
util/iov: improve qemu_iovec_is_zero
21
block/io: refactor padding
22
block: define .*_part io handlers in BlockDriver
23
block/io: bdrv_co_do_copy_on_readv: use and support qiov_offset
24
block/io: bdrv_co_do_copy_on_readv: lazy allocation
25
block/io: bdrv_aligned_preadv: use and support qiov_offset
26
block/io: bdrv_aligned_pwritev: use and support qiov_offset
27
block/io: introduce bdrv_co_p{read, write}v_part
28
block/qcow2: refactor qcow2_co_preadv to use buffer-based io
29
block/qcow2: implement .bdrv_co_preadv_part
30
block/qcow2: implement .bdrv_co_pwritev(_compressed)_part
16
31
17
----------------------------------------------------------------
32
block/qcow2.h | 1 +
18
33
include/block/block_int.h | 21 ++
19
Ashish Mittal (2):
34
include/qemu/iov.h | 10 +-
20
block/vxhs.c: Add support for a new block device type called "vxhs"
35
block/backup.c | 2 +-
21
block/vxhs.c: Add qemu-iotests for new block device type "vxhs"
36
block/io.c | 541 +++++++++++++++++++++++---------------
22
37
block/qcow2-cluster.c | 14 +-
23
Jeff Cody (10):
38
block/qcow2.c | 131 +++++----
24
qemu-iotests: exclude vxhs from image creation via protocol
39
qemu-img.c | 4 +-
25
block: add bdrv_set_read_only() helper function
40
util/iov.c | 153 +++++++++--
26
block: do not set BDS read_only if copy_on_read enabled
41
9 files changed, 568 insertions(+), 309 deletions(-)
27
block: honor BDRV_O_ALLOW_RDWR when clearing bs->read_only
28
block: code movement
29
block: introduce bdrv_can_set_read_only()
30
block: use bdrv_can_set_read_only() during reopen
31
block/rbd - update variable names to more apt names
32
block/rbd: Add support for reopen()
33
qemu-iotests: _cleanup_qemu must be called on exit
34
35
block.c | 56 +++-
36
block/Makefile.objs | 2 +
37
block/bochs.c | 5 +-
38
block/cloop.c | 5 +-
39
block/dmg.c | 6 +-
40
block/rbd.c | 65 +++--
41
block/trace-events | 17 ++
42
block/vvfat.c | 19 +-
43
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++
44
configure | 39 +++
45
include/block/block.h | 2 +
46
qapi/block-core.json | 23 +-
47
tests/qemu-iotests/017 | 1 +
48
tests/qemu-iotests/020 | 1 +
49
tests/qemu-iotests/028 | 1 +
50
tests/qemu-iotests/029 | 1 +
51
tests/qemu-iotests/073 | 1 +
52
tests/qemu-iotests/094 | 11 +-
53
tests/qemu-iotests/102 | 5 +-
54
tests/qemu-iotests/109 | 1 +
55
tests/qemu-iotests/114 | 1 +
56
tests/qemu-iotests/117 | 1 +
57
tests/qemu-iotests/130 | 2 +
58
tests/qemu-iotests/134 | 1 +
59
tests/qemu-iotests/140 | 1 +
60
tests/qemu-iotests/141 | 1 +
61
tests/qemu-iotests/143 | 1 +
62
tests/qemu-iotests/156 | 2 +
63
tests/qemu-iotests/158 | 1 +
64
tests/qemu-iotests/common | 6 +
65
tests/qemu-iotests/common.config | 13 +
66
tests/qemu-iotests/common.filter | 1 +
67
tests/qemu-iotests/common.rc | 19 ++
68
33 files changed, 844 insertions(+), 42 deletions(-)
69
create mode 100644 block/vxhs.c
70
42
71
--
43
--
72
2.9.3
44
2.21.0
73
45
74
46
diff view generated by jsdifflib
1
From: Ashish Mittal <ashmit602@gmail.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Source code for the qnio library that this code loads can be downloaded from:
3
Introduce new initialization API, to create requests with padding. Will
4
https://github.com/VeritasHyperScale/libqnio.git
4
be used in the following patch. New API uses qemu_iovec_init_buf if
5
resulting io vector has only one element, to avoid extra allocations.
6
So, we need to update qemu_iovec_destroy to support destroying such
7
QIOVs.
5
8
6
Sample command line using JSON syntax:
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
./x86_64-softmmu/qemu-system-x86_64 -name instance-00000008 -S -vnc 0.0.0.0:0
10
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
8
-k en-us -vga cirrus -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
11
Message-id: 20190604161514.262241-2-vsementsov@virtuozzo.com
9
-msg timestamp=on
12
Message-Id: <20190604161514.262241-2-vsementsov@virtuozzo.com>
10
'json:{"driver":"vxhs","vdisk-id":"c3e9095a-a5ee-4dce-afeb-2a59fb387410",
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
"server":{"host":"172.172.17.4","port":"9999"}}'
14
---
15
include/qemu/iov.h | 7 +++
16
util/iov.c | 112 +++++++++++++++++++++++++++++++++++++++++++--
17
2 files changed, 114 insertions(+), 5 deletions(-)
12
18
13
Sample command line using URI syntax:
19
diff --git a/include/qemu/iov.h b/include/qemu/iov.h
14
qemu-img convert -f raw -O raw -n
15
/var/lib/nova/instances/_base/0c5eacd5ebea5ed914b6a3e7b18f1ce734c386ad
16
vxhs://192.168.0.1:9999/c6718f6b-0401-441d-a8c3-1f0064d75ee0
17
18
Sample command line using TLS credentials (run in secure mode):
19
./qemu-io --object
20
tls-creds-x509,id=tls0,dir=/etc/pki/qemu/vxhs,endpoint=client -c 'read
21
-v 66000 2.5k' 'json:{"server.host": "127.0.0.1", "server.port": "9999",
22
"vdisk-id": "/test.raw", "driver": "vxhs", "tls-creds":"tls0"}'
23
24
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
20
index XXXXXXX..XXXXXXX 100644
40
--- a/block/Makefile.objs
21
--- a/include/qemu/iov.h
41
+++ b/block/Makefile.objs
22
+++ b/include/qemu/iov.h
42
@@ -XXX,XX +XXX,XX @@ block-obj-$(CONFIG_LIBNFS) += nfs.o
23
@@ -XXX,XX +XXX,XX @@ static inline void *qemu_iovec_buf(QEMUIOVector *qiov)
43
block-obj-$(CONFIG_CURL) += curl.o
24
44
block-obj-$(CONFIG_RBD) += rbd.o
25
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
45
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
26
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
46
+block-obj-$(CONFIG_VXHS) += vxhs.o
27
+void qemu_iovec_init_extended(
47
block-obj-$(CONFIG_LIBSSH2) += ssh.o
28
+ QEMUIOVector *qiov,
48
block-obj-y += accounting.o dirty-bitmap.o
29
+ void *head_buf, size_t head_len,
49
block-obj-y += write-threshold.o
30
+ QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len,
50
@@ -XXX,XX +XXX,XX @@ rbd.o-cflags := $(RBD_CFLAGS)
31
+ void *tail_buf, size_t tail_len);
51
rbd.o-libs := $(RBD_LIBS)
32
+void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
52
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
33
+ size_t offset, size_t len);
53
gluster.o-libs := $(GLUSTERFS_LIBS)
34
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
54
+vxhs.o-libs := $(VXHS_LIBS)
35
void qemu_iovec_concat(QEMUIOVector *dst,
55
ssh.o-cflags := $(LIBSSH2_CFLAGS)
36
QEMUIOVector *src, size_t soffset, size_t sbytes);
56
ssh.o-libs := $(LIBSSH2_LIBS)
37
diff --git a/util/iov.c b/util/iov.c
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
38
index XXXXXXX..XXXXXXX 100644
60
--- a/block/trace-events
39
--- a/util/iov.c
61
+++ b/block/trace-events
40
+++ b/util/iov.c
62
@@ -XXX,XX +XXX,XX @@ qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s
41
@@ -XXX,XX +XXX,XX @@ void qemu_iovec_concat(QEMUIOVector *dst,
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
42
qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes);
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
43
}
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"
44
45
+/*
46
+ * qiov_find_iov
47
+ *
48
+ * Return pointer to iovec structure, where byte at @offset in original vector
49
+ * @iov exactly is.
50
+ * Set @remaining_offset to be offset inside that iovec to the same byte.
51
+ */
52
+static struct iovec *iov_skip_offset(struct iovec *iov, size_t offset,
53
+ size_t *remaining_offset)
54
+{
55
+ while (offset > 0 && offset >= iov->iov_len) {
56
+ offset -= iov->iov_len;
57
+ iov++;
58
+ }
59
+ *remaining_offset = offset;
66
+
60
+
67
+# block/vxhs.c
61
+ return iov;
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
+}
62
+}
164
+
63
+
165
+/*
64
+/*
166
+ * Called from a libqnio thread
65
+ * qiov_slice
66
+ *
67
+ * Find subarray of iovec's, containing requested range. @head would
68
+ * be offset in first iov (returned by the function), @tail would be
69
+ * count of extra bytes in last iovec (returned iov + @niov - 1).
167
+ */
70
+ */
168
+static void vxhs_iio_callback(void *ctx, uint32_t opcode, uint32_t error)
71
+static struct iovec *qiov_slice(QEMUIOVector *qiov,
72
+ size_t offset, size_t len,
73
+ size_t *head, size_t *tail, int *niov)
169
+{
74
+{
170
+ VXHSAIOCB *acb = NULL;
75
+ struct iovec *iov, *end_iov;
171
+
76
+
172
+ switch (opcode) {
77
+ assert(offset + len <= qiov->size);
173
+ case IRP_READ_REQUEST:
174
+ case IRP_WRITE_REQUEST:
175
+
78
+
176
+ /*
79
+ iov = iov_skip_offset(qiov->iov, offset, head);
177
+ * ctx is VXHSAIOCB*
80
+ end_iov = iov_skip_offset(iov, *head + len, tail);
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
+
81
+
187
+ if (error) {
82
+ if (*tail > 0) {
188
+ if (!acb->err) {
83
+ assert(*tail < end_iov->iov_len);
189
+ acb->err = error;
84
+ *tail = end_iov->iov_len - *tail;
190
+ }
85
+ end_iov++;
191
+ trace_vxhs_iio_callback(error);
86
+ }
192
+ }
193
+
87
+
194
+ aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
88
+ *niov = end_iov - iov;
195
+ vxhs_complete_aio_bh, acb);
196
+ break;
197
+
89
+
198
+ default:
90
+ return iov;
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
+}
91
+}
213
+
92
+
214
+static QemuOptsList runtime_opts = {
93
+/*
215
+ .name = "vxhs",
94
+ * Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov,
216
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
95
+ * and @tail_buf buffer into new qiov.
217
+ .desc = {
96
+ */
218
+ {
97
+void qemu_iovec_init_extended(
219
+ .name = VXHS_OPT_FILENAME,
98
+ QEMUIOVector *qiov,
220
+ .type = QEMU_OPT_STRING,
99
+ void *head_buf, size_t head_len,
221
+ .help = "URI to the Veritas HyperScale image",
100
+ QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len,
222
+ },
101
+ void *tail_buf, size_t tail_len)
223
+ {
102
+{
224
+ .name = VXHS_OPT_VDISK_ID,
103
+ size_t mid_head, mid_tail;
225
+ .type = QEMU_OPT_STRING,
104
+ int total_niov, mid_niov = 0;
226
+ .help = "UUID of the VxHS vdisk",
105
+ struct iovec *p, *mid_iov;
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
+
106
+
237
+static QemuOptsList runtime_tcp_opts = {
107
+ if (mid_len) {
238
+ .name = "vxhs_tcp",
108
+ mid_iov = qiov_slice(mid_qiov, mid_offset, mid_len,
239
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_tcp_opts.head),
109
+ &mid_head, &mid_tail, &mid_niov);
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
+ }
110
+ }
272
+
111
+
273
+ qdict_put(options, VXHS_OPT_SERVER".host", qstring_from_str(uri->server));
112
+ total_niov = !!head_len + mid_niov + !!tail_len;
274
+
113
+ if (total_niov == 1) {
275
+ if (uri->port) {
114
+ qemu_iovec_init_buf(qiov, NULL, 0);
276
+ port = g_strdup_printf("%d", uri->port);
115
+ p = &qiov->local_iov;
277
+ qdict_put(options, VXHS_OPT_SERVER".port", qstring_from_str(port));
116
+ } else {
278
+ g_free(port);
117
+ qiov->niov = qiov->nalloc = total_niov;
118
+ qiov->size = head_len + mid_len + tail_len;
119
+ p = qiov->iov = g_new(struct iovec, qiov->niov);
279
+ }
120
+ }
280
+
121
+
281
+ qdict_put(options, "vdisk-id", qstring_from_str(uri->path));
122
+ if (head_len) {
282
+
123
+ p->iov_base = head_buf;
283
+ trace_vxhs_parse_uri_hostinfo(uri->server, uri->port);
124
+ p->iov_len = head_len;
284
+ uri_free(uri);
125
+ p++;
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
+ }
126
+ }
297
+
127
+
298
+ if (strstr(filename, "://")) {
128
+ if (mid_len) {
299
+ int ret = vxhs_parse_uri(filename, options);
129
+ memcpy(p, mid_iov, mid_niov * sizeof(*p));
300
+ if (ret < 0) {
130
+ p[0].iov_base = (uint8_t *)p[0].iov_base + mid_head;
301
+ error_setg(errp, "Invalid URI. URI should be of the form "
131
+ p[0].iov_len -= mid_head;
302
+ " vxhs://<host_ip>:<port>/<vdisk-id>");
132
+ p[mid_niov - 1].iov_len -= mid_tail;
303
+ }
133
+ p += mid_niov;
134
+ }
135
+
136
+ if (tail_len) {
137
+ p->iov_base = tail_buf;
138
+ p->iov_len = tail_len;
304
+ }
139
+ }
305
+}
140
+}
306
+
141
+
307
+static int vxhs_init_and_ref(void)
142
/*
143
* Check if the contents of the iovecs are all zero
144
*/
145
@@ -XXX,XX +XXX,XX @@ bool qemu_iovec_is_zero(QEMUIOVector *qiov)
146
return true;
147
}
148
149
+void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
150
+ size_t offset, size_t len)
308
+{
151
+{
309
+ if (vxhs_ref++ == 0) {
152
+ qemu_iovec_init_extended(qiov, NULL, 0, source, offset, len, NULL, 0);
310
+ if (iio_init(QNIO_VERSION, vxhs_iio_callback)) {
311
+ return -ENODEV;
312
+ }
313
+ }
314
+ return 0;
315
+}
153
+}
316
+
154
+
317
+static void vxhs_unref(void)
155
void qemu_iovec_destroy(QEMUIOVector *qiov)
318
+{
156
{
319
+ if (--vxhs_ref == 0) {
157
- assert(qiov->nalloc != -1);
320
+ iio_fini();
158
+ if (qiov->nalloc != -1) {
159
+ g_free(qiov->iov);
321
+ }
160
+ }
322
+}
161
323
+
162
- qemu_iovec_reset(qiov);
324
+static void vxhs_get_tls_creds(const char *id, char **cacert,
163
- g_free(qiov->iov);
325
+ char **key, char **cert, Error **errp)
164
- qiov->nalloc = 0;
326
+{
165
- qiov->iov = NULL;
327
+ Object *obj;
166
+ memset(qiov, 0, sizeof(*qiov));
328
+ QCryptoTLSCreds *creds;
167
}
329
+ QCryptoTLSCredsX509 *creds_x509;
168
330
+
169
void qemu_iovec_reset(QEMUIOVector *qiov)
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
750
index XXXXXXX..XXXXXXX 100644
751
--- a/qapi/block-core.json
752
+++ b/qapi/block-core.json
753
@@ -XXX,XX +XXX,XX @@
754
#
755
# Drivers that are supported in block device operations.
756
#
757
+# @vxhs: Since 2.10
758
+#
759
# Since: 2.9
760
##
761
{ 'enum': 'BlockdevDriver',
762
@@ -XXX,XX +XXX,XX @@
763
'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
764
'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
765
'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
766
- 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
767
+ 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
768
769
##
770
# @BlockdevOptionsFile:
771
@@ -XXX,XX +XXX,XX @@
772
'data': { '*offset': 'int', '*size': 'int' } }
773
774
##
775
+# @BlockdevOptionsVxHS:
776
+#
777
+# Driver specific block device options for VxHS
778
+#
779
+# @vdisk-id: UUID of VxHS volume
780
+# @server: vxhs server IP, port
781
+# @tls-creds: TLS credentials ID
782
+#
783
+# Since: 2.10
784
+##
785
+{ 'struct': 'BlockdevOptionsVxHS',
786
+ 'data': { 'vdisk-id': 'str',
787
+ 'server': 'InetSocketAddressBase',
788
+ '*tls-creds': 'str' } }
789
+
790
+##
791
# @BlockdevOptions:
792
#
793
# Options for creating a block device. Many options are available for all
794
@@ -XXX,XX +XXX,XX @@
795
'vhdx': 'BlockdevOptionsGenericFormat',
796
'vmdk': 'BlockdevOptionsGenericCOWFormat',
797
'vpc': 'BlockdevOptionsGenericFormat',
798
- 'vvfat': 'BlockdevOptionsVVFAT'
799
+ 'vvfat': 'BlockdevOptionsVVFAT',
800
+ 'vxhs': 'BlockdevOptionsVxHS'
801
} }
802
803
##
804
--
170
--
805
2.9.3
171
2.21.0
806
172
807
173
diff view generated by jsdifflib
1
This adds support for reopen in rbd, for changing between r/w and r/o.
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Note, that this is only a flag change, but we will block a change from
3
We'll need to check a part of qiov soon, so implement it now.
4
r/o to r/w if we are using an RBD internal snapshot.
5
4
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Optimization with align down to 4 * sizeof(long) is dropped due to:
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
6
1. It is strange: it aligns length of the buffer, but where is a
8
Reviewed-by: John Snow <jsnow@redhat.com>
7
guarantee that buffer pointer is aligned itself?
9
Message-id: d4e87539167ec6527d44c97b164eabcccf96e4f3.1491597120.git.jcody@redhat.com
8
2. buffer_is_zero() is a better place for optimizations and it has
9
them.
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Message-id: 20190604161514.262241-3-vsementsov@virtuozzo.com
14
Message-Id: <20190604161514.262241-3-vsementsov@virtuozzo.com>
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
16
---
11
block/rbd.c | 21 +++++++++++++++++++++
17
include/qemu/iov.h | 2 +-
12
1 file changed, 21 insertions(+)
18
block/io.c | 2 +-
19
util/iov.c | 31 +++++++++++++++++++------------
20
3 files changed, 21 insertions(+), 14 deletions(-)
13
21
14
diff --git a/block/rbd.c b/block/rbd.c
22
diff --git a/include/qemu/iov.h b/include/qemu/iov.h
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/block/rbd.c
24
--- a/include/qemu/iov.h
17
+++ b/block/rbd.c
25
+++ b/include/qemu/iov.h
18
@@ -XXX,XX +XXX,XX @@ failed_opts:
26
@@ -XXX,XX +XXX,XX @@ void qemu_iovec_concat(QEMUIOVector *dst,
19
return r;
27
size_t qemu_iovec_concat_iov(QEMUIOVector *dst,
28
struct iovec *src_iov, unsigned int src_cnt,
29
size_t soffset, size_t sbytes);
30
-bool qemu_iovec_is_zero(QEMUIOVector *qiov);
31
+bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t qiov_offeset, size_t bytes);
32
void qemu_iovec_destroy(QEMUIOVector *qiov);
33
void qemu_iovec_reset(QEMUIOVector *qiov);
34
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
35
diff --git a/block/io.c b/block/io.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/block/io.c
38
+++ b/block/io.c
39
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
40
41
if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF &&
42
!(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_pwrite_zeroes &&
43
- qemu_iovec_is_zero(qiov)) {
44
+ qemu_iovec_is_zero(qiov, 0, qiov->size)) {
45
flags |= BDRV_REQ_ZERO_WRITE;
46
if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) {
47
flags |= BDRV_REQ_MAY_UNMAP;
48
diff --git a/util/iov.c b/util/iov.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/util/iov.c
51
+++ b/util/iov.c
52
@@ -XXX,XX +XXX,XX @@ void qemu_iovec_init_extended(
20
}
53
}
21
54
55
/*
56
- * Check if the contents of the iovecs are all zero
57
+ * Check if the contents of subrange of qiov data is all zeroes.
58
*/
59
-bool qemu_iovec_is_zero(QEMUIOVector *qiov)
60
+bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t offset, size_t bytes)
61
{
62
- int i;
63
- for (i = 0; i < qiov->niov; i++) {
64
- size_t offs = QEMU_ALIGN_DOWN(qiov->iov[i].iov_len, 4 * sizeof(long));
65
- uint8_t *ptr = qiov->iov[i].iov_base;
66
- if (offs && !buffer_is_zero(qiov->iov[i].iov_base, offs)) {
67
+ struct iovec *iov;
68
+ size_t current_offset;
22
+
69
+
23
+/* Since RBD is currently always opened R/W via the API,
70
+ assert(offset + bytes <= qiov->size);
24
+ * we just need to check if we are using a snapshot or not, in
25
+ * order to determine if we will allow it to be R/W */
26
+static int qemu_rbd_reopen_prepare(BDRVReopenState *state,
27
+ BlockReopenQueue *queue, Error **errp)
28
+{
29
+ BDRVRBDState *s = state->bs->opaque;
30
+ int ret = 0;
31
+
71
+
32
+ if (s->snap && state->flags & BDRV_O_RDWR) {
72
+ iov = iov_skip_offset(qiov->iov, offset, &current_offset);
33
+ error_setg(errp,
34
+ "Cannot change node '%s' to r/w when using RBD snapshot",
35
+ bdrv_get_device_or_node_name(state->bs));
36
+ ret = -EINVAL;
37
+ }
38
+
73
+
39
+ return ret;
74
+ while (bytes) {
40
+}
75
+ uint8_t *base = (uint8_t *)iov->iov_base + current_offset;
76
+ size_t len = MIN(iov->iov_len - current_offset, bytes);
41
+
77
+
42
static void qemu_rbd_close(BlockDriverState *bs)
78
+ if (!buffer_is_zero(base, len)) {
43
{
79
return false;
44
BDRVRBDState *s = bs->opaque;
80
}
45
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
81
- for (; offs < qiov->iov[i].iov_len; offs++) {
46
.bdrv_parse_filename = qemu_rbd_parse_filename,
82
- if (ptr[offs]) {
47
.bdrv_file_open = qemu_rbd_open,
83
- return false;
48
.bdrv_close = qemu_rbd_close,
84
- }
49
+ .bdrv_reopen_prepare = qemu_rbd_reopen_prepare,
85
- }
50
.bdrv_create = qemu_rbd_create,
86
+
51
.bdrv_has_zero_init = bdrv_has_zero_init_1,
87
+ current_offset = 0;
52
.bdrv_get_info = qemu_rbd_getinfo,
88
+ bytes -= len;
89
+ iov++;
90
}
91
+
92
return true;
93
}
94
53
--
95
--
54
2.9.3
96
2.21.0
55
97
56
98
diff view generated by jsdifflib
1
Update 'clientname' to be 'user', which tracks better with both
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
the QAPI and rados variable naming.
2
3
3
We have similar padding code in bdrv_co_pwritev,
4
Update 'name' to be 'image_name', as it indicates the rbd image.
4
bdrv_co_do_pwrite_zeroes and bdrv_co_preadv. Let's combine and unify
5
Naming it 'image' would have been ideal, but we are using that for
5
it.
6
the rados_image_t value returned by rbd_open().
6
7
7
[Squashed in Vladimir's qemu-iotests 077 fix
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
--Stefan]
9
Signed-off-by: Jeff Cody <jcody@redhat.com>
9
10
Reviewed-by: John Snow <jsnow@redhat.com>
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-id: b7ec1fb2e1cf36f9b6911631447a5b0422590b7d.1491597120.git.jcody@redhat.com
11
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-id: 20190604161514.262241-4-vsementsov@virtuozzo.com
13
Message-Id: <20190604161514.262241-4-vsementsov@virtuozzo.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
15
---
13
block/rbd.c | 33 +++++++++++++++++----------------
16
block/io.c | 365 +++++++++++++++++++++++++++++------------------------
14
1 file changed, 17 insertions(+), 16 deletions(-)
17
1 file changed, 200 insertions(+), 165 deletions(-)
15
18
16
diff --git a/block/rbd.c b/block/rbd.c
19
diff --git a/block/io.c b/block/io.c
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/block/rbd.c
21
--- a/block/io.c
19
+++ b/block/rbd.c
22
+++ b/block/io.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRBDState {
23
@@ -XXX,XX +XXX,XX @@ out:
21
rados_t cluster;
24
}
22
rados_ioctx_t io_ctx;
25
23
rbd_image_t image;
26
/*
24
- char *name;
27
- * Handle a read request in coroutine context
25
+ char *image_name;
28
+ * Request padding
26
char *snap;
29
+ *
27
} BDRVRBDState;
30
+ * |<---- align ----->| |<----- align ---->|
28
31
+ * |<- head ->|<------------- bytes ------------->|<-- tail -->|
29
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
32
+ * | | | | | |
30
int64_t bytes = 0;
33
+ * -*----------$-------*-------- ... --------*-----$------------*---
31
int64_t objsize;
34
+ * | | | | | |
32
int obj_order = 0;
35
+ * | offset | | end |
33
- const char *pool, *name, *conf, *clientname, *keypairs;
36
+ * ALIGN_DOWN(offset) ALIGN_UP(offset) ALIGN_DOWN(end) ALIGN_UP(end)
34
+ const char *pool, *image_name, *conf, *user, *keypairs;
37
+ * [buf ... ) [tail_buf )
35
const char *secretid;
38
+ *
36
rados_t cluster;
39
+ * @buf is an aligned allocation needed to store @head and @tail paddings. @head
37
rados_ioctx_t io_ctx;
40
+ * is placed at the beginning of @buf and @tail at the @end.
38
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
41
+ *
39
*/
42
+ * @tail_buf is a pointer to sub-buffer, corresponding to align-sized chunk
40
pool = qdict_get_try_str(options, "pool");
43
+ * around tail, if tail exists.
41
conf = qdict_get_try_str(options, "conf");
44
+ *
42
- clientname = qdict_get_try_str(options, "user");
45
+ * @merge_reads is true for small requests,
43
- name = qdict_get_try_str(options, "image");
46
+ * if @buf_len == @head + bytes + @tail. In this case it is possible that both
44
+ user = qdict_get_try_str(options, "user");
47
+ * head and tail exist but @buf_len == align and @tail_buf == @buf.
45
+ image_name = qdict_get_try_str(options, "image");
48
*/
46
keypairs = qdict_get_try_str(options, "=keyvalue-pairs");
49
+typedef struct BdrvRequestPadding {
47
50
+ uint8_t *buf;
48
- ret = rados_create(&cluster, clientname);
51
+ size_t buf_len;
49
+ ret = rados_create(&cluster, user);
52
+ uint8_t *tail_buf;
53
+ size_t head;
54
+ size_t tail;
55
+ bool merge_reads;
56
+ QEMUIOVector local_qiov;
57
+} BdrvRequestPadding;
58
+
59
+static bool bdrv_init_padding(BlockDriverState *bs,
60
+ int64_t offset, int64_t bytes,
61
+ BdrvRequestPadding *pad)
62
+{
63
+ uint64_t align = bs->bl.request_alignment;
64
+ size_t sum;
65
+
66
+ memset(pad, 0, sizeof(*pad));
67
+
68
+ pad->head = offset & (align - 1);
69
+ pad->tail = ((offset + bytes) & (align - 1));
70
+ if (pad->tail) {
71
+ pad->tail = align - pad->tail;
72
+ }
73
+
74
+ if ((!pad->head && !pad->tail) || !bytes) {
75
+ return false;
76
+ }
77
+
78
+ sum = pad->head + bytes + pad->tail;
79
+ pad->buf_len = (sum > align && pad->head && pad->tail) ? 2 * align : align;
80
+ pad->buf = qemu_blockalign(bs, pad->buf_len);
81
+ pad->merge_reads = sum == pad->buf_len;
82
+ if (pad->tail) {
83
+ pad->tail_buf = pad->buf + pad->buf_len - align;
84
+ }
85
+
86
+ return true;
87
+}
88
+
89
+static int bdrv_padding_rmw_read(BdrvChild *child,
90
+ BdrvTrackedRequest *req,
91
+ BdrvRequestPadding *pad,
92
+ bool zero_middle)
93
+{
94
+ QEMUIOVector local_qiov;
95
+ BlockDriverState *bs = child->bs;
96
+ uint64_t align = bs->bl.request_alignment;
97
+ int ret;
98
+
99
+ assert(req->serialising && pad->buf);
100
+
101
+ if (pad->head || pad->merge_reads) {
102
+ uint64_t bytes = pad->merge_reads ? pad->buf_len : align;
103
+
104
+ qemu_iovec_init_buf(&local_qiov, pad->buf, bytes);
105
+
106
+ if (pad->head) {
107
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
108
+ }
109
+ if (pad->merge_reads && pad->tail) {
110
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
111
+ }
112
+ ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes,
113
+ align, &local_qiov, 0);
114
+ if (ret < 0) {
115
+ return ret;
116
+ }
117
+ if (pad->head) {
118
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
119
+ }
120
+ if (pad->merge_reads && pad->tail) {
121
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
122
+ }
123
+
124
+ if (pad->merge_reads) {
125
+ goto zero_mem;
126
+ }
127
+ }
128
+
129
+ if (pad->tail) {
130
+ qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align);
131
+
132
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
133
+ ret = bdrv_aligned_preadv(
134
+ child, req,
135
+ req->overlap_offset + req->overlap_bytes - align,
136
+ align, align, &local_qiov, 0);
137
+ if (ret < 0) {
138
+ return ret;
139
+ }
140
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
141
+ }
142
+
143
+zero_mem:
144
+ if (zero_middle) {
145
+ memset(pad->buf + pad->head, 0, pad->buf_len - pad->head - pad->tail);
146
+ }
147
+
148
+ return 0;
149
+}
150
+
151
+static void bdrv_padding_destroy(BdrvRequestPadding *pad)
152
+{
153
+ if (pad->buf) {
154
+ qemu_vfree(pad->buf);
155
+ qemu_iovec_destroy(&pad->local_qiov);
156
+ }
157
+}
158
+
159
+/*
160
+ * bdrv_pad_request
161
+ *
162
+ * Exchange request parameters with padded request if needed. Don't include RMW
163
+ * read of padding, bdrv_padding_rmw_read() should be called separately if
164
+ * needed.
165
+ *
166
+ * All parameters except @bs are in-out: they represent original request at
167
+ * function call and padded (if padding needed) at function finish.
168
+ *
169
+ * Function always succeeds.
170
+ */
171
+static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov,
172
+ int64_t *offset, unsigned int *bytes,
173
+ BdrvRequestPadding *pad)
174
+{
175
+ if (!bdrv_init_padding(bs, *offset, *bytes, pad)) {
176
+ return false;
177
+ }
178
+
179
+ qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head,
180
+ *qiov, 0, *bytes,
181
+ pad->buf + pad->buf_len - pad->tail, pad->tail);
182
+ *bytes += pad->head + pad->tail;
183
+ *offset -= pad->head;
184
+ *qiov = &pad->local_qiov;
185
+
186
+ return true;
187
+}
188
+
189
int coroutine_fn bdrv_co_preadv(BdrvChild *child,
190
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
191
BdrvRequestFlags flags)
192
{
193
BlockDriverState *bs = child->bs;
194
- BlockDriver *drv = bs->drv;
195
BdrvTrackedRequest req;
196
-
197
- uint64_t align = bs->bl.request_alignment;
198
- uint8_t *head_buf = NULL;
199
- uint8_t *tail_buf = NULL;
200
- QEMUIOVector local_qiov;
201
- bool use_local_qiov = false;
202
+ BdrvRequestPadding pad;
203
int ret;
204
205
- trace_bdrv_co_preadv(child->bs, offset, bytes, flags);
206
-
207
- if (!drv) {
208
- return -ENOMEDIUM;
209
- }
210
+ trace_bdrv_co_preadv(bs, offset, bytes, flags);
211
212
ret = bdrv_check_byte_request(bs, offset, bytes);
50
if (ret < 0) {
213
if (ret < 0) {
51
error_setg_errno(errp, -ret, "error initializing");
214
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child,
52
goto exit;
215
flags |= BDRV_REQ_COPY_ON_READ;
53
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
54
goto shutdown;
55
}
216
}
56
217
57
- ret = rbd_create(io_ctx, name, bytes, &obj_order);
218
- /* Align read if necessary by padding qiov */
58
+ ret = rbd_create(io_ctx, image_name, bytes, &obj_order);
219
- if (offset & (align - 1)) {
59
if (ret < 0) {
220
- head_buf = qemu_blockalign(bs, align);
60
error_setg_errno(errp, -ret, "error rbd create");
221
- qemu_iovec_init(&local_qiov, qiov->niov + 2);
222
- qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1));
223
- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
224
- use_local_qiov = true;
225
-
226
- bytes += offset & (align - 1);
227
- offset = offset & ~(align - 1);
228
- }
229
-
230
- if ((offset + bytes) & (align - 1)) {
231
- if (!use_local_qiov) {
232
- qemu_iovec_init(&local_qiov, qiov->niov + 1);
233
- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
234
- use_local_qiov = true;
235
- }
236
- tail_buf = qemu_blockalign(bs, align);
237
- qemu_iovec_add(&local_qiov, tail_buf,
238
- align - ((offset + bytes) & (align - 1)));
239
-
240
- bytes = ROUND_UP(bytes, align);
241
- }
242
+ bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad);
243
244
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ);
245
- ret = bdrv_aligned_preadv(child, &req, offset, bytes, align,
246
- use_local_qiov ? &local_qiov : qiov,
247
- flags);
248
+ ret = bdrv_aligned_preadv(child, &req, offset, bytes,
249
+ bs->bl.request_alignment,
250
+ qiov, flags);
251
tracked_request_end(&req);
252
bdrv_dec_in_flight(bs);
253
254
- if (use_local_qiov) {
255
- qemu_iovec_destroy(&local_qiov);
256
- qemu_vfree(head_buf);
257
- qemu_vfree(tail_buf);
258
- }
259
+ bdrv_padding_destroy(&pad);
260
261
return ret;
262
}
263
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
264
BdrvTrackedRequest *req)
265
{
266
BlockDriverState *bs = child->bs;
267
- uint8_t *buf = NULL;
268
QEMUIOVector local_qiov;
269
uint64_t align = bs->bl.request_alignment;
270
- unsigned int head_padding_bytes, tail_padding_bytes;
271
int ret = 0;
272
+ bool padding;
273
+ BdrvRequestPadding pad;
274
275
- head_padding_bytes = offset & (align - 1);
276
- tail_padding_bytes = (align - (offset + bytes)) & (align - 1);
277
-
278
-
279
- assert(flags & BDRV_REQ_ZERO_WRITE);
280
- if (head_padding_bytes || tail_padding_bytes) {
281
- buf = qemu_blockalign(bs, align);
282
- qemu_iovec_init_buf(&local_qiov, buf, align);
283
- }
284
- if (head_padding_bytes) {
285
- uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes);
286
-
287
- /* RMW the unaligned part before head. */
288
+ padding = bdrv_init_padding(bs, offset, bytes, &pad);
289
+ if (padding) {
290
mark_request_serialising(req, align);
291
wait_serialising_requests(req);
292
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
293
- ret = bdrv_aligned_preadv(child, req, offset & ~(align - 1), align,
294
- align, &local_qiov, 0);
295
- if (ret < 0) {
296
- goto fail;
297
- }
298
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
299
300
- memset(buf + head_padding_bytes, 0, zero_bytes);
301
- ret = bdrv_aligned_pwritev(child, req, offset & ~(align - 1), align,
302
- align, &local_qiov,
303
- flags & ~BDRV_REQ_ZERO_WRITE);
304
- if (ret < 0) {
305
- goto fail;
306
+ bdrv_padding_rmw_read(child, req, &pad, true);
307
+
308
+ if (pad.head || pad.merge_reads) {
309
+ int64_t aligned_offset = offset & ~(align - 1);
310
+ int64_t write_bytes = pad.merge_reads ? pad.buf_len : align;
311
+
312
+ qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes);
313
+ ret = bdrv_aligned_pwritev(child, req, aligned_offset, write_bytes,
314
+ align, &local_qiov,
315
+ flags & ~BDRV_REQ_ZERO_WRITE);
316
+ if (ret < 0 || pad.merge_reads) {
317
+ /* Error or all work is done */
318
+ goto out;
319
+ }
320
+ offset += write_bytes - pad.head;
321
+ bytes -= write_bytes - pad.head;
322
}
323
- offset += zero_bytes;
324
- bytes -= zero_bytes;
61
}
325
}
62
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
326
63
Error **errp)
327
assert(!bytes || (offset & (align - 1)) == 0);
64
{
328
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
65
BDRVRBDState *s = bs->opaque;
329
ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align,
66
- const char *pool, *snap, *conf, *clientname, *name, *keypairs;
330
NULL, flags);
67
+ const char *pool, *snap, *conf, *user, *image_name, *keypairs;
331
if (ret < 0) {
68
const char *secretid;
332
- goto fail;
69
QemuOpts *opts;
333
+ goto out;
70
Error *local_err = NULL;
334
}
71
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
335
bytes -= aligned_bytes;
72
pool = qemu_opt_get(opts, "pool");
336
offset += aligned_bytes;
73
conf = qemu_opt_get(opts, "conf");
337
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
74
snap = qemu_opt_get(opts, "snapshot");
338
75
- clientname = qemu_opt_get(opts, "user");
339
assert(!bytes || (offset & (align - 1)) == 0);
76
- name = qemu_opt_get(opts, "image");
340
if (bytes) {
77
+ user = qemu_opt_get(opts, "user");
341
- assert(align == tail_padding_bytes + bytes);
78
+ image_name = qemu_opt_get(opts, "image");
342
- /* RMW the unaligned part after tail. */
79
keypairs = qemu_opt_get(opts, "=keyvalue-pairs");
343
- mark_request_serialising(req, align);
80
344
- wait_serialising_requests(req);
81
- if (!pool || !name) {
345
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
82
+ if (!pool || !image_name) {
346
- ret = bdrv_aligned_preadv(child, req, offset, align,
83
error_setg(errp, "Parameters 'pool' and 'image' are required");
347
- align, &local_qiov, 0);
84
r = -EINVAL;
348
- if (ret < 0) {
85
goto failed_opts;
349
- goto fail;
350
- }
351
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
352
+ assert(align == pad.tail + bytes);
353
354
- memset(buf, 0, bytes);
355
+ qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align);
356
ret = bdrv_aligned_pwritev(child, req, offset, align, align,
357
&local_qiov, flags & ~BDRV_REQ_ZERO_WRITE);
86
}
358
}
87
359
-fail:
88
- r = rados_create(&s->cluster, clientname);
360
- qemu_vfree(buf);
89
+ r = rados_create(&s->cluster, user);
361
+
90
if (r < 0) {
362
+out:
91
error_setg_errno(errp, -r, "error initializing");
363
+ bdrv_padding_destroy(&pad);
92
goto failed_opts;
364
+
365
return ret;
366
-
367
}
368
369
/*
370
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
371
BlockDriverState *bs = child->bs;
372
BdrvTrackedRequest req;
373
uint64_t align = bs->bl.request_alignment;
374
- uint8_t *head_buf = NULL;
375
- uint8_t *tail_buf = NULL;
376
- QEMUIOVector local_qiov;
377
- bool use_local_qiov = false;
378
+ BdrvRequestPadding pad;
379
int ret;
380
381
trace_bdrv_co_pwritev(child->bs, offset, bytes, flags);
382
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
383
goto out;
93
}
384
}
94
385
95
s->snap = g_strdup(snap);
386
- if (offset & (align - 1)) {
96
- s->name = g_strdup(name);
387
- QEMUIOVector head_qiov;
97
+ s->image_name = g_strdup(image_name);
388
-
98
389
+ if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) {
99
/* try default location when conf=NULL, but ignore failure */
390
mark_request_serialising(&req, align);
100
r = rados_conf_read_file(s->cluster, conf);
391
wait_serialising_requests(&req);
101
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
392
-
393
- head_buf = qemu_blockalign(bs, align);
394
- qemu_iovec_init_buf(&head_qiov, head_buf, align);
395
-
396
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
397
- ret = bdrv_aligned_preadv(child, &req, offset & ~(align - 1), align,
398
- align, &head_qiov, 0);
399
- if (ret < 0) {
400
- goto fail;
401
- }
402
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
403
-
404
- qemu_iovec_init(&local_qiov, qiov->niov + 2);
405
- qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1));
406
- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
407
- use_local_qiov = true;
408
-
409
- bytes += offset & (align - 1);
410
- offset = offset & ~(align - 1);
411
-
412
- /* We have read the tail already if the request is smaller
413
- * than one aligned block.
414
- */
415
- if (bytes < align) {
416
- qemu_iovec_add(&local_qiov, head_buf + bytes, align - bytes);
417
- bytes = align;
418
- }
419
- }
420
-
421
- if ((offset + bytes) & (align - 1)) {
422
- QEMUIOVector tail_qiov;
423
- size_t tail_bytes;
424
- bool waited;
425
-
426
- mark_request_serialising(&req, align);
427
- waited = wait_serialising_requests(&req);
428
- assert(!waited || !use_local_qiov);
429
-
430
- tail_buf = qemu_blockalign(bs, align);
431
- qemu_iovec_init_buf(&tail_qiov, tail_buf, align);
432
-
433
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
434
- ret = bdrv_aligned_preadv(child, &req, (offset + bytes) & ~(align - 1),
435
- align, align, &tail_qiov, 0);
436
- if (ret < 0) {
437
- goto fail;
438
- }
439
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
440
-
441
- if (!use_local_qiov) {
442
- qemu_iovec_init(&local_qiov, qiov->niov + 1);
443
- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
444
- use_local_qiov = true;
445
- }
446
-
447
- tail_bytes = (offset + bytes) & (align - 1);
448
- qemu_iovec_add(&local_qiov, tail_buf + tail_bytes, align - tail_bytes);
449
-
450
- bytes = ROUND_UP(bytes, align);
451
+ bdrv_padding_rmw_read(child, &req, &pad, false);
102
}
452
}
103
453
104
/* rbd_open is always r/w */
454
ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align,
105
- r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
455
- use_local_qiov ? &local_qiov : qiov,
106
+ r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap);
456
- flags);
107
if (r < 0) {
457
+ qiov, flags);
108
- error_setg_errno(errp, -r, "error reading header from %s", s->name);
458
109
+ error_setg_errno(errp, -r, "error reading header from %s",
459
-fail:
110
+ s->image_name);
460
+ bdrv_padding_destroy(&pad);
111
goto failed_open;
461
112
}
462
- if (use_local_qiov) {
113
463
- qemu_iovec_destroy(&local_qiov);
114
@@ -XXX,XX +XXX,XX @@ failed_open:
464
- }
115
failed_shutdown:
465
- qemu_vfree(head_buf);
116
rados_shutdown(s->cluster);
466
- qemu_vfree(tail_buf);
117
g_free(s->snap);
467
out:
118
- g_free(s->name);
468
tracked_request_end(&req);
119
+ g_free(s->image_name);
469
bdrv_dec_in_flight(bs);
120
failed_opts:
470
+
121
qemu_opts_del(opts);
471
return ret;
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
}
472
}
131
473
132
--
474
--
133
2.9.3
475
2.21.0
134
476
135
477
diff view generated by jsdifflib
1
A few block drivers will set the BDS read_only flag from their
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
.bdrv_open() function. This means the bs->read_only flag could
2
3
be set after we enable copy_on_read, as the BDRV_O_COPY_ON_READ
3
Add handlers supporting qiov_offset parameter:
4
flag check occurs prior to the call to bdrv->bdrv_open().
4
bdrv_co_preadv_part
5
5
bdrv_co_pwritev_part
6
This adds an error return to bdrv_set_read_only(), and an error will be
6
bdrv_co_pwritev_compressed_part
7
return if we try to set the BDS to read_only while copy_on_read is
7
This is used to reduce need of defining local_qiovs and hd_qiovs in all
8
enabled.
8
corners of block layer code. The following patches will increase usage
9
9
of this new API part by part.
10
This patch also changes the behavior of vvfat. Before, vvfat could
10
11
override the drive 'readonly' flag with its own, internal 'rw' flag.
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
12
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
13
For instance, this -drive parameter would result in a writable image:
13
Message-id: 20190604161514.262241-5-vsementsov@virtuozzo.com
14
14
Message-Id: <20190604161514.262241-5-vsementsov@virtuozzo.com>
15
"-drive format=vvfat,dir=/tmp/vvfat,rw,if=virtio,readonly=on"
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
17
This is not correct. Now, attempting to use the above -drive parameter
18
will result in an error (i.e., 'rw' is incompatible with 'readonly=on').
19
20
Signed-off-by: Jeff Cody <jcody@redhat.com>
21
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
22
Reviewed-by: John Snow <jsnow@redhat.com>
23
Message-id: 0c5b4c1cc2c651471b131f21376dfd5ea24d2196.1491597120.git.jcody@redhat.com
24
---
16
---
25
block.c | 10 +++++++++-
17
include/block/block_int.h | 15 ++++++
26
block/bochs.c | 5 ++++-
18
block/backup.c | 2 +-
27
block/cloop.c | 5 ++++-
19
block/io.c | 96 +++++++++++++++++++++++++++++++--------
28
block/dmg.c | 6 +++++-
20
qemu-img.c | 4 +-
29
block/rbd.c | 11 ++++++++++-
21
4 files changed, 95 insertions(+), 22 deletions(-)
30
block/vvfat.c | 19 +++++++++++++++----
22
31
include/block/block.h | 2 +-
23
diff --git a/include/block/block_int.h b/include/block/block_int.h
32
7 files changed, 48 insertions(+), 10 deletions(-)
33
34
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
25
--- a/include/block/block_int.h
37
+++ b/block.c
26
+++ b/include/block/block_int.h
38
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
27
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
39
}
28
*/
29
int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs,
30
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags);
31
+ int coroutine_fn (*bdrv_co_preadv_part)(BlockDriverState *bs,
32
+ uint64_t offset, uint64_t bytes,
33
+ QEMUIOVector *qiov, size_t qiov_offset, int flags);
34
int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
35
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int flags);
36
/**
37
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
38
*/
39
int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs,
40
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags);
41
+ int coroutine_fn (*bdrv_co_pwritev_part)(BlockDriverState *bs,
42
+ uint64_t offset, uint64_t bytes,
43
+ QEMUIOVector *qiov, size_t qiov_offset, int flags);
44
45
/*
46
* Efficiently zero a region of the disk image. Typically an image format
47
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
49
int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs,
50
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov);
51
+ int coroutine_fn (*bdrv_co_pwritev_compressed_part)(BlockDriverState *bs,
52
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
53
+ size_t qiov_offset);
54
55
int (*bdrv_snapshot_create)(BlockDriverState *bs,
56
QEMUSnapshotInfo *sn_info);
57
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
58
const char *const *strong_runtime_opts;
59
};
60
61
+static inline bool block_driver_can_compress(BlockDriver *drv)
62
+{
63
+ return drv->bdrv_co_pwritev_compressed ||
64
+ drv->bdrv_co_pwritev_compressed_part;
65
+}
66
+
67
typedef struct BlockLimits {
68
/* Alignment requirement, in bytes, for offset/length of I/O
69
* requests. Must be a power of 2 less than INT_MAX; defaults to
70
diff --git a/block/backup.c b/block/backup.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/backup.c
73
+++ b/block/backup.c
74
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
75
return NULL;
76
}
77
78
- if (compress && target->drv->bdrv_co_pwritev_compressed == NULL) {
79
+ if (compress && !block_driver_can_compress(target->drv)) {
80
error_setg(errp, "Compression is not supported for this drive %s",
81
bdrv_get_device_name(target));
82
return NULL;
83
diff --git a/block/io.c b/block/io.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/block/io.c
86
+++ b/block/io.c
87
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
88
89
/* Default alignment based on whether driver has byte interface */
90
bs->bl.request_alignment = (drv->bdrv_co_preadv ||
91
- drv->bdrv_aio_preadv) ? 1 : 512;
92
+ drv->bdrv_aio_preadv ||
93
+ drv->bdrv_co_preadv_part) ? 1 : 512;
94
95
/* Take some limits from the children as a default */
96
if (bs->file) {
97
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_io_em_complete(void *opaque, int ret)
98
99
static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
100
uint64_t offset, uint64_t bytes,
101
- QEMUIOVector *qiov, int flags)
102
+ QEMUIOVector *qiov,
103
+ size_t qiov_offset, int flags)
104
{
105
BlockDriver *drv = bs->drv;
106
int64_t sector_num;
107
unsigned int nb_sectors;
108
+ QEMUIOVector local_qiov;
109
+ int ret;
110
111
assert(!(flags & ~BDRV_REQ_MASK));
112
assert(!(flags & BDRV_REQ_NO_FALLBACK));
113
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
114
return -ENOMEDIUM;
115
}
116
117
+ if (drv->bdrv_co_preadv_part) {
118
+ return drv->bdrv_co_preadv_part(bs, offset, bytes, qiov, qiov_offset,
119
+ flags);
120
+ }
121
+
122
+ if (qiov_offset > 0 || bytes != qiov->size) {
123
+ qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes);
124
+ qiov = &local_qiov;
125
+ }
126
+
127
if (drv->bdrv_co_preadv) {
128
- return drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags);
129
+ ret = drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags);
130
+ goto out;
131
}
132
133
if (drv->bdrv_aio_preadv) {
134
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
135
acb = drv->bdrv_aio_preadv(bs, offset, bytes, qiov, flags,
136
bdrv_co_io_em_complete, &co);
137
if (acb == NULL) {
138
- return -EIO;
139
+ ret = -EIO;
140
+ goto out;
141
} else {
142
qemu_coroutine_yield();
143
- return co.ret;
144
+ ret = co.ret;
145
+ goto out;
146
}
147
}
148
149
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
150
assert(bytes <= BDRV_REQUEST_MAX_BYTES);
151
assert(drv->bdrv_co_readv);
152
153
- return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
154
+ ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
155
+
156
+out:
157
+ if (qiov == &local_qiov) {
158
+ qemu_iovec_destroy(&local_qiov);
159
+ }
160
+
161
+ return ret;
40
}
162
}
41
163
42
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
164
static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
43
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
165
uint64_t offset, uint64_t bytes,
166
- QEMUIOVector *qiov, int flags)
167
+ QEMUIOVector *qiov,
168
+ size_t qiov_offset, int flags)
44
{
169
{
45
+ /* Do not set read_only if copy_on_read is enabled */
170
BlockDriver *drv = bs->drv;
46
+ if (bs->copy_on_read && read_only) {
171
int64_t sector_num;
47
+ error_setg(errp, "Can't set node '%s' to r/o with copy-on-read enabled",
172
unsigned int nb_sectors;
48
+ bdrv_get_device_or_node_name(bs));
173
+ QEMUIOVector local_qiov;
49
+ return -EINVAL;
174
int ret;
50
+ }
175
51
+
176
assert(!(flags & ~BDRV_REQ_MASK));
52
bs->read_only = read_only;
177
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
53
+ return 0;
178
return -ENOMEDIUM;
179
}
180
181
+ if (drv->bdrv_co_pwritev_part) {
182
+ ret = drv->bdrv_co_pwritev_part(bs, offset, bytes, qiov, qiov_offset,
183
+ flags & bs->supported_write_flags);
184
+ flags &= ~bs->supported_write_flags;
185
+ goto emulate_flags;
186
+ }
187
+
188
+ if (qiov_offset > 0 || bytes != qiov->size) {
189
+ qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes);
190
+ qiov = &local_qiov;
191
+ }
192
+
193
if (drv->bdrv_co_pwritev) {
194
ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov,
195
flags & bs->supported_write_flags);
196
@@ -XXX,XX +XXX,XX @@ emulate_flags:
197
ret = bdrv_co_flush(bs);
198
}
199
200
+ if (qiov == &local_qiov) {
201
+ qemu_iovec_destroy(&local_qiov);
202
+ }
203
+
204
return ret;
54
}
205
}
55
206
56
void bdrv_get_full_backing_filename_from_filename(const char *backed,
207
static int coroutine_fn
57
diff --git a/block/bochs.c b/block/bochs.c
208
bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
209
- uint64_t bytes, QEMUIOVector *qiov)
210
+ uint64_t bytes, QEMUIOVector *qiov,
211
+ size_t qiov_offset)
212
{
213
BlockDriver *drv = bs->drv;
214
+ QEMUIOVector local_qiov;
215
+ int ret;
216
217
if (!drv) {
218
return -ENOMEDIUM;
219
}
220
221
- if (!drv->bdrv_co_pwritev_compressed) {
222
+ if (!block_driver_can_compress(drv)) {
223
return -ENOTSUP;
224
}
225
226
- return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov);
227
+ if (drv->bdrv_co_pwritev_compressed_part) {
228
+ return drv->bdrv_co_pwritev_compressed_part(bs, offset, bytes,
229
+ qiov, qiov_offset);
230
+ }
231
+
232
+ if (qiov_offset == 0) {
233
+ return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov);
234
+ }
235
+
236
+ qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes);
237
+ ret = drv->bdrv_co_pwritev_compressed(bs, offset, bytes, &local_qiov);
238
+ qemu_iovec_destroy(&local_qiov);
239
+
240
+ return ret;
241
}
242
243
static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
244
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
245
qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum);
246
247
ret = bdrv_driver_preadv(bs, cluster_offset, pnum,
248
- &local_qiov, 0);
249
+ &local_qiov, 0, 0);
250
if (ret < 0) {
251
goto err;
252
}
253
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
254
* necessary to flush even in cache=writethrough mode.
255
*/
256
ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
257
- &local_qiov,
258
+ &local_qiov, 0,
259
BDRV_REQ_WRITE_UNCHANGED);
260
}
261
262
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
263
qemu_iovec_init(&local_qiov, qiov->niov);
264
qemu_iovec_concat(&local_qiov, qiov, progress, pnum - skip_bytes);
265
ret = bdrv_driver_preadv(bs, offset + progress, local_qiov.size,
266
- &local_qiov, 0);
267
+ &local_qiov, 0, 0);
268
qemu_iovec_destroy(&local_qiov);
269
if (ret < 0) {
270
goto err;
271
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
272
273
max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align);
274
if (bytes <= max_bytes && bytes <= max_transfer) {
275
- ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0);
276
+ ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0, 0);
277
goto out;
278
}
279
280
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
281
qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num);
282
283
ret = bdrv_driver_preadv(bs, offset + bytes - bytes_remaining,
284
- num, &local_qiov, 0);
285
+ num, &local_qiov, 0, 0);
286
max_bytes -= num;
287
qemu_iovec_destroy(&local_qiov);
288
} else {
289
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
290
}
291
qemu_iovec_init_buf(&qiov, buf, num);
292
293
- ret = bdrv_driver_pwritev(bs, offset, num, &qiov, write_flags);
294
+ ret = bdrv_driver_pwritev(bs, offset, num, &qiov, 0, write_flags);
295
296
/* Keep bounce buffer around if it is big enough for all
297
* all future requests.
298
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
299
bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
300
ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
301
} else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
302
- ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov);
303
+ ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov, 0);
304
} else if (bytes <= max_transfer) {
305
bdrv_debug_event(bs, BLKDBG_PWRITEV);
306
- ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags);
307
+ ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, 0, flags);
308
} else {
309
bdrv_debug_event(bs, BLKDBG_PWRITEV);
310
while (bytes_remaining) {
311
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
312
qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num);
313
314
ret = bdrv_driver_pwritev(bs, offset + bytes - bytes_remaining,
315
- num, &local_qiov, local_flags);
316
+ num, &local_qiov, 0, local_flags);
317
qemu_iovec_destroy(&local_qiov);
318
if (ret < 0) {
319
break;
320
diff --git a/qemu-img.c b/qemu-img.c
58
index XXXXXXX..XXXXXXX 100644
321
index XXXXXXX..XXXXXXX 100644
59
--- a/block/bochs.c
322
--- a/qemu-img.c
60
+++ b/block/bochs.c
323
+++ b/qemu-img.c
61
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
324
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
62
return -EINVAL;
325
const char *preallocation =
63
}
326
qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
64
327
65
- bdrv_set_read_only(bs, true); /* no write support yet */
328
- if (drv && !drv->bdrv_co_pwritev_compressed) {
66
+ ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
329
+ if (drv && !block_driver_can_compress(drv)) {
67
+ if (ret < 0) {
330
error_report("Compression not supported for this file format");
68
+ return ret;
331
ret = -1;
69
+ }
332
goto out;
70
333
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
71
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
334
}
72
if (ret < 0) {
335
out_bs = blk_bs(s.target);
73
diff --git a/block/cloop.c b/block/cloop.c
336
74
index XXXXXXX..XXXXXXX 100644
337
- if (s.compressed && !out_bs->drv->bdrv_co_pwritev_compressed) {
75
--- a/block/cloop.c
338
+ if (s.compressed && !block_driver_can_compress(out_bs->drv)) {
76
+++ b/block/cloop.c
339
error_report("Compression not supported for this file format");
77
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
340
ret = -1;
78
return -EINVAL;
341
goto out;
79
}
80
81
- bdrv_set_read_only(bs, true);
82
+ ret = bdrv_set_read_only(bs, true, errp);
83
+ if (ret < 0) {
84
+ return ret;
85
+ }
86
87
/* read header */
88
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
89
diff --git a/block/dmg.c b/block/dmg.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/block/dmg.c
92
+++ b/block/dmg.c
93
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
94
return -EINVAL;
95
}
96
97
+ ret = bdrv_set_read_only(bs, true, errp);
98
+ if (ret < 0) {
99
+ return ret;
100
+ }
101
+
102
block_module_load_one("dmg-bz2");
103
- bdrv_set_read_only(bs, true);
104
105
s->n_chunks = 0;
106
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
107
diff --git a/block/rbd.c b/block/rbd.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/block/rbd.c
110
+++ b/block/rbd.c
111
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
112
goto failed_shutdown;
113
}
114
115
+ /* rbd_open is always r/w */
116
r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
117
if (r < 0) {
118
error_setg_errno(errp, -r, "error reading header from %s", s->name);
119
goto failed_open;
120
}
121
122
- bdrv_set_read_only(bs, (s->snap != NULL));
123
+ /* If we are using an rbd snapshot, we must be r/o, otherwise
124
+ * leave as-is */
125
+ if (s->snap != NULL) {
126
+ r = bdrv_set_read_only(bs, true, &local_err);
127
+ if (r < 0) {
128
+ error_propagate(errp, local_err);
129
+ goto failed_open;
130
+ }
131
+ }
132
133
qemu_opts_del(opts);
134
return 0;
135
diff --git a/block/vvfat.c b/block/vvfat.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/block/vvfat.c
138
+++ b/block/vvfat.c
139
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
140
141
s->current_cluster=0xffffffff;
142
143
- /* read only is the default for safety */
144
- bdrv_set_read_only(bs, true);
145
s->qcow = NULL;
146
s->qcow_filename = NULL;
147
s->fat2 = NULL;
148
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
149
s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
150
151
if (qemu_opt_get_bool(opts, "rw", false)) {
152
- ret = enable_write_target(bs, errp);
153
+ if (!bdrv_is_read_only(bs)) {
154
+ ret = enable_write_target(bs, errp);
155
+ if (ret < 0) {
156
+ goto fail;
157
+ }
158
+ } else {
159
+ ret = -EPERM;
160
+ error_setg(errp,
161
+ "Unable to set VVFAT to 'rw' when drive is read-only");
162
+ goto fail;
163
+ }
164
+ } else {
165
+ /* read only is the default for safety */
166
+ ret = bdrv_set_read_only(bs, true, &local_err);
167
if (ret < 0) {
168
+ error_propagate(errp, local_err);
169
goto fail;
170
}
171
- bdrv_set_read_only(bs, false);
172
}
173
174
bs->total_sectors = cyls * heads * secs;
175
diff --git a/include/block/block.h b/include/block/block.h
176
index XXXXXXX..XXXXXXX 100644
177
--- a/include/block/block.h
178
+++ b/include/block/block.h
179
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
180
int64_t sector_num, int nb_sectors, int *pnum);
181
182
bool bdrv_is_read_only(BlockDriverState *bs);
183
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only);
184
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
185
bool bdrv_is_sg(BlockDriverState *bs);
186
bool bdrv_is_inserted(BlockDriverState *bs);
187
int bdrv_media_changed(BlockDriverState *bs);
188
--
342
--
189
2.9.3
343
2.21.0
190
344
191
345
diff view generated by jsdifflib
1
For the tests that use the common.qemu functions for running a QEMU
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
process, _cleanup_qemu must be called in the exit function.
3
2
4
If it is not, if the qemu process aborts, then not all of the droppings
3
Use and support new API in bdrv_co_do_copy_on_readv. Note that in case
5
are cleaned up (e.g. pidfile, fifos).
4
of allocated-in-top we need to shrink read size to MIN(..) by hand, as
5
pre-patch this was actually done implicitly by qemu_iovec_concat (and
6
we used local_qiov.size).
6
7
7
This updates those tests that did not have a cleanup in qemu-iotests.
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-id: 20190604161514.262241-6-vsementsov@virtuozzo.com
11
Message-Id: <20190604161514.262241-6-vsementsov@virtuozzo.com>
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
14
block/io.c | 18 +++++++++---------
15
1 file changed, 9 insertions(+), 9 deletions(-)
8
16
9
(I swapped spaces for tabs in test 102 as well)
17
diff --git a/block/io.c b/block/io.c
10
18
index XXXXXXX..XXXXXXX 100644
11
Reported-by: Eric Blake <eblake@redhat.com>
19
--- a/block/io.c
12
Reviewed-by: Eric Blake <eblake@redhat.com>
20
+++ b/block/io.c
13
Signed-off-by: Jeff Cody <jcody@redhat.com>
21
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
14
Message-id: d59c2f6ad6c1da8b9b3c7f357c94a7122ccfc55a.1492544096.git.jcody@redhat.com
22
15
---
23
static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
16
tests/qemu-iotests/028 | 1 +
24
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
17
tests/qemu-iotests/094 | 11 ++++++++---
25
- int flags)
18
tests/qemu-iotests/102 | 5 +++--
26
+ size_t qiov_offset, int flags)
19
tests/qemu-iotests/109 | 1 +
20
tests/qemu-iotests/117 | 1 +
21
tests/qemu-iotests/130 | 1 +
22
tests/qemu-iotests/140 | 1 +
23
tests/qemu-iotests/141 | 1 +
24
tests/qemu-iotests/143 | 1 +
25
tests/qemu-iotests/156 | 1 +
26
10 files changed, 19 insertions(+), 5 deletions(-)
27
28
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
29
index XXXXXXX..XXXXXXX 100755
30
--- a/tests/qemu-iotests/028
31
+++ b/tests/qemu-iotests/028
32
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
33
34
_cleanup()
35
{
27
{
36
+ _cleanup_qemu
28
BlockDriverState *bs = child->bs;
37
rm -f "${TEST_IMG}.copy"
29
38
_cleanup_test_img
30
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
39
}
31
void *bounce_buffer;
40
diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094
32
41
index XXXXXXX..XXXXXXX 100755
33
BlockDriver *drv = bs->drv;
42
--- a/tests/qemu-iotests/094
34
- QEMUIOVector local_qiov;
43
+++ b/tests/qemu-iotests/094
35
int64_t cluster_offset;
44
@@ -XXX,XX +XXX,XX @@ echo "QA output created by $seq"
36
int64_t cluster_bytes;
45
here="$PWD"
37
size_t skip_bytes;
46
status=1    # failure is the default!
38
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
47
39
assert(skip_bytes < pnum);
48
-trap "exit \$status" 0 1 2 3 15
40
49
+_cleanup()
41
if (ret <= 0) {
50
+{
42
+ QEMUIOVector local_qiov;
51
+ _cleanup_qemu
52
+ _cleanup_test_img
53
+ rm -f "$TEST_DIR/source.$IMGFMT"
54
+}
55
+
43
+
56
+trap "_cleanup; exit \$status" 0 1 2 3 15
44
/* Must copy-on-read; use the bounce buffer */
57
45
pnum = MIN(pnum, MAX_BOUNCE_BUFFER);
58
# get standard environment, filters and checks
46
qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum);
59
. ./common.rc
47
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
60
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE \
48
}
61
49
62
wait=1 _cleanup_qemu
50
if (!(flags & BDRV_REQ_PREFETCH)) {
63
51
- qemu_iovec_from_buf(qiov, progress, bounce_buffer + skip_bytes,
64
-_cleanup_test_img
52
+ qemu_iovec_from_buf(qiov, qiov_offset + progress,
65
-rm -f "$TEST_DIR/source.$IMGFMT"
53
+ bounce_buffer + skip_bytes,
66
54
pnum - skip_bytes);
67
# success, all done
55
}
68
echo '*** done'
56
} else if (!(flags & BDRV_REQ_PREFETCH)) {
69
diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102
57
/* Read directly into the destination */
70
index XXXXXXX..XXXXXXX 100755
58
- qemu_iovec_init(&local_qiov, qiov->niov);
71
--- a/tests/qemu-iotests/102
59
- qemu_iovec_concat(&local_qiov, qiov, progress, pnum - skip_bytes);
72
+++ b/tests/qemu-iotests/102
60
- ret = bdrv_driver_preadv(bs, offset + progress, local_qiov.size,
73
@@ -XXX,XX +XXX,XX @@ seq=$(basename $0)
61
- &local_qiov, 0, 0);
74
echo "QA output created by $seq"
62
- qemu_iovec_destroy(&local_qiov);
75
63
+ ret = bdrv_driver_preadv(bs, offset + progress,
76
here=$PWD
64
+ MIN(pnum - skip_bytes, bytes - progress),
77
-status=1    # failure is the default!
65
+ qiov, qiov_offset + progress, 0);
78
+status=1 # failure is the default!
66
if (ret < 0) {
79
67
goto err;
80
_cleanup()
68
}
81
{
69
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
82
-    _cleanup_test_img
70
}
83
+ _cleanup_qemu
71
84
+ _cleanup_test_img
72
if (!ret || pnum != bytes) {
85
}
73
- ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov, flags);
86
trap "_cleanup; exit \$status" 0 1 2 3 15
74
+ ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov, 0, flags);
87
75
goto out;
88
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
76
} else if (flags & BDRV_REQ_PREFETCH) {
89
index XXXXXXX..XXXXXXX 100755
77
goto out;
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
--
78
--
173
2.9.3
79
2.21.0
174
80
175
81
diff view generated by jsdifflib
1
Introduce check function for setting read_only flags. Will return < 0 on
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
error, with appropriate Error value set. Does not alter any flags.
3
2
4
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
Allocate bounce_buffer only if it is really needed. Also, sub-optimize
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4
allocation size (why not?).
6
Reviewed-by: John Snow <jsnow@redhat.com>
5
7
Message-id: e2bba34ac3bc76a0c42adc390413f358ae0566e8.1491597120.git.jcody@redhat.com
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-id: 20190604161514.262241-7-vsementsov@virtuozzo.com
9
Message-Id: <20190604161514.262241-7-vsementsov@virtuozzo.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
11
---
9
block.c | 14 +++++++++++++-
12
block/io.c | 21 ++++++++++++---------
10
include/block/block.h | 1 +
13
1 file changed, 12 insertions(+), 9 deletions(-)
11
2 files changed, 14 insertions(+), 1 deletion(-)
12
14
13
diff --git a/block.c b/block.c
15
diff --git a/block/io.c b/block/io.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
17
--- a/block/io.c
16
+++ b/block.c
18
+++ b/block/io.c
17
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
18
return bs->read_only;
20
* modifying the image file. This is critical for zero-copy guest I/O
19
}
21
* where anything might happen inside guest memory.
20
22
*/
21
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
23
- void *bounce_buffer;
22
+int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
24
+ void *bounce_buffer = NULL;
23
{
25
24
/* Do not set read_only if copy_on_read is enabled */
26
BlockDriver *drv = bs->drv;
25
if (bs->copy_on_read && read_only) {
27
int64_t cluster_offset;
26
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
27
return -EPERM;
29
trace_bdrv_co_do_copy_on_readv(bs, offset, bytes,
28
}
30
cluster_offset, cluster_bytes);
29
31
30
+ return 0;
32
- bounce_buffer = qemu_try_blockalign(bs,
31
+}
33
- MIN(MIN(max_transfer, cluster_bytes),
34
- MAX_BOUNCE_BUFFER));
35
- if (bounce_buffer == NULL) {
36
- ret = -ENOMEM;
37
- goto err;
38
- }
39
-
40
while (cluster_bytes) {
41
int64_t pnum;
42
43
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
44
45
/* Must copy-on-read; use the bounce buffer */
46
pnum = MIN(pnum, MAX_BOUNCE_BUFFER);
47
+ if (!bounce_buffer) {
48
+ int64_t max_we_need = MAX(pnum, cluster_bytes - pnum);
49
+ int64_t max_allowed = MIN(max_transfer, MAX_BOUNCE_BUFFER);
50
+ int64_t bounce_buffer_len = MIN(max_we_need, max_allowed);
32
+
51
+
33
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
52
+ bounce_buffer = qemu_try_blockalign(bs, bounce_buffer_len);
34
+{
53
+ if (!bounce_buffer) {
35
+ int ret = 0;
54
+ ret = -ENOMEM;
36
+
55
+ goto err;
37
+ ret = bdrv_can_set_read_only(bs, read_only, errp);
56
+ }
38
+ if (ret < 0) {
57
+ }
39
+ return ret;
58
qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum);
40
+ }
59
41
+
60
ret = bdrv_driver_preadv(bs, cluster_offset, pnum,
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
--
61
--
58
2.9.3
62
2.21.0
59
63
60
64
diff view generated by jsdifflib
1
The BDRV_O_ALLOW_RDWR flag allows / prohibits the changing of
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
the BDS 'read_only' state, but there are a few places where it
3
is ignored. In the bdrv_set_read_only() helper, make sure to
4
honor the flag.
5
2
6
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
Use and support new API in bdrv_co_do_copy_on_readv.
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4
8
Reviewed-by: John Snow <jsnow@redhat.com>
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-id: be2e5fb2d285cbece2b6d06bed54a6f56520d251.1491597120.git.jcody@redhat.com
6
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Message-id: 20190604161514.262241-8-vsementsov@virtuozzo.com
8
Message-Id: <20190604161514.262241-8-vsementsov@virtuozzo.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
10
---
11
block.c | 7 +++++++
11
block/io.c | 21 ++++++++-------------
12
1 file changed, 7 insertions(+)
12
1 file changed, 8 insertions(+), 13 deletions(-)
13
13
14
diff --git a/block.c b/block.c
14
diff --git a/block/io.c b/block/io.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block.c
16
--- a/block/io.c
17
+++ b/block.c
17
+++ b/block/io.c
18
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
18
@@ -XXX,XX +XXX,XX @@ err:
19
return -EINVAL;
19
*/
20
static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
21
BdrvTrackedRequest *req, int64_t offset, unsigned int bytes,
22
- int64_t align, QEMUIOVector *qiov, int flags)
23
+ int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
24
{
25
BlockDriverState *bs = child->bs;
26
int64_t total_bytes, max_bytes;
27
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
28
assert(is_power_of_2(align));
29
assert((offset & (align - 1)) == 0);
30
assert((bytes & (align - 1)) == 0);
31
- assert(!qiov || bytes == qiov->size);
32
assert((bs->open_flags & BDRV_O_NO_IO) == 0);
33
max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX),
34
align);
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
36
}
37
38
if (!ret || pnum != bytes) {
39
- ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov, 0, flags);
40
+ ret = bdrv_co_do_copy_on_readv(child, offset, bytes,
41
+ qiov, qiov_offset, flags);
42
goto out;
43
} else if (flags & BDRV_REQ_PREFETCH) {
44
goto out;
45
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
46
47
max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align);
48
if (bytes <= max_bytes && bytes <= max_transfer) {
49
- ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0, 0);
50
+ ret = bdrv_driver_preadv(bs, offset, bytes, qiov, qiov_offset, 0);
51
goto out;
20
}
52
}
21
53
22
+ /* Do not clear read_only if it is prohibited */
54
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
23
+ if (!read_only && !(bs->open_flags & BDRV_O_ALLOW_RDWR)) {
55
int num;
24
+ error_setg(errp, "Node '%s' is read only",
56
25
+ bdrv_get_device_or_node_name(bs));
57
if (max_bytes) {
26
+ return -EPERM;
58
- QEMUIOVector local_qiov;
27
+ }
59
-
28
+
60
num = MIN(bytes_remaining, MIN(max_bytes, max_transfer));
29
bs->read_only = read_only;
61
assert(num);
30
return 0;
62
- qemu_iovec_init(&local_qiov, qiov->niov);
31
}
63
- qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num);
64
65
ret = bdrv_driver_preadv(bs, offset + bytes - bytes_remaining,
66
- num, &local_qiov, 0, 0);
67
+ num, qiov, bytes - bytes_remaining, 0);
68
max_bytes -= num;
69
- qemu_iovec_destroy(&local_qiov);
70
} else {
71
num = bytes_remaining;
72
ret = qemu_iovec_memset(qiov, bytes - bytes_remaining, 0,
73
@@ -XXX,XX +XXX,XX @@ static int bdrv_padding_rmw_read(BdrvChild *child,
74
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
75
}
76
ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes,
77
- align, &local_qiov, 0);
78
+ align, &local_qiov, 0, 0);
79
if (ret < 0) {
80
return ret;
81
}
82
@@ -XXX,XX +XXX,XX @@ static int bdrv_padding_rmw_read(BdrvChild *child,
83
ret = bdrv_aligned_preadv(
84
child, req,
85
req->overlap_offset + req->overlap_bytes - align,
86
- align, align, &local_qiov, 0);
87
+ align, align, &local_qiov, 0, 0);
88
if (ret < 0) {
89
return ret;
90
}
91
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child,
92
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ);
93
ret = bdrv_aligned_preadv(child, &req, offset, bytes,
94
bs->bl.request_alignment,
95
- qiov, flags);
96
+ qiov, 0, flags);
97
tracked_request_end(&req);
98
bdrv_dec_in_flight(bs);
99
32
--
100
--
33
2.9.3
101
2.21.0
34
102
35
103
diff view generated by jsdifflib
1
Signed-off-by: Jeff Cody <jcody@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2
3
Reviewed-by: John Snow <jsnow@redhat.com>
3
Use and support new API in bdrv_aligned_pwritev.
4
Message-id: 00aed7ffdd7be4b9ed9ce1007d50028a72b34ebe.1491597120.git.jcody@redhat.com
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Message-id: 20190604161514.262241-9-vsementsov@virtuozzo.com
8
Message-Id: <20190604161514.262241-9-vsementsov@virtuozzo.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
---
10
---
6
block.c | 14 ++++++++------
11
block/io.c | 27 +++++++++++++--------------
7
1 file changed, 8 insertions(+), 6 deletions(-)
12
1 file changed, 13 insertions(+), 14 deletions(-)
8
13
9
diff --git a/block.c b/block.c
14
diff --git a/block/io.c b/block/io.c
10
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
11
--- a/block.c
16
--- a/block/io.c
12
+++ b/block.c
17
+++ b/block/io.c
13
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
18
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
14
BlockDriver *drv;
19
*/
15
QemuOpts *opts;
20
static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
16
const char *value;
21
BdrvTrackedRequest *req, int64_t offset, unsigned int bytes,
17
+ bool read_only;
22
- int64_t align, QEMUIOVector *qiov, int flags)
18
23
+ int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
19
assert(reopen_state != NULL);
24
{
20
assert(reopen_state->bs->drv != NULL);
25
BlockDriverState *bs = child->bs;
21
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
26
BlockDriver *drv = bs->drv;
22
qdict_put(reopen_state->options, "driver", qstring_from_str(value));
27
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
28
assert(is_power_of_2(align));
29
assert((offset & (align - 1)) == 0);
30
assert((bytes & (align - 1)) == 0);
31
- assert(!qiov || bytes == qiov->size);
32
+ assert(!qiov || qiov_offset + bytes <= qiov->size);
33
max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX),
34
align);
35
36
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
37
38
if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF &&
39
!(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_pwrite_zeroes &&
40
- qemu_iovec_is_zero(qiov, 0, qiov->size)) {
41
+ qemu_iovec_is_zero(qiov, qiov_offset, bytes)) {
42
flags |= BDRV_REQ_ZERO_WRITE;
43
if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) {
44
flags |= BDRV_REQ_MAY_UNMAP;
45
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
46
bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
47
ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
48
} else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
49
- ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov, 0);
50
+ ret = bdrv_driver_pwritev_compressed(bs, offset, bytes,
51
+ qiov, qiov_offset);
52
} else if (bytes <= max_transfer) {
53
bdrv_debug_event(bs, BLKDBG_PWRITEV);
54
- ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, 0, flags);
55
+ ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, qiov_offset, flags);
56
} else {
57
bdrv_debug_event(bs, BLKDBG_PWRITEV);
58
while (bytes_remaining) {
59
int num = MIN(bytes_remaining, max_transfer);
60
- QEMUIOVector local_qiov;
61
int local_flags = flags;
62
63
assert(num);
64
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
65
* need to flush on the last iteration */
66
local_flags &= ~BDRV_REQ_FUA;
67
}
68
- qemu_iovec_init(&local_qiov, qiov->niov);
69
- qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num);
70
71
ret = bdrv_driver_pwritev(bs, offset + bytes - bytes_remaining,
72
- num, &local_qiov, 0, local_flags);
73
- qemu_iovec_destroy(&local_qiov);
74
+ num, qiov, bytes - bytes_remaining,
75
+ local_flags);
76
if (ret < 0) {
77
break;
78
}
79
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
80
81
qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes);
82
ret = bdrv_aligned_pwritev(child, req, aligned_offset, write_bytes,
83
- align, &local_qiov,
84
+ align, &local_qiov, 0,
85
flags & ~BDRV_REQ_ZERO_WRITE);
86
if (ret < 0 || pad.merge_reads) {
87
/* Error or all work is done */
88
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
89
/* Write the aligned part in the middle. */
90
uint64_t aligned_bytes = bytes & ~(align - 1);
91
ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align,
92
- NULL, flags);
93
+ NULL, 0, flags);
94
if (ret < 0) {
95
goto out;
96
}
97
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
98
99
qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align);
100
ret = bdrv_aligned_pwritev(child, req, offset, align, align,
101
- &local_qiov, flags & ~BDRV_REQ_ZERO_WRITE);
102
+ &local_qiov, 0,
103
+ flags & ~BDRV_REQ_ZERO_WRITE);
23
}
104
}
24
105
25
- /* if we are to stay read-only, do not allow permission change
106
out:
26
- * to r/w */
107
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
27
- if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) &&
28
- reopen_state->flags & BDRV_O_RDWR) {
29
- error_setg(errp, "Node '%s' is read only",
30
- bdrv_get_device_or_node_name(reopen_state->bs));
31
+ /* If we are to stay read-only, do not allow permission change
32
+ * to r/w. Attempting to set to r/w may fail if either BDRV_O_ALLOW_RDWR is
33
+ * not set, or if the BDS still has copy_on_read enabled */
34
+ read_only = !(reopen_state->flags & BDRV_O_RDWR);
35
+ ret = bdrv_can_set_read_only(reopen_state->bs, read_only, &local_err);
36
+ if (local_err) {
37
+ error_propagate(errp, local_err);
38
goto error;
39
}
108
}
40
109
110
ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align,
111
- qiov, flags);
112
+ qiov, 0, flags);
113
114
bdrv_padding_destroy(&pad);
115
41
--
116
--
42
2.9.3
117
2.21.0
43
118
44
119
diff view generated by jsdifflib
1
We have a helper wrapper for checking for the BDS read_only flag,
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
add a helper wrapper to set the read_only flag as well.
3
2
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
3
Introduce extended variants of bdrv_co_preadv and bdrv_co_pwritev
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
4
with qiov_offset parameter.
6
Reviewed-by: John Snow <jsnow@redhat.com>
5
7
Message-id: 9b18972d05f5fa2ac16c014f0af98d680553048d.1491597120.git.jcody@redhat.com
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-id: 20190604161514.262241-10-vsementsov@virtuozzo.com
9
Message-Id: <20190604161514.262241-10-vsementsov@virtuozzo.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
11
---
9
block.c | 5 +++++
12
include/block/block_int.h | 6 ++++++
10
block/bochs.c | 2 +-
13
block/io.c | 29 +++++++++++++++++++++++------
11
block/cloop.c | 2 +-
14
2 files changed, 29 insertions(+), 6 deletions(-)
12
block/dmg.c | 2 +-
13
block/rbd.c | 2 +-
14
block/vvfat.c | 4 ++--
15
include/block/block.h | 1 +
16
7 files changed, 12 insertions(+), 6 deletions(-)
17
15
18
diff --git a/block.c b/block.c
16
diff --git a/include/block/block_int.h b/include/block/block_int.h
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
18
--- a/include/block/block_int.h
21
+++ b/block.c
19
+++ b/include/block/block_int.h
22
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
20
@@ -XXX,XX +XXX,XX @@ extern BlockDriver bdrv_qcow2;
21
int coroutine_fn bdrv_co_preadv(BdrvChild *child,
22
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
23
BdrvRequestFlags flags);
24
+int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
25
+ int64_t offset, unsigned int bytes,
26
+ QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
27
int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
28
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
29
BdrvRequestFlags flags);
30
+int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
31
+ int64_t offset, unsigned int bytes,
32
+ QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
33
34
static inline int coroutine_fn bdrv_co_pread(BdrvChild *child,
35
int64_t offset, unsigned int bytes, void *buf, BdrvRequestFlags flags)
36
diff --git a/block/io.c b/block/io.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/block/io.c
39
+++ b/block/io.c
40
@@ -XXX,XX +XXX,XX @@ static void bdrv_padding_destroy(BdrvRequestPadding *pad)
41
*
42
* Function always succeeds.
43
*/
44
-static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov,
45
+static bool bdrv_pad_request(BlockDriverState *bs,
46
+ QEMUIOVector **qiov, size_t *qiov_offset,
47
int64_t *offset, unsigned int *bytes,
48
BdrvRequestPadding *pad)
49
{
50
@@ -XXX,XX +XXX,XX @@ static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov,
23
}
51
}
52
53
qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head,
54
- *qiov, 0, *bytes,
55
+ *qiov, *qiov_offset, *bytes,
56
pad->buf + pad->buf_len - pad->tail, pad->tail);
57
*bytes += pad->head + pad->tail;
58
*offset -= pad->head;
59
*qiov = &pad->local_qiov;
60
+ *qiov_offset = 0;
61
62
return true;
24
}
63
}
25
64
@@ -XXX,XX +XXX,XX @@ static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov,
26
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
65
int coroutine_fn bdrv_co_preadv(BdrvChild *child,
66
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
67
BdrvRequestFlags flags)
27
+{
68
+{
28
+ bs->read_only = read_only;
69
+ return bdrv_co_preadv_part(child, offset, bytes, qiov, 0, flags);
29
+}
70
+}
30
+
71
+
31
void bdrv_get_full_backing_filename_from_filename(const char *backed,
72
+int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
32
const char *backing,
73
+ int64_t offset, unsigned int bytes,
33
char *dest, size_t sz,
74
+ QEMUIOVector *qiov, size_t qiov_offset,
34
diff --git a/block/bochs.c b/block/bochs.c
75
+ BdrvRequestFlags flags)
35
index XXXXXXX..XXXXXXX 100644
76
{
36
--- a/block/bochs.c
77
BlockDriverState *bs = child->bs;
37
+++ b/block/bochs.c
78
BdrvTrackedRequest req;
38
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
79
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child,
39
return -EINVAL;
80
flags |= BDRV_REQ_COPY_ON_READ;
40
}
81
}
41
82
42
- bs->read_only = true; /* no write support yet */
83
- bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad);
43
+ bdrv_set_read_only(bs, true); /* no write support yet */
84
+ bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad);
44
85
45
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
86
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ);
46
if (ret < 0) {
87
ret = bdrv_aligned_preadv(child, &req, offset, bytes,
47
diff --git a/block/cloop.c b/block/cloop.c
88
bs->bl.request_alignment,
48
index XXXXXXX..XXXXXXX 100644
89
- qiov, 0, flags);
49
--- a/block/cloop.c
90
+ qiov, qiov_offset, flags);
50
+++ b/block/cloop.c
91
tracked_request_end(&req);
51
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
92
bdrv_dec_in_flight(bs);
52
return -EINVAL;
93
94
@@ -XXX,XX +XXX,XX @@ out:
95
int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
96
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
97
BdrvRequestFlags flags)
98
+{
99
+ return bdrv_co_pwritev_part(child, offset, bytes, qiov, 0, flags);
100
+}
101
+
102
+int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
103
+ int64_t offset, unsigned int bytes, QEMUIOVector *qiov, size_t qiov_offset,
104
+ BdrvRequestFlags flags)
105
{
106
BlockDriverState *bs = child->bs;
107
BdrvTrackedRequest req;
108
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
109
goto out;
53
}
110
}
54
111
55
- bs->read_only = true;
112
- if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) {
56
+ bdrv_set_read_only(bs, true);
113
+ if (bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad)) {
57
114
mark_request_serialising(&req, align);
58
/* read header */
115
wait_serialising_requests(&req);
59
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
116
bdrv_padding_rmw_read(child, &req, &pad, false);
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
}
117
}
66
118
67
block_module_load_one("dmg-bz2");
119
ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align,
68
- bs->read_only = true;
120
- qiov, 0, flags);
69
+ bdrv_set_read_only(bs, true);
121
+ qiov, qiov_offset, flags);
70
122
71
s->n_chunks = 0;
123
bdrv_padding_destroy(&pad);
72
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
124
73
diff --git a/block/rbd.c b/block/rbd.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/rbd.c
76
+++ b/block/rbd.c
77
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
78
goto failed_open;
79
}
80
81
- bs->read_only = (s->snap != NULL);
82
+ bdrv_set_read_only(bs, (s->snap != NULL));
83
84
qemu_opts_del(opts);
85
return 0;
86
diff --git a/block/vvfat.c b/block/vvfat.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/vvfat.c
89
+++ b/block/vvfat.c
90
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
91
s->current_cluster=0xffffffff;
92
93
/* read only is the default for safety */
94
- bs->read_only = true;
95
+ bdrv_set_read_only(bs, true);
96
s->qcow = NULL;
97
s->qcow_filename = NULL;
98
s->fat2 = NULL;
99
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
100
if (ret < 0) {
101
goto fail;
102
}
103
- bs->read_only = false;
104
+ bdrv_set_read_only(bs, false);
105
}
106
107
bs->total_sectors = cyls * heads * secs;
108
diff --git a/include/block/block.h b/include/block/block.h
109
index XXXXXXX..XXXXXXX 100644
110
--- a/include/block/block.h
111
+++ b/include/block/block.h
112
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
113
int64_t sector_num, int nb_sectors, int *pnum);
114
115
bool bdrv_is_read_only(BlockDriverState *bs);
116
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only);
117
bool bdrv_is_sg(BlockDriverState *bs);
118
bool bdrv_is_inserted(BlockDriverState *bs);
119
int bdrv_media_changed(BlockDriverState *bs);
120
--
125
--
121
2.9.3
126
2.21.0
122
127
123
128
diff view generated by jsdifflib
1
The protocol VXHS does not support image creation. Some tests expect
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
to be able to create images through the protocol. Exclude VXHS from
3
these tests.
4
2
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
Use buffer based io in encrypted case.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Message-id: 20190604161514.262241-11-vsementsov@virtuozzo.com
8
Message-Id: <20190604161514.262241-11-vsementsov@virtuozzo.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
10
---
7
tests/qemu-iotests/017 | 1 +
11
block/qcow2.c | 28 ++++++++++++++++------------
8
tests/qemu-iotests/020 | 1 +
12
1 file changed, 16 insertions(+), 12 deletions(-)
9
tests/qemu-iotests/029 | 1 +
10
tests/qemu-iotests/073 | 1 +
11
tests/qemu-iotests/114 | 1 +
12
tests/qemu-iotests/130 | 1 +
13
tests/qemu-iotests/134 | 1 +
14
tests/qemu-iotests/156 | 1 +
15
tests/qemu-iotests/158 | 1 +
16
9 files changed, 9 insertions(+)
17
13
18
diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017
14
diff --git a/block/qcow2.c b/block/qcow2.c
19
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/017
16
--- a/block/qcow2.c
21
+++ b/tests/qemu-iotests/017
17
+++ b/block/qcow2.c
22
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
18
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
23
# Any format supporting backing files
19
}
24
_supported_fmt qcow qcow2 vmdk qed
20
25
_supported_proto generic
21
assert(cur_bytes <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
26
+_unsupported_proto vxhs
22
- qemu_iovec_reset(&hd_qiov);
27
_supported_os Linux
23
- qemu_iovec_add(&hd_qiov, cluster_data, cur_bytes);
28
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
24
- }
29
25
30
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
26
- BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
31
index XXXXXXX..XXXXXXX 100755
27
- ret = bdrv_co_preadv(s->data_file,
32
--- a/tests/qemu-iotests/020
28
- cluster_offset + offset_in_cluster,
33
+++ b/tests/qemu-iotests/020
29
- cur_bytes, &hd_qiov, 0);
34
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
30
- if (ret < 0) {
35
# Any format supporting backing files
31
- goto fail;
36
_supported_fmt qcow qcow2 vmdk qed
32
- }
37
_supported_proto generic
33
- if (bs->encrypted) {
38
+_unsupported_proto vxhs
34
- assert(s->crypto);
39
_supported_os Linux
35
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
40
_unsupported_imgopts "subformat=monolithicFlat" \
36
+ ret = bdrv_co_pread(s->data_file,
41
"subformat=twoGbMaxExtentFlat" \
37
+ cluster_offset + offset_in_cluster,
42
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
38
+ cur_bytes, cluster_data, 0);
43
index XXXXXXX..XXXXXXX 100755
39
+ if (ret < 0) {
44
--- a/tests/qemu-iotests/029
40
+ goto fail;
45
+++ b/tests/qemu-iotests/029
41
+ }
46
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
42
+
47
# Any format supporting intenal snapshots
43
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
48
_supported_fmt qcow2
44
assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
49
_supported_proto generic
45
if (qcow2_co_decrypt(bs, cluster_offset, offset,
50
+_unsupported_proto vxhs
46
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
51
_supported_os Linux
47
goto fail;
52
# Internal snapshots are (currently) impossible with refcount_bits=1
48
}
53
_unsupported_imgopts 'refcount_bits=1[^0-9]'
49
qemu_iovec_from_buf(qiov, bytes_done, cluster_data, cur_bytes);
54
diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073
50
+ } else {
55
index XXXXXXX..XXXXXXX 100755
51
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
56
--- a/tests/qemu-iotests/073
52
+ ret = bdrv_co_preadv(s->data_file,
57
+++ b/tests/qemu-iotests/073
53
+ cluster_offset + offset_in_cluster,
58
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
54
+ cur_bytes, &hd_qiov, 0);
59
55
+ if (ret < 0) {
60
_supported_fmt qcow2
56
+ goto fail;
61
_supported_proto generic
57
+ }
62
+_unsupported_proto vxhs
58
}
63
_supported_os Linux
59
break;
64
65
CLUSTER_SIZE=64k
66
diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114
67
index XXXXXXX..XXXXXXX 100755
68
--- a/tests/qemu-iotests/114
69
+++ b/tests/qemu-iotests/114
70
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
71
72
_supported_fmt qcow2
73
_supported_proto generic
74
+_unsupported_proto vxhs
75
_supported_os Linux
76
77
78
diff --git a/tests/qemu-iotests/130 b/tests/qemu-iotests/130
79
index XXXXXXX..XXXXXXX 100755
80
--- a/tests/qemu-iotests/130
81
+++ b/tests/qemu-iotests/130
82
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
83
84
_supported_fmt qcow2
85
_supported_proto generic
86
+_unsupported_proto vxhs
87
_supported_os Linux
88
89
qemu_comm_method="monitor"
90
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
91
index XXXXXXX..XXXXXXX 100755
92
--- a/tests/qemu-iotests/134
93
+++ b/tests/qemu-iotests/134
94
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
95
96
_supported_fmt qcow2
97
_supported_proto generic
98
+_unsupported_proto vxhs
99
_supported_os Linux
100
101
102
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
103
index XXXXXXX..XXXXXXX 100755
104
--- a/tests/qemu-iotests/156
105
+++ b/tests/qemu-iotests/156
106
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
107
108
_supported_fmt qcow2 qed
109
_supported_proto generic
110
+_unsupported_proto vxhs
111
_supported_os Linux
112
113
# Create source disk
114
diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158
115
index XXXXXXX..XXXXXXX 100755
116
--- a/tests/qemu-iotests/158
117
+++ b/tests/qemu-iotests/158
118
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
119
120
_supported_fmt qcow2
121
_supported_proto generic
122
+_unsupported_proto vxhs
123
_supported_os Linux
124
125
60
126
--
61
--
127
2.9.3
62
2.21.0
128
63
129
64
diff view generated by jsdifflib
1
From: Ashish Mittal <ashmit602@gmail.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
These changes use a vxhs test server that is a part of the following
3
Implement and use new interface to get rid of hd_qiov.
4
repository:
5
https://github.com/VeritasHyperScale/libqnio.git
6
4
7
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
7
Message-id: 20190604161514.262241-12-vsementsov@virtuozzo.com
10
Signed-off-by: Jeff Cody <jcody@redhat.com>
8
Message-Id: <20190604161514.262241-12-vsementsov@virtuozzo.com>
11
Message-id: 1491277689-24949-3-git-send-email-Ashish.Mittal@veritas.com
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
10
---
13
tests/qemu-iotests/common | 6 ++++++
11
block/qcow2-cluster.c | 5 +++--
14
tests/qemu-iotests/common.config | 13 +++++++++++++
12
block/qcow2.c | 49 +++++++++++++++++++------------------------
15
tests/qemu-iotests/common.filter | 1 +
13
2 files changed, 25 insertions(+), 29 deletions(-)
16
tests/qemu-iotests/common.rc | 19 +++++++++++++++++++
17
4 files changed, 39 insertions(+)
18
14
19
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
15
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/common
17
--- a/block/qcow2-cluster.c
22
+++ b/tests/qemu-iotests/common
18
+++ b/block/qcow2-cluster.c
23
@@ -XXX,XX +XXX,XX @@ check options
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
24
-ssh test ssh
20
* interface. This avoids double I/O throttling and request tracking,
25
-nfs test nfs
21
* which can lead to deadlock when block layer copy-on-read is enabled.
26
-luks test luks
22
*/
27
+ -vxhs test vxhs
23
- ret = bs->drv->bdrv_co_preadv(bs, src_cluster_offset + offset_in_cluster,
28
-xdiff graphical mode diff
24
- qiov->size, qiov, 0);
29
-nocache use O_DIRECT on backing file
25
+ ret = bs->drv->bdrv_co_preadv_part(bs,
30
-misalign misalign memory allocations
26
+ src_cluster_offset + offset_in_cluster,
31
@@ -XXX,XX +XXX,XX @@ testlist options
27
+ qiov->size, qiov, 0, 0);
32
xpand=false
28
if (ret < 0) {
33
;;
29
return ret;
34
30
}
35
+ -vxhs)
31
diff --git a/block/qcow2.c b/block/qcow2.c
36
+ IMGPROTO=vxhs
37
+ xpand=false
38
+ ;;
39
+
40
-ssh)
41
IMGPROTO=ssh
42
xpand=false
43
diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
44
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
45
--- a/tests/qemu-iotests/common.config
33
--- a/block/qcow2.c
46
+++ b/tests/qemu-iotests/common.config
34
+++ b/block/qcow2.c
47
@@ -XXX,XX +XXX,XX @@ if [ -z "$QEMU_NBD_PROG" ]; then
35
@@ -XXX,XX +XXX,XX @@ qcow2_co_preadv_compressed(BlockDriverState *bs,
48
export QEMU_NBD_PROG="`set_prog_path qemu-nbd`"
36
uint64_t file_cluster_offset,
49
fi
37
uint64_t offset,
50
38
uint64_t bytes,
51
+if [ -z "$QEMU_VXHS_PROG" ]; then
39
- QEMUIOVector *qiov);
52
+ export QEMU_VXHS_PROG="`set_prog_path qnio_server`"
40
+ QEMUIOVector *qiov,
53
+fi
41
+ size_t qiov_offset);
54
+
42
55
_qemu_wrapper()
43
static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
56
{
44
{
57
(
45
@@ -XXX,XX +XXX,XX @@ out:
58
@@ -XXX,XX +XXX,XX @@ _qemu_nbd_wrapper()
46
return ret;
59
)
60
}
47
}
61
48
62
+_qemu_vxhs_wrapper()
49
-static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
63
+{
50
- uint64_t bytes, QEMUIOVector *qiov,
64
+ (
51
- int flags)
65
+ echo $BASHPID > "${TEST_DIR}/qemu-vxhs.pid"
52
+static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
66
+ exec "$QEMU_VXHS_PROG" $QEMU_VXHS_OPTIONS "$@"
53
+ uint64_t offset, uint64_t bytes,
67
+ )
54
+ QEMUIOVector *qiov,
68
+}
55
+ size_t qiov_offset, int flags)
69
+
56
{
70
export QEMU=_qemu_wrapper
57
BDRVQcow2State *s = bs->opaque;
71
export QEMU_IMG=_qemu_img_wrapper
58
int offset_in_cluster;
72
export QEMU_IO=_qemu_io_wrapper
59
int ret;
73
export QEMU_NBD=_qemu_nbd_wrapper
60
unsigned int cur_bytes; /* number of bytes in current iteration */
74
+export QEMU_VXHS=_qemu_vxhs_wrapper
61
uint64_t cluster_offset = 0;
75
62
- uint64_t bytes_done = 0;
76
QEMU_IMG_EXTRA_ARGS=
63
- QEMUIOVector hd_qiov;
77
if [ "$IMGOPTSSYNTAX" = "true" ]; then
64
uint8_t *cluster_data = NULL;
78
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
65
79
index XXXXXXX..XXXXXXX 100644
66
- qemu_iovec_init(&hd_qiov, qiov->niov);
80
--- a/tests/qemu-iotests/common.filter
67
-
81
+++ b/tests/qemu-iotests/common.filter
68
while (bytes != 0) {
82
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
69
83
-e "s#$TEST_DIR#TEST_DIR#g" \
70
/* prepare next request */
84
-e "s#$IMGFMT#IMGFMT#g" \
71
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
85
-e 's#nbd://127.0.0.1:10810$#TEST_DIR/t.IMGFMT#g' \
72
86
+ -e 's#json.*vdisk-id.*vxhs"}}#TEST_DIR/t.IMGFMT#' \
73
offset_in_cluster = offset_into_cluster(s, offset);
87
-e "/encrypted: yes/d" \
74
88
-e "/cluster_size: [0-9]\\+/d" \
75
- qemu_iovec_reset(&hd_qiov);
89
-e "/table_size: [0-9]\\+/d" \
76
- qemu_iovec_concat(&hd_qiov, qiov, bytes_done, cur_bytes);
90
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
77
-
91
index XXXXXXX..XXXXXXX 100644
78
switch (ret) {
92
--- a/tests/qemu-iotests/common.rc
79
case QCOW2_CLUSTER_UNALLOCATED:
93
+++ b/tests/qemu-iotests/common.rc
80
94
@@ -XXX,XX +XXX,XX @@ else
81
if (bs->backing) {
95
elif [ "$IMGPROTO" = "nfs" ]; then
82
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
96
TEST_DIR="nfs://127.0.0.1/$TEST_DIR"
83
- ret = bdrv_co_preadv(bs->backing, offset, cur_bytes,
97
TEST_IMG=$TEST_DIR/t.$IMGFMT
84
- &hd_qiov, 0);
98
+ elif [ "$IMGPROTO" = "vxhs" ]; then
85
+ ret = bdrv_co_preadv_part(bs->backing, offset, cur_bytes,
99
+ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
86
+ qiov, qiov_offset, 0);
100
+ TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT"
87
if (ret < 0) {
101
else
88
goto fail;
102
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
89
}
103
fi
90
} else {
104
@@ -XXX,XX +XXX,XX @@ _make_test_img()
91
/* Note: in this case, no need to wait */
105
eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT $TEST_IMG_FILE >/dev/null &"
92
- qemu_iovec_memset(&hd_qiov, 0, 0, cur_bytes);
106
sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
93
+ qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
107
fi
94
}
108
+
95
break;
109
+ # Start QNIO server on image directory for vxhs protocol
96
110
+ if [ $IMGPROTO = "vxhs" ]; then
97
case QCOW2_CLUSTER_ZERO_PLAIN:
111
+ eval "$QEMU_VXHS -d $TEST_DIR > /dev/null &"
98
case QCOW2_CLUSTER_ZERO_ALLOC:
112
+ sleep 1 # Wait for server to come up.
99
- qemu_iovec_memset(&hd_qiov, 0, 0, cur_bytes);
113
+ fi
100
+ qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
101
break;
102
103
case QCOW2_CLUSTER_COMPRESSED:
104
ret = qcow2_co_preadv_compressed(bs, cluster_offset,
105
offset, cur_bytes,
106
- &hd_qiov);
107
+ qiov, qiov_offset);
108
if (ret < 0) {
109
goto fail;
110
}
111
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
112
ret = -EIO;
113
goto fail;
114
}
115
- qemu_iovec_from_buf(qiov, bytes_done, cluster_data, cur_bytes);
116
+ qemu_iovec_from_buf(qiov, qiov_offset, cluster_data, cur_bytes);
117
} else {
118
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
119
- ret = bdrv_co_preadv(s->data_file,
120
- cluster_offset + offset_in_cluster,
121
- cur_bytes, &hd_qiov, 0);
122
+ ret = bdrv_co_preadv_part(s->data_file,
123
+ cluster_offset + offset_in_cluster,
124
+ cur_bytes, qiov, qiov_offset, 0);
125
if (ret < 0) {
126
goto fail;
127
}
128
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
129
130
bytes -= cur_bytes;
131
offset += cur_bytes;
132
- bytes_done += cur_bytes;
133
+ qiov_offset += cur_bytes;
134
}
135
ret = 0;
136
137
fail:
138
- qemu_iovec_destroy(&hd_qiov);
139
qemu_vfree(cluster_data);
140
141
return ret;
142
@@ -XXX,XX +XXX,XX @@ qcow2_co_preadv_compressed(BlockDriverState *bs,
143
uint64_t file_cluster_offset,
144
uint64_t offset,
145
uint64_t bytes,
146
- QEMUIOVector *qiov)
147
+ QEMUIOVector *qiov,
148
+ size_t qiov_offset)
149
{
150
BDRVQcow2State *s = bs->opaque;
151
int ret = 0, csize, nb_csectors;
152
@@ -XXX,XX +XXX,XX @@ qcow2_co_preadv_compressed(BlockDriverState *bs,
153
goto fail;
154
}
155
156
- qemu_iovec_from_buf(qiov, 0, out_buf + offset_in_cluster, bytes);
157
+ qemu_iovec_from_buf(qiov, qiov_offset, out_buf + offset_in_cluster, bytes);
158
159
fail:
160
qemu_vfree(out_buf);
161
@@ -XXX,XX +XXX,XX @@ static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
162
BDRVQcow2State *s = bs->opaque;
163
164
BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_LOAD);
165
- return bs->drv->bdrv_co_preadv(bs, qcow2_vm_state_offset(s) + pos,
166
- qiov->size, qiov, 0);
167
+ return bs->drv->bdrv_co_preadv_part(bs, qcow2_vm_state_offset(s) + pos,
168
+ qiov->size, qiov, 0, 0);
114
}
169
}
115
170
116
_rm_test_img()
171
/*
117
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img()
172
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
118
fi
173
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
119
rm -f "$TEST_IMG_FILE"
174
.bdrv_co_block_status = qcow2_co_block_status,
120
;;
175
121
+ vxhs)
176
- .bdrv_co_preadv = qcow2_co_preadv,
122
+ if [ -f "${TEST_DIR}/qemu-vxhs.pid" ]; then
177
+ .bdrv_co_preadv_part = qcow2_co_preadv_part,
123
+ local QEMU_VXHS_PID
178
.bdrv_co_pwritev = qcow2_co_pwritev,
124
+ read QEMU_VXHS_PID < "${TEST_DIR}/qemu-vxhs.pid"
179
.bdrv_co_flush_to_os = qcow2_co_flush_to_os,
125
+ kill ${QEMU_VXHS_PID} >/dev/null 2>&1
180
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
--
181
--
135
2.9.3
182
2.21.0
136
183
137
184
diff view generated by jsdifflib
1
Move bdrv_is_read_only() up with its friends.
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
3
Implement and use new interface to get rid of hd_qiov.
4
Reviewed-by: John Snow <jsnow@redhat.com>
4
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-id: 73b2399459760c32506f9407efb9dddb3a2789de.1491597120.git.jcody@redhat.com
6
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Message-id: 20190604161514.262241-13-vsementsov@virtuozzo.com
8
Message-Id: <20190604161514.262241-13-vsementsov@virtuozzo.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
---
10
---
8
block.c | 10 +++++-----
11
block/qcow2.h | 1 +
9
1 file changed, 5 insertions(+), 5 deletions(-)
12
include/qemu/iov.h | 1 +
10
13
block/qcow2-cluster.c | 9 ++++---
11
diff --git a/block.c b/block.c
14
block/qcow2.c | 60 +++++++++++++++++++++----------------------
12
index XXXXXXX..XXXXXXX 100644
15
util/iov.c | 10 ++++++++
13
--- a/block.c
16
5 files changed, 48 insertions(+), 33 deletions(-)
14
+++ b/block.c
17
15
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
18
diff --git a/block/qcow2.h b/block/qcow2.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow2.h
21
+++ b/block/qcow2.h
22
@@ -XXX,XX +XXX,XX @@ typedef struct QCowL2Meta
23
* from @cow_start and @cow_end into one single write operation.
24
*/
25
QEMUIOVector *data_qiov;
26
+ size_t data_qiov_offset;
27
28
/** Pointer to next L2Meta of the same write request */
29
struct QCowL2Meta *next;
30
diff --git a/include/qemu/iov.h b/include/qemu/iov.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/qemu/iov.h
33
+++ b/include/qemu/iov.h
34
@@ -XXX,XX +XXX,XX @@ void qemu_iovec_init_extended(
35
void *tail_buf, size_t tail_len);
36
void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
37
size_t offset, size_t len);
38
+int qemu_iovec_subvec_niov(QEMUIOVector *qiov, size_t offset, size_t len);
39
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
40
void qemu_iovec_concat(QEMUIOVector *dst,
41
QEMUIOVector *src, size_t soffset, size_t sbytes);
42
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/block/qcow2-cluster.c
45
+++ b/block/qcow2-cluster.c
46
@@ -XXX,XX +XXX,XX @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
47
assert(start->nb_bytes <= UINT_MAX - end->nb_bytes);
48
assert(start->nb_bytes + end->nb_bytes <= UINT_MAX - data_bytes);
49
assert(start->offset + start->nb_bytes <= end->offset);
50
- assert(!m->data_qiov || m->data_qiov->size == data_bytes);
51
52
if ((start->nb_bytes == 0 && end->nb_bytes == 0) || m->skip_cow) {
53
return 0;
54
@@ -XXX,XX +XXX,XX @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
55
/* The part of the buffer where the end region is located */
56
end_buffer = start_buffer + buffer_size - end->nb_bytes;
57
58
- qemu_iovec_init(&qiov, 2 + (m->data_qiov ? m->data_qiov->niov : 0));
59
+ qemu_iovec_init(&qiov, 2 + (m->data_qiov ?
60
+ qemu_iovec_subvec_niov(m->data_qiov,
61
+ m->data_qiov_offset,
62
+ data_bytes)
63
+ : 0));
64
65
qemu_co_mutex_unlock(&s->lock);
66
/* First we read the existing data from both COW regions. We
67
@@ -XXX,XX +XXX,XX @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
68
if (start->nb_bytes) {
69
qemu_iovec_add(&qiov, start_buffer, start->nb_bytes);
70
}
71
- qemu_iovec_concat(&qiov, m->data_qiov, 0, data_bytes);
72
+ qemu_iovec_concat(&qiov, m->data_qiov, m->data_qiov_offset, data_bytes);
73
if (end->nb_bytes) {
74
qemu_iovec_add(&qiov, end_buffer, end->nb_bytes);
75
}
76
diff --git a/block/qcow2.c b/block/qcow2.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/block/qcow2.c
79
+++ b/block/qcow2.c
80
@@ -XXX,XX +XXX,XX @@ fail:
81
/* Check if it's possible to merge a write request with the writing of
82
* the data from the COW regions */
83
static bool merge_cow(uint64_t offset, unsigned bytes,
84
- QEMUIOVector *hd_qiov, QCowL2Meta *l2meta)
85
+ QEMUIOVector *qiov, size_t qiov_offset,
86
+ QCowL2Meta *l2meta)
87
{
88
QCowL2Meta *m;
89
90
@@ -XXX,XX +XXX,XX @@ static bool merge_cow(uint64_t offset, unsigned bytes,
91
92
/* Make sure that adding both COW regions to the QEMUIOVector
93
* does not exceed IOV_MAX */
94
- if (hd_qiov->niov > IOV_MAX - 2) {
95
+ if (qemu_iovec_subvec_niov(qiov, qiov_offset, bytes) > IOV_MAX - 2) {
96
continue;
97
}
98
99
- m->data_qiov = hd_qiov;
100
+ m->data_qiov = qiov;
101
+ m->data_qiov_offset = qiov_offset;
102
return true;
16
}
103
}
104
105
@@ -XXX,XX +XXX,XX @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
106
return 0;
17
}
107
}
18
108
19
+bool bdrv_is_read_only(BlockDriverState *bs)
109
-static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
110
- uint64_t bytes, QEMUIOVector *qiov,
111
- int flags)
112
+static coroutine_fn int qcow2_co_pwritev_part(
113
+ BlockDriverState *bs, uint64_t offset, uint64_t bytes,
114
+ QEMUIOVector *qiov, size_t qiov_offset, int flags)
115
{
116
BDRVQcow2State *s = bs->opaque;
117
int offset_in_cluster;
118
int ret;
119
unsigned int cur_bytes; /* number of sectors in current iteration */
120
uint64_t cluster_offset;
121
- QEMUIOVector hd_qiov;
122
+ QEMUIOVector encrypted_qiov;
123
uint64_t bytes_done = 0;
124
uint8_t *cluster_data = NULL;
125
QCowL2Meta *l2meta = NULL;
126
127
trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
128
129
- qemu_iovec_init(&hd_qiov, qiov->niov);
130
-
131
qemu_co_mutex_lock(&s->lock);
132
133
while (bytes != 0) {
134
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
135
136
qemu_co_mutex_unlock(&s->lock);
137
138
- qemu_iovec_reset(&hd_qiov);
139
- qemu_iovec_concat(&hd_qiov, qiov, bytes_done, cur_bytes);
140
-
141
if (bs->encrypted) {
142
assert(s->crypto);
143
if (!cluster_data) {
144
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
145
}
146
}
147
148
- assert(hd_qiov.size <=
149
- QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
150
- qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);
151
+ assert(cur_bytes <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
152
+ qemu_iovec_to_buf(qiov, qiov_offset + bytes_done,
153
+ cluster_data, cur_bytes);
154
155
if (qcow2_co_encrypt(bs, cluster_offset, offset,
156
cluster_data, cur_bytes) < 0) {
157
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
158
goto out_unlocked;
159
}
160
161
- qemu_iovec_reset(&hd_qiov);
162
- qemu_iovec_add(&hd_qiov, cluster_data, cur_bytes);
163
+ qemu_iovec_init_buf(&encrypted_qiov, cluster_data, cur_bytes);
164
}
165
166
/* Try to efficiently initialize the physical space with zeroes */
167
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
168
* writing of the guest data together with that of the COW regions.
169
* If it's not possible (or not necessary) then write the
170
* guest data now. */
171
- if (!merge_cow(offset, cur_bytes, &hd_qiov, l2meta)) {
172
+ if (!merge_cow(offset, cur_bytes,
173
+ bs->encrypted ? &encrypted_qiov : qiov,
174
+ bs->encrypted ? 0 : qiov_offset + bytes_done, l2meta))
175
+ {
176
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
177
trace_qcow2_writev_data(qemu_coroutine_self(),
178
cluster_offset + offset_in_cluster);
179
- ret = bdrv_co_pwritev(s->data_file,
180
- cluster_offset + offset_in_cluster,
181
- cur_bytes, &hd_qiov, 0);
182
+ ret = bdrv_co_pwritev_part(
183
+ s->data_file, cluster_offset + offset_in_cluster, cur_bytes,
184
+ bs->encrypted ? &encrypted_qiov : qiov,
185
+ bs->encrypted ? 0 : qiov_offset + bytes_done, 0);
186
if (ret < 0) {
187
goto out_unlocked;
188
}
189
@@ -XXX,XX +XXX,XX @@ out_locked:
190
191
qemu_co_mutex_unlock(&s->lock);
192
193
- qemu_iovec_destroy(&hd_qiov);
194
qemu_vfree(cluster_data);
195
trace_qcow2_writev_done_req(qemu_coroutine_self(), ret);
196
197
@@ -XXX,XX +XXX,XX @@ fail:
198
/* XXX: put compressed sectors first, then all the cluster aligned
199
tables to avoid losing bytes in alignment */
200
static coroutine_fn int
201
-qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
202
- uint64_t bytes, QEMUIOVector *qiov)
203
+qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
204
+ uint64_t offset, uint64_t bytes,
205
+ QEMUIOVector *qiov, size_t qiov_offset)
206
{
207
BDRVQcow2State *s = bs->opaque;
208
int ret;
209
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
210
/* Zero-pad last write if image size is not cluster aligned */
211
memset(buf + bytes, 0, s->cluster_size - bytes);
212
}
213
- qemu_iovec_to_buf(qiov, 0, buf, bytes);
214
+ qemu_iovec_to_buf(qiov, qiov_offset, buf, bytes);
215
216
out_buf = g_malloc(s->cluster_size);
217
218
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
219
buf, s->cluster_size);
220
if (out_len == -ENOMEM) {
221
/* could not compress: write normal cluster */
222
- ret = qcow2_co_pwritev(bs, offset, bytes, qiov, 0);
223
+ ret = qcow2_co_pwritev_part(bs, offset, bytes, qiov, qiov_offset, 0);
224
if (ret < 0) {
225
goto fail;
226
}
227
@@ -XXX,XX +XXX,XX @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
228
BDRVQcow2State *s = bs->opaque;
229
230
BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE);
231
- return bs->drv->bdrv_co_pwritev(bs, qcow2_vm_state_offset(s) + pos,
232
- qiov->size, qiov, 0);
233
+ return bs->drv->bdrv_co_pwritev_part(bs, qcow2_vm_state_offset(s) + pos,
234
+ qiov->size, qiov, 0, 0);
235
}
236
237
static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
238
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
239
.bdrv_co_block_status = qcow2_co_block_status,
240
241
.bdrv_co_preadv_part = qcow2_co_preadv_part,
242
- .bdrv_co_pwritev = qcow2_co_pwritev,
243
+ .bdrv_co_pwritev_part = qcow2_co_pwritev_part,
244
.bdrv_co_flush_to_os = qcow2_co_flush_to_os,
245
246
.bdrv_co_pwrite_zeroes = qcow2_co_pwrite_zeroes,
247
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
248
.bdrv_co_copy_range_from = qcow2_co_copy_range_from,
249
.bdrv_co_copy_range_to = qcow2_co_copy_range_to,
250
.bdrv_co_truncate = qcow2_co_truncate,
251
- .bdrv_co_pwritev_compressed = qcow2_co_pwritev_compressed,
252
+ .bdrv_co_pwritev_compressed_part = qcow2_co_pwritev_compressed_part,
253
.bdrv_make_empty = qcow2_make_empty,
254
255
.bdrv_snapshot_create = qcow2_snapshot_create,
256
diff --git a/util/iov.c b/util/iov.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/util/iov.c
259
+++ b/util/iov.c
260
@@ -XXX,XX +XXX,XX @@ static struct iovec *qiov_slice(QEMUIOVector *qiov,
261
return iov;
262
}
263
264
+int qemu_iovec_subvec_niov(QEMUIOVector *qiov, size_t offset, size_t len)
20
+{
265
+{
21
+ return bs->read_only;
266
+ size_t head, tail;
267
+ int niov;
268
+
269
+ qiov_slice(qiov, offset, len, &head, &tail, &niov);
270
+
271
+ return niov;
22
+}
272
+}
23
+
273
+
24
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
274
/*
25
{
275
* Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov,
26
/* Do not set read_only if copy_on_read is enabled */
276
* and @tail_buf buffer into new qiov.
27
@@ -XXX,XX +XXX,XX @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
28
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
29
}
30
31
-bool bdrv_is_read_only(BlockDriverState *bs)
32
-{
33
- return bs->read_only;
34
-}
35
-
36
bool bdrv_is_sg(BlockDriverState *bs)
37
{
38
return bs->sg;
39
--
277
--
40
2.9.3
278
2.21.0
41
279
42
280
diff view generated by jsdifflib