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, ¤t_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 |