1
The following changes since commit 063833a6ec2a6747e27c5f9866bb44c7e8de1265:
1
The following changes since commit dac03af5d5482ec7ee9c23db467bb7230b33c0d9:
2
2
3
Merge remote-tracking branch 'remotes/mcayland/tags/qemu-sparc-signed' into staging (2017-10-19 18:42:51 +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/stefanha/qemu.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 e947d47da0b16e80d237c510e9d2e80799578c7f:
9
for you to fetch changes up to 5396234b96a2ac743f48644529771498e036e698:
10
10
11
oslib-posix: Fix compiler warning and some data types (2017-10-20 11:16:27 +0200)
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
----------------------------------------------------------------
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
Stefan Weil (1):
32
block/qcow2.h | 1 +
18
oslib-posix: Fix compiler warning and some data types
33
include/block/block_int.h | 21 ++
19
34
include/qemu/iov.h | 10 +-
20
util/oslib-posix.c | 15 ++++++++-------
35
block/backup.c | 2 +-
21
1 file changed, 8 insertions(+), 7 deletions(-)
36
block/io.c | 541 +++++++++++++++++++++++---------------
37
block/qcow2-cluster.c | 14 +-
38
block/qcow2.c | 131 +++++----
39
qemu-img.c | 4 +-
40
util/iov.c | 153 +++++++++--
41
9 files changed, 568 insertions(+), 309 deletions(-)
22
42
23
--
43
--
24
2.13.6
44
2.21.0
25
45
26
46
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Introduce new initialization API, to create requests with padding. Will
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.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-id: 20190604161514.262241-2-vsementsov@virtuozzo.com
12
Message-Id: <20190604161514.262241-2-vsementsov@virtuozzo.com>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
---
15
include/qemu/iov.h | 7 +++
16
util/iov.c | 112 +++++++++++++++++++++++++++++++++++++++++++--
17
2 files changed, 114 insertions(+), 5 deletions(-)
18
19
diff --git a/include/qemu/iov.h b/include/qemu/iov.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/qemu/iov.h
22
+++ b/include/qemu/iov.h
23
@@ -XXX,XX +XXX,XX @@ static inline void *qemu_iovec_buf(QEMUIOVector *qiov)
24
25
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
26
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
27
+void qemu_iovec_init_extended(
28
+ QEMUIOVector *qiov,
29
+ void *head_buf, size_t head_len,
30
+ QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len,
31
+ void *tail_buf, size_t tail_len);
32
+void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
33
+ size_t offset, size_t len);
34
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
35
void qemu_iovec_concat(QEMUIOVector *dst,
36
QEMUIOVector *src, size_t soffset, size_t sbytes);
37
diff --git a/util/iov.c b/util/iov.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/util/iov.c
40
+++ b/util/iov.c
41
@@ -XXX,XX +XXX,XX @@ void qemu_iovec_concat(QEMUIOVector *dst,
42
qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes);
43
}
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;
60
+
61
+ return iov;
62
+}
63
+
64
+/*
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).
70
+ */
71
+static struct iovec *qiov_slice(QEMUIOVector *qiov,
72
+ size_t offset, size_t len,
73
+ size_t *head, size_t *tail, int *niov)
74
+{
75
+ struct iovec *iov, *end_iov;
76
+
77
+ assert(offset + len <= qiov->size);
78
+
79
+ iov = iov_skip_offset(qiov->iov, offset, head);
80
+ end_iov = iov_skip_offset(iov, *head + len, tail);
81
+
82
+ if (*tail > 0) {
83
+ assert(*tail < end_iov->iov_len);
84
+ *tail = end_iov->iov_len - *tail;
85
+ end_iov++;
86
+ }
87
+
88
+ *niov = end_iov - iov;
89
+
90
+ return iov;
91
+}
92
+
93
+/*
94
+ * Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov,
95
+ * and @tail_buf buffer into new qiov.
96
+ */
97
+void qemu_iovec_init_extended(
98
+ QEMUIOVector *qiov,
99
+ void *head_buf, size_t head_len,
100
+ QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len,
101
+ void *tail_buf, size_t tail_len)
102
+{
103
+ size_t mid_head, mid_tail;
104
+ int total_niov, mid_niov = 0;
105
+ struct iovec *p, *mid_iov;
106
+
107
+ if (mid_len) {
108
+ mid_iov = qiov_slice(mid_qiov, mid_offset, mid_len,
109
+ &mid_head, &mid_tail, &mid_niov);
110
+ }
111
+
112
+ total_niov = !!head_len + mid_niov + !!tail_len;
113
+ if (total_niov == 1) {
114
+ qemu_iovec_init_buf(qiov, NULL, 0);
115
+ p = &qiov->local_iov;
116
+ } else {
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);
120
+ }
121
+
122
+ if (head_len) {
123
+ p->iov_base = head_buf;
124
+ p->iov_len = head_len;
125
+ p++;
126
+ }
127
+
128
+ if (mid_len) {
129
+ memcpy(p, mid_iov, mid_niov * sizeof(*p));
130
+ p[0].iov_base = (uint8_t *)p[0].iov_base + mid_head;
131
+ p[0].iov_len -= mid_head;
132
+ p[mid_niov - 1].iov_len -= mid_tail;
133
+ p += mid_niov;
134
+ }
135
+
136
+ if (tail_len) {
137
+ p->iov_base = tail_buf;
138
+ p->iov_len = tail_len;
139
+ }
140
+}
141
+
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)
151
+{
152
+ qemu_iovec_init_extended(qiov, NULL, 0, source, offset, len, NULL, 0);
153
+}
154
+
155
void qemu_iovec_destroy(QEMUIOVector *qiov)
156
{
157
- assert(qiov->nalloc != -1);
158
+ if (qiov->nalloc != -1) {
159
+ g_free(qiov->iov);
160
+ }
161
162
- qemu_iovec_reset(qiov);
163
- g_free(qiov->iov);
164
- qiov->nalloc = 0;
165
- qiov->iov = NULL;
166
+ memset(qiov, 0, sizeof(*qiov));
167
}
168
169
void qemu_iovec_reset(QEMUIOVector *qiov)
170
--
171
2.21.0
172
173
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
We'll need to check a part of qiov soon, so implement it now.
4
5
Optimization with align down to 4 * sizeof(long) is dropped due to:
6
1. It is strange: it aligns length of the buffer, but where is a
7
guarantee that buffer pointer is aligned itself?
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>
16
---
17
include/qemu/iov.h | 2 +-
18
block/io.c | 2 +-
19
util/iov.c | 31 +++++++++++++++++++------------
20
3 files changed, 21 insertions(+), 14 deletions(-)
21
22
diff --git a/include/qemu/iov.h b/include/qemu/iov.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/qemu/iov.h
25
+++ b/include/qemu/iov.h
26
@@ -XXX,XX +XXX,XX @@ void qemu_iovec_concat(QEMUIOVector *dst,
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(
53
}
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;
69
+
70
+ assert(offset + bytes <= qiov->size);
71
+
72
+ iov = iov_skip_offset(qiov->iov, offset, &current_offset);
73
+
74
+ while (bytes) {
75
+ uint8_t *base = (uint8_t *)iov->iov_base + current_offset;
76
+ size_t len = MIN(iov->iov_len - current_offset, bytes);
77
+
78
+ if (!buffer_is_zero(base, len)) {
79
return false;
80
}
81
- for (; offs < qiov->iov[i].iov_len; offs++) {
82
- if (ptr[offs]) {
83
- return false;
84
- }
85
- }
86
+
87
+ current_offset = 0;
88
+ bytes -= len;
89
+ iov++;
90
}
91
+
92
return true;
93
}
94
95
--
96
2.21.0
97
98
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
We have similar padding code in bdrv_co_pwritev,
4
bdrv_co_do_pwrite_zeroes and bdrv_co_preadv. Let's combine and unify
5
it.
6
7
[Squashed in Vladimir's qemu-iotests 077 fix
8
--Stefan]
9
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.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>
15
---
16
block/io.c | 365 +++++++++++++++++++++++++++++------------------------
17
1 file changed, 200 insertions(+), 165 deletions(-)
18
19
diff --git a/block/io.c b/block/io.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/io.c
22
+++ b/block/io.c
23
@@ -XXX,XX +XXX,XX @@ out:
24
}
25
26
/*
27
- * Handle a read request in coroutine context
28
+ * Request padding
29
+ *
30
+ * |<---- align ----->| |<----- align ---->|
31
+ * |<- head ->|<------------- bytes ------------->|<-- tail -->|
32
+ * | | | | | |
33
+ * -*----------$-------*-------- ... --------*-----$------------*---
34
+ * | | | | | |
35
+ * | offset | | end |
36
+ * ALIGN_DOWN(offset) ALIGN_UP(offset) ALIGN_DOWN(end) ALIGN_UP(end)
37
+ * [buf ... ) [tail_buf )
38
+ *
39
+ * @buf is an aligned allocation needed to store @head and @tail paddings. @head
40
+ * is placed at the beginning of @buf and @tail at the @end.
41
+ *
42
+ * @tail_buf is a pointer to sub-buffer, corresponding to align-sized chunk
43
+ * around tail, if tail exists.
44
+ *
45
+ * @merge_reads is true for small requests,
46
+ * if @buf_len == @head + bytes + @tail. In this case it is possible that both
47
+ * head and tail exist but @buf_len == align and @tail_buf == @buf.
48
*/
49
+typedef struct BdrvRequestPadding {
50
+ uint8_t *buf;
51
+ size_t buf_len;
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);
213
if (ret < 0) {
214
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child,
215
flags |= BDRV_REQ_COPY_ON_READ;
216
}
217
218
- /* Align read if necessary by padding qiov */
219
- if (offset & (align - 1)) {
220
- head_buf = qemu_blockalign(bs, align);
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;
325
}
326
327
assert(!bytes || (offset & (align - 1)) == 0);
328
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
329
ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align,
330
NULL, flags);
331
if (ret < 0) {
332
- goto fail;
333
+ goto out;
334
}
335
bytes -= aligned_bytes;
336
offset += aligned_bytes;
337
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
338
339
assert(!bytes || (offset & (align - 1)) == 0);
340
if (bytes) {
341
- assert(align == tail_padding_bytes + bytes);
342
- /* RMW the unaligned part after tail. */
343
- mark_request_serialising(req, align);
344
- wait_serialising_requests(req);
345
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
346
- ret = bdrv_aligned_preadv(child, req, offset, align,
347
- align, &local_qiov, 0);
348
- if (ret < 0) {
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);
358
}
359
-fail:
360
- qemu_vfree(buf);
361
+
362
+out:
363
+ bdrv_padding_destroy(&pad);
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;
384
}
385
386
- if (offset & (align - 1)) {
387
- QEMUIOVector head_qiov;
388
-
389
+ if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) {
390
mark_request_serialising(&req, align);
391
wait_serialising_requests(&req);
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);
452
}
453
454
ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align,
455
- use_local_qiov ? &local_qiov : qiov,
456
- flags);
457
+ qiov, flags);
458
459
-fail:
460
+ bdrv_padding_destroy(&pad);
461
462
- if (use_local_qiov) {
463
- qemu_iovec_destroy(&local_qiov);
464
- }
465
- qemu_vfree(head_buf);
466
- qemu_vfree(tail_buf);
467
out:
468
tracked_request_end(&req);
469
bdrv_dec_in_flight(bs);
470
+
471
return ret;
472
}
473
474
--
475
2.21.0
476
477
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
Add handlers supporting qiov_offset parameter:
4
bdrv_co_preadv_part
5
bdrv_co_pwritev_part
6
bdrv_co_pwritev_compressed_part
7
This is used to reduce need of defining local_qiovs and hd_qiovs in all
8
corners of block layer code. The following patches will increase usage
9
of this new API part by part.
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Message-id: 20190604161514.262241-5-vsementsov@virtuozzo.com
14
Message-Id: <20190604161514.262241-5-vsementsov@virtuozzo.com>
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
17
include/block/block_int.h | 15 ++++++
18
block/backup.c | 2 +-
19
block/io.c | 96 +++++++++++++++++++++++++++++++--------
20
qemu-img.c | 4 +-
21
4 files changed, 95 insertions(+), 22 deletions(-)
22
23
diff --git a/include/block/block_int.h b/include/block/block_int.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/block/block_int.h
26
+++ b/include/block/block_int.h
27
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
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;
162
}
163
164
static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
165
uint64_t offset, uint64_t bytes,
166
- QEMUIOVector *qiov, int flags)
167
+ QEMUIOVector *qiov,
168
+ size_t qiov_offset, int flags)
169
{
170
BlockDriver *drv = bs->drv;
171
int64_t sector_num;
172
unsigned int nb_sectors;
173
+ QEMUIOVector local_qiov;
174
int ret;
175
176
assert(!(flags & ~BDRV_REQ_MASK));
177
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
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;
205
}
206
207
static int coroutine_fn
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
321
index XXXXXXX..XXXXXXX 100644
322
--- a/qemu-img.c
323
+++ b/qemu-img.c
324
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
325
const char *preallocation =
326
qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
327
328
- if (drv && !drv->bdrv_co_pwritev_compressed) {
329
+ if (drv && !block_driver_can_compress(drv)) {
330
error_report("Compression not supported for this file format");
331
ret = -1;
332
goto out;
333
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
334
}
335
out_bs = blk_bs(s.target);
336
337
- if (s.compressed && !out_bs->drv->bdrv_co_pwritev_compressed) {
338
+ if (s.compressed && !block_driver_can_compress(out_bs->drv)) {
339
error_report("Compression not supported for this file format");
340
ret = -1;
341
goto out;
342
--
343
2.21.0
344
345
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Use and support new API in bdrv_co_do_copy_on_readv. Note that in case
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).
7
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(-)
16
17
diff --git a/block/io.c b/block/io.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/io.c
20
+++ b/block/io.c
21
@@ -XXX,XX +XXX,XX @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
22
23
static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
24
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
25
- int flags)
26
+ size_t qiov_offset, int flags)
27
{
28
BlockDriverState *bs = child->bs;
29
30
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
31
void *bounce_buffer;
32
33
BlockDriver *drv = bs->drv;
34
- QEMUIOVector local_qiov;
35
int64_t cluster_offset;
36
int64_t cluster_bytes;
37
size_t skip_bytes;
38
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
39
assert(skip_bytes < pnum);
40
41
if (ret <= 0) {
42
+ QEMUIOVector local_qiov;
43
+
44
/* Must copy-on-read; use the bounce buffer */
45
pnum = MIN(pnum, MAX_BOUNCE_BUFFER);
46
qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum);
47
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
48
}
49
50
if (!(flags & BDRV_REQ_PREFETCH)) {
51
- qemu_iovec_from_buf(qiov, progress, bounce_buffer + skip_bytes,
52
+ qemu_iovec_from_buf(qiov, qiov_offset + progress,
53
+ bounce_buffer + skip_bytes,
54
pnum - skip_bytes);
55
}
56
} else if (!(flags & BDRV_REQ_PREFETCH)) {
57
/* Read directly into the destination */
58
- qemu_iovec_init(&local_qiov, qiov->niov);
59
- qemu_iovec_concat(&local_qiov, qiov, progress, pnum - skip_bytes);
60
- ret = bdrv_driver_preadv(bs, offset + progress, local_qiov.size,
61
- &local_qiov, 0, 0);
62
- qemu_iovec_destroy(&local_qiov);
63
+ ret = bdrv_driver_preadv(bs, offset + progress,
64
+ MIN(pnum - skip_bytes, bytes - progress),
65
+ qiov, qiov_offset + progress, 0);
66
if (ret < 0) {
67
goto err;
68
}
69
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
70
}
71
72
if (!ret || pnum != bytes) {
73
- ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov, flags);
74
+ ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov, 0, flags);
75
goto out;
76
} else if (flags & BDRV_REQ_PREFETCH) {
77
goto out;
78
--
79
2.21.0
80
81
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Allocate bounce_buffer only if it is really needed. Also, sub-optimize
4
allocation size (why not?).
5
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>
11
---
12
block/io.c | 21 ++++++++++++---------
13
1 file changed, 12 insertions(+), 9 deletions(-)
14
15
diff --git a/block/io.c b/block/io.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/io.c
18
+++ b/block/io.c
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
20
* modifying the image file. This is critical for zero-copy guest I/O
21
* where anything might happen inside guest memory.
22
*/
23
- void *bounce_buffer;
24
+ void *bounce_buffer = NULL;
25
26
BlockDriver *drv = bs->drv;
27
int64_t cluster_offset;
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
29
trace_bdrv_co_do_copy_on_readv(bs, offset, bytes,
30
cluster_offset, cluster_bytes);
31
32
- bounce_buffer = qemu_try_blockalign(bs,
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);
51
+
52
+ bounce_buffer = qemu_try_blockalign(bs, bounce_buffer_len);
53
+ if (!bounce_buffer) {
54
+ ret = -ENOMEM;
55
+ goto err;
56
+ }
57
+ }
58
qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum);
59
60
ret = bdrv_driver_preadv(bs, cluster_offset, pnum,
61
--
62
2.21.0
63
64
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Use and support new API in bdrv_co_do_copy_on_readv.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.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
---
11
block/io.c | 21 ++++++++-------------
12
1 file changed, 8 insertions(+), 13 deletions(-)
13
14
diff --git a/block/io.c b/block/io.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/io.c
17
+++ b/block/io.c
18
@@ -XXX,XX +XXX,XX @@ err:
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;
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
55
int num;
56
57
if (max_bytes) {
58
- QEMUIOVector local_qiov;
59
-
60
num = MIN(bytes_remaining, MIN(max_bytes, max_transfer));
61
assert(num);
62
- qemu_iovec_init(&local_qiov, qiov->niov);
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
100
--
101
2.21.0
102
103
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Use and support new API in bdrv_aligned_pwritev.
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>
10
---
11
block/io.c | 27 +++++++++++++--------------
12
1 file changed, 13 insertions(+), 14 deletions(-)
13
14
diff --git a/block/io.c b/block/io.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/io.c
17
+++ b/block/io.c
18
@@ -XXX,XX +XXX,XX @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
19
*/
20
static int coroutine_fn bdrv_aligned_pwritev(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
BlockDriver *drv = bs->drv;
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);
104
}
105
106
out:
107
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
108
}
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
116
--
117
2.21.0
118
119
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
Introduce extended variants of bdrv_co_preadv and bdrv_co_pwritev
4
with qiov_offset parameter.
5
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>
11
---
12
include/block/block_int.h | 6 ++++++
13
block/io.c | 29 +++++++++++++++++++++++------
14
2 files changed, 29 insertions(+), 6 deletions(-)
15
16
diff --git a/include/block/block_int.h b/include/block/block_int.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block_int.h
19
+++ b/include/block/block_int.h
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,
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;
63
}
64
@@ -XXX,XX +XXX,XX @@ static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov,
65
int coroutine_fn bdrv_co_preadv(BdrvChild *child,
66
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
67
BdrvRequestFlags flags)
68
+{
69
+ return bdrv_co_preadv_part(child, offset, bytes, qiov, 0, flags);
70
+}
71
+
72
+int coroutine_fn bdrv_co_preadv_part(BdrvChild *child,
73
+ int64_t offset, unsigned int bytes,
74
+ QEMUIOVector *qiov, size_t qiov_offset,
75
+ BdrvRequestFlags flags)
76
{
77
BlockDriverState *bs = child->bs;
78
BdrvTrackedRequest req;
79
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child,
80
flags |= BDRV_REQ_COPY_ON_READ;
81
}
82
83
- bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad);
84
+ bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad);
85
86
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ);
87
ret = bdrv_aligned_preadv(child, &req, offset, bytes,
88
bs->bl.request_alignment,
89
- qiov, 0, flags);
90
+ qiov, qiov_offset, flags);
91
tracked_request_end(&req);
92
bdrv_dec_in_flight(bs);
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;
110
}
111
112
- if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) {
113
+ if (bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad)) {
114
mark_request_serialising(&req, align);
115
wait_serialising_requests(&req);
116
bdrv_padding_rmw_read(child, &req, &pad, false);
117
}
118
119
ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align,
120
- qiov, 0, flags);
121
+ qiov, qiov_offset, flags);
122
123
bdrv_padding_destroy(&pad);
124
125
--
126
2.21.0
127
128
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
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>
10
---
11
block/qcow2.c | 28 ++++++++++++++++------------
12
1 file changed, 16 insertions(+), 12 deletions(-)
13
14
diff --git a/block/qcow2.c b/block/qcow2.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/qcow2.c
17
+++ b/block/qcow2.c
18
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
19
}
20
21
assert(cur_bytes <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
22
- qemu_iovec_reset(&hd_qiov);
23
- qemu_iovec_add(&hd_qiov, cluster_data, cur_bytes);
24
- }
25
26
- BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
27
- ret = bdrv_co_preadv(s->data_file,
28
- cluster_offset + offset_in_cluster,
29
- cur_bytes, &hd_qiov, 0);
30
- if (ret < 0) {
31
- goto fail;
32
- }
33
- if (bs->encrypted) {
34
- assert(s->crypto);
35
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
36
+ ret = bdrv_co_pread(s->data_file,
37
+ cluster_offset + offset_in_cluster,
38
+ cur_bytes, cluster_data, 0);
39
+ if (ret < 0) {
40
+ goto fail;
41
+ }
42
+
43
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
44
assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
45
if (qcow2_co_decrypt(bs, cluster_offset, offset,
46
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
47
goto fail;
48
}
49
qemu_iovec_from_buf(qiov, bytes_done, cluster_data, cur_bytes);
50
+ } else {
51
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
52
+ ret = bdrv_co_preadv(s->data_file,
53
+ cluster_offset + offset_in_cluster,
54
+ cur_bytes, &hd_qiov, 0);
55
+ if (ret < 0) {
56
+ goto fail;
57
+ }
58
}
59
break;
60
61
--
62
2.21.0
63
64
diff view generated by jsdifflib
1
From: Stefan Weil <sw@weilnetz.de>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
gcc warning:
3
Implement and use new interface to get rid of hd_qiov.
4
4
5
/qemu/util/oslib-posix.c:304:11: error:
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
variable ‘addr’ might be clobbered by ‘longjmp’ or ‘vfork’
6
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7
[-Werror=clobbered]
7
Message-id: 20190604161514.262241-12-vsementsov@virtuozzo.com
8
8
Message-Id: <20190604161514.262241-12-vsementsov@virtuozzo.com>
9
Fix also some related data types:
10
11
numpages, hpagesize are used as pointer offset.
12
Always use size_t for them and also for the derived
13
numpages_per_thread and size_per_thread.
14
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Signed-off-by: Stefan Weil <sw@weilnetz.de>
17
Message-id: 20171016202912.1117-1-sw@weilnetz.de
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
19
---
10
---
20
util/oslib-posix.c | 15 ++++++++-------
11
block/qcow2-cluster.c | 5 +++--
21
1 file changed, 8 insertions(+), 7 deletions(-)
12
block/qcow2.c | 49 +++++++++++++++++++------------------------
13
2 files changed, 25 insertions(+), 29 deletions(-)
22
14
23
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
15
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/util/oslib-posix.c
17
--- a/block/qcow2-cluster.c
26
+++ b/util/oslib-posix.c
18
+++ b/block/qcow2-cluster.c
27
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
28
20
* interface. This avoids double I/O throttling and request tracking,
29
struct MemsetThread {
21
* which can lead to deadlock when block layer copy-on-read is enabled.
30
char *addr;
22
*/
31
- uint64_t numpages;
23
- ret = bs->drv->bdrv_co_preadv(bs, src_cluster_offset + offset_in_cluster,
32
- uint64_t hpagesize;
24
- qiov->size, qiov, 0);
33
+ size_t numpages;
25
+ ret = bs->drv->bdrv_co_preadv_part(bs,
34
+ size_t hpagesize;
26
+ src_cluster_offset + offset_in_cluster,
35
QemuThread pgthread;
27
+ qiov->size, qiov, 0, 0);
36
sigjmp_buf env;
28
if (ret < 0) {
37
};
29
return ret;
38
@@ -XXX,XX +XXX,XX @@ static void sigbus_handler(int signal)
30
}
39
static void *do_touch_pages(void *arg)
31
diff --git a/block/qcow2.c b/block/qcow2.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/qcow2.c
34
+++ b/block/qcow2.c
35
@@ -XXX,XX +XXX,XX @@ qcow2_co_preadv_compressed(BlockDriverState *bs,
36
uint64_t file_cluster_offset,
37
uint64_t offset,
38
uint64_t bytes,
39
- QEMUIOVector *qiov);
40
+ QEMUIOVector *qiov,
41
+ size_t qiov_offset);
42
43
static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
40
{
44
{
41
MemsetThread *memset_args = (MemsetThread *)arg;
45
@@ -XXX,XX +XXX,XX @@ out:
42
- char *addr = memset_args->addr;
46
return ret;
43
- uint64_t numpages = memset_args->numpages;
47
}
44
- uint64_t hpagesize = memset_args->hpagesize;
48
45
sigset_t set, oldset;
49
-static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
46
- int i = 0;
50
- uint64_t bytes, QEMUIOVector *qiov,
47
51
- int flags)
48
/* unblock SIGBUS */
52
+static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
49
sigemptyset(&set);
53
+ uint64_t offset, uint64_t bytes,
50
@@ -XXX,XX +XXX,XX @@ static void *do_touch_pages(void *arg)
54
+ QEMUIOVector *qiov,
51
if (sigsetjmp(memset_args->env, 1)) {
55
+ size_t qiov_offset, int flags)
52
memset_thread_failed = true;
53
} else {
54
+ char *addr = memset_args->addr;
55
+ size_t numpages = memset_args->numpages;
56
+ size_t hpagesize = memset_args->hpagesize;
57
+ size_t i;
58
for (i = 0; i < numpages; i++) {
59
/*
60
* Read & write back the same value, so we don't
61
@@ -XXX,XX +XXX,XX @@ static inline int get_memset_num_threads(int smp_cpus)
62
static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages,
63
int smp_cpus)
64
{
56
{
65
- uint64_t numpages_per_thread, size_per_thread;
57
BDRVQcow2State *s = bs->opaque;
66
+ size_t numpages_per_thread;
58
int offset_in_cluster;
67
+ size_t size_per_thread;
59
int ret;
68
char *addr = area;
60
unsigned int cur_bytes; /* number of bytes in current iteration */
69
int i = 0;
61
uint64_t cluster_offset = 0;
62
- uint64_t bytes_done = 0;
63
- QEMUIOVector hd_qiov;
64
uint8_t *cluster_data = NULL;
65
66
- qemu_iovec_init(&hd_qiov, qiov->niov);
67
-
68
while (bytes != 0) {
69
70
/* prepare next request */
71
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
72
73
offset_in_cluster = offset_into_cluster(s, offset);
74
75
- qemu_iovec_reset(&hd_qiov);
76
- qemu_iovec_concat(&hd_qiov, qiov, bytes_done, cur_bytes);
77
-
78
switch (ret) {
79
case QCOW2_CLUSTER_UNALLOCATED:
80
81
if (bs->backing) {
82
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
83
- ret = bdrv_co_preadv(bs->backing, offset, cur_bytes,
84
- &hd_qiov, 0);
85
+ ret = bdrv_co_preadv_part(bs->backing, offset, cur_bytes,
86
+ qiov, qiov_offset, 0);
87
if (ret < 0) {
88
goto fail;
89
}
90
} else {
91
/* Note: in this case, no need to wait */
92
- qemu_iovec_memset(&hd_qiov, 0, 0, cur_bytes);
93
+ qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
94
}
95
break;
96
97
case QCOW2_CLUSTER_ZERO_PLAIN:
98
case QCOW2_CLUSTER_ZERO_ALLOC:
99
- qemu_iovec_memset(&hd_qiov, 0, 0, cur_bytes);
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);
169
}
170
171
/*
172
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
173
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
174
.bdrv_co_block_status = qcow2_co_block_status,
175
176
- .bdrv_co_preadv = qcow2_co_preadv,
177
+ .bdrv_co_preadv_part = qcow2_co_preadv_part,
178
.bdrv_co_pwritev = qcow2_co_pwritev,
179
.bdrv_co_flush_to_os = qcow2_co_flush_to_os,
70
180
71
--
181
--
72
2.13.6
182
2.21.0
73
183
74
184
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
Implement and use new interface to get rid of hd_qiov.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.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>
10
---
11
block/qcow2.h | 1 +
12
include/qemu/iov.h | 1 +
13
block/qcow2-cluster.c | 9 ++++---
14
block/qcow2.c | 60 +++++++++++++++++++++----------------------
15
util/iov.c | 10 ++++++++
16
5 files changed, 48 insertions(+), 33 deletions(-)
17
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;
103
}
104
105
@@ -XXX,XX +XXX,XX @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
106
return 0;
107
}
108
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)
265
+{
266
+ size_t head, tail;
267
+ int niov;
268
+
269
+ qiov_slice(qiov, offset, len, &head, &tail, &niov);
270
+
271
+ return niov;
272
+}
273
+
274
/*
275
* Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov,
276
* and @tail_buf buffer into new qiov.
277
--
278
2.21.0
279
280
diff view generated by jsdifflib