qemu

Форк
0
/
qcow2-threads.c 
527 строк · 14.5 Кб
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
#ifdef CONFIG_ZSTD
32
#include <zstd.h>
33
#include <zstd_errors.h>
34
#endif
35

36
#include "qcow2.h"
37
#include "block/block-io.h"
38
#include "block/thread-pool.h"
39
#include "crypto.h"
40

41
static int coroutine_fn
42
qcow2_co_process(BlockDriverState *bs, ThreadPoolFunc *func, void *arg)
43
{
44
    int ret;
45
    BDRVQcow2State *s = bs->opaque;
46

47
    qemu_co_mutex_lock(&s->lock);
48
    while (s->nb_threads >= QCOW2_MAX_THREADS) {
49
        qemu_co_queue_wait(&s->thread_task_queue, &s->lock);
50
    }
51
    s->nb_threads++;
52
    qemu_co_mutex_unlock(&s->lock);
53

54
    ret = thread_pool_submit_co(func, arg);
55

56
    qemu_co_mutex_lock(&s->lock);
57
    s->nb_threads--;
58
    qemu_co_queue_next(&s->thread_task_queue);
59
    qemu_co_mutex_unlock(&s->lock);
60

61
    return ret;
62
}
63

64

65
/*
66
 * Compression
67
 */
68

69
typedef ssize_t (*Qcow2CompressFunc)(void *dest, size_t dest_size,
70
                                     const void *src, size_t src_size);
71
typedef struct Qcow2CompressData {
72
    void *dest;
73
    size_t dest_size;
74
    const void *src;
75
    size_t src_size;
76
    ssize_t ret;
77

78
    Qcow2CompressFunc func;
79
} Qcow2CompressData;
80

81
/*
82
 * qcow2_zlib_compress()
83
 *
84
 * Compress @src_size bytes of data using zlib compression method
85
 *
86
 * @dest - destination buffer, @dest_size bytes
87
 * @src - source buffer, @src_size bytes
88
 *
89
 * Returns: compressed size on success
90
 *          -ENOMEM destination buffer is not enough to store compressed data
91
 *          -EIO    on any other error
92
 */
93
static ssize_t qcow2_zlib_compress(void *dest, size_t dest_size,
94
                                   const void *src, size_t src_size)
95
{
96
    ssize_t ret;
97
    z_stream strm;
98

99
    /* best compression, small window, no zlib header */
100
    memset(&strm, 0, sizeof(strm));
101
    ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
102
                       -12, 9, Z_DEFAULT_STRATEGY);
103
    if (ret != Z_OK) {
104
        return -EIO;
105
    }
106

107
    /*
108
     * strm.next_in is not const in old zlib versions, such as those used on
109
     * OpenBSD/NetBSD, so cast the const away
110
     */
111
    strm.avail_in = src_size;
112
    strm.next_in = (void *) src;
113
    strm.avail_out = dest_size;
114
    strm.next_out = dest;
115

116
    ret = deflate(&strm, Z_FINISH);
117
    if (ret == Z_STREAM_END) {
118
        ret = dest_size - strm.avail_out;
119
    } else {
120
        ret = (ret == Z_OK ? -ENOMEM : -EIO);
121
    }
122

123
    deflateEnd(&strm);
124

125
    return ret;
126
}
127

128
/*
129
 * qcow2_zlib_decompress()
130
 *
131
 * Decompress some data (not more than @src_size bytes) to produce exactly
132
 * @dest_size bytes using zlib compression method
133
 *
134
 * @dest - destination buffer, @dest_size bytes
135
 * @src - source buffer, @src_size bytes
136
 *
137
 * Returns: 0 on success
138
 *          -EIO on fail
139
 */
140
static ssize_t qcow2_zlib_decompress(void *dest, size_t dest_size,
141
                                     const void *src, size_t src_size)
