]> git.proxmox.com Git - mirror_qemu.git/blob - block/qcow2-threads.c
7dbaf53489835df412d2871cebb3f5b5f1b19523
[mirror_qemu.git] / block / qcow2-threads.c
1 /*
2 * Threaded data processing for Qcow2: compression, encryption
3 *
4 * Copyright (c) 2004-2006 Fabrice Bellard
5 * Copyright (c) 2018 Virtuozzo International GmbH. All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26 #include "qemu/osdep.h"
27
28 #define ZLIB_CONST
29 #include <zlib.h>
30
31 #include "qcow2.h"
32 #include "block/thread-pool.h"
33 #include "crypto.h"
34
35 static int coroutine_fn
36 qcow2_co_process(BlockDriverState *bs, ThreadPoolFunc *func, void *arg)
37 {
38 int ret;
39 BDRVQcow2State *s = bs->opaque;
40 ThreadPool *pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
41
42 qemu_co_mutex_lock(&s->lock);
43 while (s->nb_threads >= QCOW2_MAX_THREADS) {
44 qemu_co_queue_wait(&s->thread_task_queue, &s->lock);
45 }
46 s->nb_threads++;
47 qemu_co_mutex_unlock(&s->lock);
48
49 ret = thread_pool_submit_co(pool, func, arg);
50
51 qemu_co_mutex_lock(&s->lock);
52 s->nb_threads--;
53 qemu_co_queue_next(&s->thread_task_queue);
54 qemu_co_mutex_unlock(&s->lock);
55
56 return ret;
57 }
58
59
60 /*
61 * Compression
62 */
63
64 typedef ssize_t (*Qcow2CompressFunc)(void *dest, size_t dest_size,
65 const void *src, size_t src_size);
66 typedef struct Qcow2CompressData {
67 void *dest;
68 size_t dest_size;
69 const void *src;
70 size_t src_size;
71 ssize_t ret;
72
73 Qcow2CompressFunc func;
74 } Qcow2CompressData;
75
76 /*
77 * qcow2_zlib_compress()
78 *
79 * Compress @src_size bytes of data using zlib compression method
80 *
81 * @dest - destination buffer, @dest_size bytes
82 * @src - source buffer, @src_size bytes
83 *
84 * Returns: compressed size on success
85 * -ENOMEM destination buffer is not enough to store compressed data
86 * -EIO on any other error
87 */
88 static ssize_t qcow2_zlib_compress(void *dest, size_t dest_size,
89 const void *src, size_t src_size)
90 {
91 ssize_t ret;
92 z_stream strm;
93
94 /* best compression, small window, no zlib header */
95 memset(&strm, 0, sizeof(strm));
96 ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
97 -12, 9, Z_DEFAULT_STRATEGY);
98 if (ret != Z_OK) {
99 return -EIO;
100 }
101
102 /*
103 * strm.next_in is not const in old zlib versions, such as those used on
104 * OpenBSD/NetBSD, so cast the const away
105 */
106 strm.avail_in = src_size;
107 strm.next_in = (void *) src;
108 strm.avail_out = dest_size;
109 strm.next_out = dest;
110
111 ret = deflate(&strm, Z_FINISH);
112 if (ret == Z_STREAM_END) {
113 ret = dest_size - strm.avail_out;
114 } else {
115 ret = (ret == Z_OK ? -ENOMEM : -EIO);
116 }
117
118 deflateEnd(&strm);
119
120 return ret;
121 }
122
123 /*
124 * qcow2_zlib_decompress()
125 *
126 * Decompress some data (not more than @src_size bytes) to produce exactly
127 * @dest_size bytes using zlib compression method
128 *
129 * @dest - destination buffer, @dest_size bytes
130 * @src - source buffer, @src_size bytes
131 *
132 * Returns: 0 on success
133 * -EIO on fail
134 */
135 static ssize_t qcow2_zlib_decompress(void *dest, size_t dest_size,
136 const void *src, size_t src_size)
137 {
138 int ret;
139 z_stream strm;
140
141 memset(&strm, 0, sizeof(strm));
142 strm.avail_in = src_size;
143 strm.next_in = (void *) src;
144 strm.avail_out = dest_size;
145 strm.next_out = dest;
146
147 ret = inflateInit2(&strm, -12);
148 if (ret != Z_OK) {
149 return -EIO;
150 }
151
152 ret = inflate(&strm, Z_FINISH);
153 if ((ret == Z_STREAM_END || ret == Z_BUF_ERROR) && strm.avail_out == 0) {
154 /*
155 * We approve Z_BUF_ERROR because we need @dest buffer to be filled, but
156 * @src buffer may be processed partly (because in qcow2 we know size of
157 * compressed data with precision of one sector)
158 */
159 ret = 0;
160 } else {
161 ret = -EIO;
162 }
163
164 inflateEnd(&strm);
165
166 return ret;
167 }
168
169 static int qcow2_compress_pool_func(void *opaque)
170 {
171 Qcow2CompressData *data = opaque;
172
173 data->ret = data->func(data->dest, data->dest_size,
174 data->src, data->src_size);
175
176 return 0;
177 }
178
179 static ssize_t coroutine_fn
180 qcow2_co_do_compress(BlockDriverState *bs, void *dest, size_t dest_size,
181 const void *src, size_t src_size, Qcow2CompressFunc func)
182 {
183 Qcow2CompressData arg = {
184 .dest = dest,
185 .dest_size = dest_size,
186 .src = src,
187 .src_size = src_size,
188 .func = func,
189 };
190
191 qcow2_co_process(bs, qcow2_compress_pool_func, &arg);
192
193 return arg.ret;
194 }
195
196 /*
197 * qcow2_co_compress()
198 *
199 * Compress @src_size bytes of data using the compression
200 * method defined by the image compression type
201 *
202 * @dest - destination buffer, @dest_size bytes
203 * @src - source buffer, @src_size bytes
204 *
205 * Returns: compressed size on success
206 * a negative error code on failure
207 */
208 ssize_t coroutine_fn
209 qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
210 const void *src, size_t src_size)
211 {
212 BDRVQcow2State *s = bs->opaque;
213 Qcow2CompressFunc fn;
214
215 switch (s->compression_type) {
216 case QCOW2_COMPRESSION_TYPE_ZLIB:
217 fn = qcow2_zlib_compress;
218 break;
219
220 default:
221 abort();
222 }
223
224 return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn);
225 }
226
227 /*
228 * qcow2_co_decompress()
229 *
230 * Decompress some data (not more than @src_size bytes) to produce exactly
231 * @dest_size bytes using the compression method defined by the image
232 * compression type
233 *
234 * @dest - destination buffer, @dest_size bytes
235 * @src - source buffer, @src_size bytes
236 *
237 * Returns: 0 on success
238 * a negative error code on failure
239 */
240 ssize_t coroutine_fn
241 qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size,
242 const void *src, size_t src_size)
243 {
244 BDRVQcow2State *s = bs->opaque;
245 Qcow2CompressFunc fn;
246
247 switch (s->compression_type) {
248 case QCOW2_COMPRESSION_TYPE_ZLIB:
249 fn = qcow2_zlib_decompress;
250 break;
251
252 default:
253 abort();
254 }
255
256 return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn);
257 }
258
259
260 /*
261 * Cryptography
262 */
263
264 /*
265 * Qcow2EncDecFunc: common prototype of qcrypto_block_encrypt() and
266 * qcrypto_block_decrypt() functions.
267 */
268 typedef int (*Qcow2EncDecFunc)(QCryptoBlock *block, uint64_t offset,
269 uint8_t *buf, size_t len, Error **errp);
270
271 typedef struct Qcow2EncDecData {
272 QCryptoBlock *block;
273 uint64_t offset;
274 uint8_t *buf;
275 size_t len;
276
277 Qcow2EncDecFunc func;
278 } Qcow2EncDecData;
279
280 static int qcow2_encdec_pool_func(void *opaque)
281 {
282 Qcow2EncDecData *data = opaque;
283
284 return data->func(data->block, data->offset, data->buf, data->len, NULL);
285 }
286
287 static int coroutine_fn
288 qcow2_co_encdec(BlockDriverState *bs, uint64_t host_offset,
289 uint64_t guest_offset, void *buf, size_t len,
290 Qcow2EncDecFunc func)
291 {
292 BDRVQcow2State *s = bs->opaque;
293 Qcow2EncDecData arg = {
294 .block = s->crypto,
295 .offset = s->crypt_physical_offset ? host_offset : guest_offset,
296 .buf = buf,
297 .len = len,
298 .func = func,
299 };
300 uint64_t sector_size;
301
302 assert(s->crypto);
303
304 sector_size = qcrypto_block_get_sector_size(s->crypto);
305 assert(QEMU_IS_ALIGNED(guest_offset, sector_size));
306 assert(QEMU_IS_ALIGNED(host_offset, sector_size));
307 assert(QEMU_IS_ALIGNED(len, sector_size));
308
309 return len == 0 ? 0 : qcow2_co_process(bs, qcow2_encdec_pool_func, &arg);
310 }
311
312 /*
313 * qcow2_co_encrypt()
314 *
315 * Encrypts one or more contiguous aligned sectors
316 *
317 * @host_offset - underlying storage offset of the first sector of the
318 * data to be encrypted
319 *
320 * @guest_offset - guest (virtual) offset of the first sector of the
321 * data to be encrypted
322 *
323 * @buf - buffer with the data to encrypt, that after encryption
324 * will be written to the underlying storage device at
325 * @host_offset
326 *
327 * @len - length of the buffer (must be a multiple of the encryption
328 * sector size)
329 *
330 * Depending on the encryption method, @host_offset and/or @guest_offset
331 * may be used for generating the initialization vector for
332 * encryption.
333 *
334 * Note that while the whole range must be aligned on sectors, it
335 * does not have to be aligned on clusters and can also cross cluster
336 * boundaries
337 */
338 int coroutine_fn
339 qcow2_co_encrypt(BlockDriverState *bs, uint64_t host_offset,
340 uint64_t guest_offset, void *buf, size_t len)
341 {
342 return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len,
343 qcrypto_block_encrypt);
344 }
345
346 /*
347 * qcow2_co_decrypt()
348 *
349 * Decrypts one or more contiguous aligned sectors
350 * Similar to qcow2_co_encrypt
351 */
352 int coroutine_fn
353 qcow2_co_decrypt(BlockDriverState *bs, uint64_t host_offset,
354 uint64_t guest_offset, void *buf, size_t len)
355 {
356 return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len,
357 qcrypto_block_decrypt);
358 }