142
{
143
    int ret;
144
    z_stream strm;
145

146
    memset(&strm, 0, sizeof(strm));
147
    strm.avail_in = src_size;
148
    strm.next_in = (void *) src;
149
    strm.avail_out = dest_size;
150
    strm.next_out = dest;
151

152
    ret = inflateInit2(&strm, -12);
153
    if (ret != Z_OK) {
154
        return -EIO;
155
    }
156

157
    ret = inflate(&strm, Z_FINISH);
158
    if ((ret == Z_STREAM_END || ret == Z_BUF_ERROR) && strm.avail_out == 0) {
159
        /*
160
         * We approve Z_BUF_ERROR because we need @dest buffer to be filled, but
161
         * @src buffer may be processed partly (because in qcow2 we know size of
162
         * compressed data with precision of one sector)
163
         */
164
        ret = 0;
165
    } else {
166
        ret = -EIO;
167
    }
168

169
    inflateEnd(&strm);
170

171
    return ret;
172
}
173

174
#ifdef CONFIG_ZSTD
175

176
/*
177
 * qcow2_zstd_compress()
178
 *
179
 * Compress @src_size bytes of data using zstd compression method
180
 *
181
 * @dest - destination buffer, @dest_size bytes
182
 * @src - source buffer, @src_size bytes
183
 *
184
 * Returns: compressed size on success
185
 *          -ENOMEM destination buffer is not enough to store compressed data
186
 *          -EIO    on any other error
187
 */
188
static ssize_t qcow2_zstd_compress(void *dest, size_t dest_size,
189
                                   const void *src, size_t src_size)
190
{
191
    ssize_t ret;
192
    size_t zstd_ret;
193
    ZSTD_outBuffer output = {
194
        .dst = dest,
195
        .size = dest_size,
196
        .pos = 0
197
    };
198
    ZSTD_inBuffer input = {
199
        .src = src,
200
        .size = src_size,
201
        .pos = 0
202
    };
203
    ZSTD_CCtx *cctx = ZSTD_createCCtx();
204

205
    if (!cctx) {
206
        return -EIO;
207
    }
208
    /*
209
     * Use the zstd streamed interface for symmetry with decompression,
210
     * where streaming is essential since we don't record the exact
211
     * compressed size.
212
     *
213
     * ZSTD_compressStream2() tries to compress everything it could
214
     * with a single call. Although, ZSTD docs says that:
215
     * "You must continue calling ZSTD_compressStream2() with ZSTD_e_end
216
     * until it returns 0, at which point you are free to start a new frame",
217
     * in out tests we saw the only case when it returned with >0 -
218
     * when the output buffer was too small. In that case,
219
     * ZSTD_compressStream2() expects a bigger buffer on the next call.
220
     * We can't provide a bigger buffer because we are limited with dest_size
221
     * which we pass to the ZSTD_compressStream2() at once.
222
     * So, we don't need any loops and just abort the compression when we
223
     * don't get 0 result on the first call.
224
     */
225
    zstd_ret = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_end);
226

227
    if (zstd_ret) {
228
        if (zstd_ret > output.size - output.pos) {
229
            ret = -ENOMEM;
230
        } else {
231
            ret = -EIO;
232
        }
233
        goto out;
234
    }
235

236
    /* make sure that zstd didn't overflow the dest buffer */
237
    assert(output.pos <= dest_size);
238
    ret = output.pos;
239
out:
240
    ZSTD_freeCCtx(cctx);
241
    return ret;
242
}
243

244
/*
245
 * qcow2_zstd_decompress()
246
 *
247
 * Decompress some data (not more than @src_size bytes) to produce exactly
248
 * @dest_size bytes using zstd compression method
249
 *
250
 * @dest - destination buffer, @dest_size bytes
251
 * @src - source buffer, @src_size bytes
252
 *
253
 * Returns: 0 on success
254
 *          -EIO on any error
255
 */
256
static ssize_t qcow2_zstd_decompress(void *dest, size_t dest_size,
257
                                     const void *src, size_t src_size)
258
{
259
    size_t zstd_ret = 0;
260
    ssize_t ret = 0;
261
    ZSTD_outBuffer output = {
262
        .dst = dest,
263
        .size = dest_size,
264
        .pos = 0
265
    };
266
    ZSTD_inBuffer input = {
267
        .src = src,
268
        .size = src_size,
269
        .pos = 0
270
    };
271
    ZSTD_DCtx *dctx = ZSTD_createDCtx();
272

273
    if (!dctx) {
274
        return -EIO;
275
    }
276

277
    /*
278
     * The compressed stream from the input buffer may consist of more
279
     * than one zstd frame. So we iterate until we get a fully
280
     * uncompressed cluster.
281
     * From zstd docs related to ZSTD_decompressStream:
282
     * "return : 0 when a frame is completely decoded and fully flushed"
283
     * We suppose that this means: each time ZSTD_decompressStream reads
284
     * only ONE full frame and returns 0 if and only if that frame
285
     * is completely decoded and flushed. Only after returning 0,
286
     * ZSTD_decompressStream reads another ONE full frame.
287
     */
288
    while (output.pos < output.size) {
289
        size_t last_in_pos = input.pos;
290
        size_t last_out_pos = output.pos;
291
        zstd_ret = ZSTD_decompressStream(dctx, &output, &input);
292

293
        if (ZSTD_isError(zstd_ret)) {
294
            ret = -EIO;
295
            break;
296
        }
297

298
        /*
299
         * The ZSTD manual is vague about what to do if it reads
300
         * the buffer partially, and we don't want to get stuck
301
         * in an infinite loop where ZSTD_decompressStream
302
         * returns > 0 waiting for another input chunk. So, we add
303
         * a check which ensures that the loop makes some progress
304
         * on each step.
305
         */
306
        if (last_in_pos >= input.pos &&
307
            last_out_pos >= output.pos) {
308
            ret = -EIO;
309
            break;
310
        }
311
    }
312
    /*
313
     * Make sure that we have the frame fully flushed here
314
     * if not, we somehow managed to get uncompressed cluster
315
     * greater then the cluster size, possibly because of its
316
     * damage.
317
     */
318
    if (zstd_ret > 0) {
319
        ret = -EIO;
320
    }
321

322
    ZSTD_freeDCtx(dctx);
323
    assert(ret == 0 || ret == -EIO);
324
    return ret;
325
}
326
#endif
327

328
static int qcow2_compress_pool_func(void *opaque)
329
{
330
    Qcow2CompressData *data = opaque;
331

332
    data->ret = data->func(data->dest, data->dest_size,
333
                           data->src, data->src_size);
334

335
    return 0;
336
}
337

338
static ssize_t coroutine_fn
339
qcow2_co_do_compress(BlockDriverState *bs, void *dest, size_t dest_size,
340
                     const void *src, size_t src_size, Qcow2CompressFunc func)
341
{
342
    Qcow2CompressData arg = {
343
        .dest = dest,
344
        .dest_size = dest_size,
345
        .src = src,
346
        .src_size = src_size,
347
        .func = func,
348
    };
349

350
    qcow2_co_process(bs, qcow2_compress_pool_func, &arg);
351

352
    return arg.ret;
353
}
354

355
/*
356
 * qcow2_co_compress()
357
 *
358
 * Compress @src_size bytes of data using the compression
359
 * method defined by the image compression type
360
 *
361
 * @dest - destination buffer, @dest_size bytes
362
 * @src - source buffer, @src_size bytes
363
 *
364
 * Returns: compressed size on success
365
 *          a negative error code on failure
366
 */
367
ssize_t coroutine_fn
368
qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
369
                  const void *src, size_t src_size)
370
{
371
    BDRVQcow2State *s = bs->opaque;
372
    Qcow2CompressFunc fn;
373

374
    switch (s->compression_type) {
375
    case QCOW2_COMPRESSION_TYPE_ZLIB:
376
        fn = qcow2_zlib_compress;
377
        break;
378

379
#ifdef CONFIG_ZSTD
380
    case QCOW2_COMPRESSION_TYPE_ZSTD:
381
        fn = qcow2_zstd_compress;
382
        break;
383
#endif
384
    default:
385
        abort();
386
    }
387

388
    return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn);
389
}
390

391
/*
392
 * qcow2_co_decompress()
393
 *
394
 * Decompress some data (not more than @src_size bytes) to produce exactly
395
 * @dest_size bytes using the compression method defined by the image
396
 * compression type
397
 *
398
 * @dest - destination buffer, @dest_size bytes
399
 * @src - source buffer, @src_size bytes
400
 *
401
 * Returns: 0 on success
402
 *          a negative error code on failure
403
 */
404
ssize_t coroutine_fn
405
qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size,
406
                    const void *src, size_t src_size)
407
{
408
    BDRVQcow2State *s = bs->opaque;
409
    Qcow2CompressFunc fn;
410

411
    switch (s->compression_type) {
412
    case QCOW2_COMPRESSION_TYPE_ZLIB:
413
        fn = qcow2_zlib_decompress;
414
        break;
415

416
#ifdef CONFIG_ZSTD
417
    case QCOW2_COMPRESSION_TYPE_ZSTD:
418
        fn = qcow2_zstd_decompress;
419
        break;
420
#endif
421
    default:
422
        abort();
423
    }
424

425
    return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn);
426
}
427

428

429
/*
430
 * Cryptography
431
 */
432

433
/*
434
 * Qcow2EncDecFunc: common prototype of qcrypto_block_encrypt() and
435
 * qcrypto_block_decrypt() functions.
436
 */
437
typedef int (*Qcow2EncDecFunc)(QCryptoBlock *block, uint64_t offset,
438
                               uint8_t *buf, size_t len, Error **errp);
439

440
typedef struct Qcow2EncDecData {
441
    QCryptoBlock *block;
442
    uint64_t offset;
443
    uint8_t *buf;
444
    size_t len;
445

446
    Qcow2EncDecFunc func;
447
} Qcow2EncDecData;
448

449
static int qcow2_encdec_pool_func(void *opaque)
450
{
451
    Qcow2EncDecData *data = opaque;
452

453
    return data->func(data->block, data->offset, data->buf, data->len, NULL);
454
}
455

456
static int coroutine_fn
457
qcow2_co_encdec(BlockDriverState *bs, uint64_t host_offset,
458
                uint64_t guest_offset, void *buf, size_t len,
459
                Qcow2EncDecFunc func)
460
{
461
    BDRVQcow2State *s = bs->opaque;
462
    Qcow2EncDecData arg = {
463
        .block = s->crypto,
464
        .offset = s->crypt_physical_offset ? host_offset : guest_offset,
465
        .buf = buf,
466
        .len = len,
467
        .func = func,
468
    };
469
    uint64_t sector_size;
470

471
    assert(s->crypto);
472

473
    sector_size = qcrypto_block_get_sector_size(s->crypto);
474
    assert(QEMU_IS_ALIGNED(guest_offset, sector_size));
475
    assert(QEMU_IS_ALIGNED(host_offset, sector_size));
476
    assert(QEMU_IS_ALIGNED(len, sector_size));
477

478
    return len == 0 ? 0 : qcow2_co_process(bs, qcow2_encdec_pool_func, &arg);
479
}
480

481
/*
482
 * qcow2_co_encrypt()
483
 *
484
 * Encrypts one or more contiguous aligned sectors
485
 *
486
 * @host_offset - underlying storage offset of the first sector of the
487
 * data to be encrypted
488
 *
489
 * @guest_offset - guest (virtual) offset of the first sector of the
490
 * data to be encrypted
491
 *
492
 * @buf - buffer with the data to encrypt, that after encryption
493
 *        will be written to the underlying storage device at
494
 *        @host_offset
495
 *
496
 * @len - length of the buffer (must be a multiple of the encryption
497
 *        sector size)
498
 *
499
 * Depending on the encryption method, @host_offset and/or @guest_offset
500
 * may be used for generating the initialization vector for
501
 * encryption.
502
 *
503
 * Note that while the whole range must be aligned on sectors, it
504
 * does not have to be aligned on clusters and can also cross cluster
505
 * boundaries
506
 */
507
int coroutine_fn
508
qcow2_co_encrypt(BlockDriverState *bs, uint64_t host_offset,
509
                 uint64_t guest_offset, void *buf, size_t len)
510
{
511
    return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len,
512
                           qcrypto_block_encrypt);
513
}
514

515
/*
516
 * qcow2_co_decrypt()
517
 *
518
 * Decrypts one or more contiguous aligned sectors
519
 * Similar to qcow2_co_encrypt
520
 */
521
int coroutine_fn
522
qcow2_co_decrypt(BlockDriverState *bs, uint64_t host_offset,
523
                 uint64_t guest_offset, void *buf, size_t len)
524
{
525
    return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len,
526
                           qcrypto_block_decrypt);
527
}
528

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.