qcow2: do encryption in threads
Do encryption/decryption in threads, like it is already done for compression. This improves asynchronous encrypted io. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Alberto Garcia <berto@igalia.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Message-id: 20190506142741.41731-9-vsementsov@virtuozzo.com Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
5447c3a03f
commit
8ac0f15f33
@ -471,13 +471,12 @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
|
|||||||
{
|
{
|
||||||
if (bytes && bs->encrypted) {
|
if (bytes && bs->encrypted) {
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
int64_t offset = (s->crypt_physical_offset ?
|
|
||||||
(cluster_offset + offset_in_cluster) :
|
|
||||||
(src_cluster_offset + offset_in_cluster));
|
|
||||||
assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);
|
assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);
|
||||||
assert((bytes & ~BDRV_SECTOR_MASK) == 0);
|
assert((bytes & ~BDRV_SECTOR_MASK) == 0);
|
||||||
assert(s->crypto);
|
assert(s->crypto);
|
||||||
if (qcrypto_block_encrypt(s->crypto, offset, buffer, bytes, NULL) < 0) {
|
if (qcow2_co_encrypt(bs, cluster_offset,
|
||||||
|
src_cluster_offset + offset_in_cluster,
|
||||||
|
buffer, bytes) < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,7 @@
|
|||||||
|
|
||||||
#include "qcow2.h"
|
#include "qcow2.h"
|
||||||
#include "block/thread-pool.h"
|
#include "block/thread-pool.h"
|
||||||
|
#include "crypto.h"
|
||||||
#define QCOW2_MAX_THREADS 4
|
|
||||||
|
|
||||||
static int coroutine_fn
|
static int coroutine_fn
|
||||||
qcow2_co_process(BlockDriverState *bs, ThreadPoolFunc *func, void *arg)
|
qcow2_co_process(BlockDriverState *bs, ThreadPoolFunc *func, void *arg)
|
||||||
@ -205,3 +204,65 @@ qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size,
|
|||||||
return qcow2_co_do_compress(bs, dest, dest_size, src, src_size,
|
return qcow2_co_do_compress(bs, dest, dest_size, src, src_size,
|
||||||
qcow2_decompress);
|
qcow2_decompress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cryptography
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Qcow2EncDecFunc: common prototype of qcrypto_block_encrypt() and
|
||||||
|
* qcrypto_block_decrypt() functions.
|
||||||
|
*/
|
||||||
|
typedef int (*Qcow2EncDecFunc)(QCryptoBlock *block, uint64_t offset,
|
||||||
|
uint8_t *buf, size_t len, Error **errp);
|
||||||
|
|
||||||
|
typedef struct Qcow2EncDecData {
|
||||||
|
QCryptoBlock *block;
|
||||||
|
uint64_t offset;
|
||||||
|
uint8_t *buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
Qcow2EncDecFunc func;
|
||||||
|
} Qcow2EncDecData;
|
||||||
|
|
||||||
|
static int qcow2_encdec_pool_func(void *opaque)
|
||||||
|
{
|
||||||
|
Qcow2EncDecData *data = opaque;
|
||||||
|
|
||||||
|
return data->func(data->block, data->offset, data->buf, data->len, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn
|
||||||
|
qcow2_co_encdec(BlockDriverState *bs, uint64_t file_cluster_offset,
|
||||||
|
uint64_t offset, void *buf, size_t len, Qcow2EncDecFunc func)
|
||||||
|
{
|
||||||
|
BDRVQcow2State *s = bs->opaque;
|
||||||
|
Qcow2EncDecData arg = {
|
||||||
|
.block = s->crypto,
|
||||||
|
.offset = s->crypt_physical_offset ?
|
||||||
|
file_cluster_offset + offset_into_cluster(s, offset) :
|
||||||
|
offset,
|
||||||
|
.buf = buf,
|
||||||
|
.len = len,
|
||||||
|
.func = func,
|
||||||
|
};
|
||||||
|
|
||||||
|
return qcow2_co_process(bs, qcow2_encdec_pool_func, &arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int coroutine_fn
|
||||||
|
qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
|
||||||
|
uint64_t offset, void *buf, size_t len)
|
||||||
|
{
|
||||||
|
return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len,
|
||||||
|
qcrypto_block_encrypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int coroutine_fn
|
||||||
|
qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
|
||||||
|
uint64_t offset, void *buf, size_t len)
|
||||||
|
{
|
||||||
|
return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len,
|
||||||
|
qcrypto_block_decrypt);
|
||||||
|
}
|
||||||
|
@ -297,7 +297,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
|||||||
}
|
}
|
||||||
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
|
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
|
||||||
qcow2_crypto_hdr_read_func,
|
qcow2_crypto_hdr_read_func,
|
||||||
bs, cflags, 1, errp);
|
bs, cflags, QCOW2_MAX_THREADS, errp);
|
||||||
if (!s->crypto) {
|
if (!s->crypto) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1538,7 +1538,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
|
|||||||
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
|
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
|
||||||
}
|
}
|
||||||
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
|
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
|
||||||
NULL, NULL, cflags, 1, errp);
|
NULL, NULL, cflags,
|
||||||
|
QCOW2_MAX_THREADS, errp);
|
||||||
if (!s->crypto) {
|
if (!s->crypto) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -2061,13 +2062,8 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
|
|||||||
assert(s->crypto);
|
assert(s->crypto);
|
||||||
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||||
assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||||
if (qcrypto_block_decrypt(s->crypto,
|
if (qcow2_co_decrypt(bs, cluster_offset, offset,
|
||||||
(s->crypt_physical_offset ?
|
cluster_data, cur_bytes) < 0) {
|
||||||
cluster_offset + offset_in_cluster :
|
|
||||||
offset),
|
|
||||||
cluster_data,
|
|
||||||
cur_bytes,
|
|
||||||
NULL) < 0) {
|
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -2201,12 +2197,8 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
|
|||||||
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
|
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
|
||||||
qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);
|
qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);
|
||||||
|
|
||||||
if (qcrypto_block_encrypt(s->crypto,
|
if (qcow2_co_encrypt(bs, cluster_offset, offset,
|
||||||
(s->crypt_physical_offset ?
|
cluster_data, cur_bytes) < 0) {
|
||||||
cluster_offset + offset_in_cluster :
|
|
||||||
offset),
|
|
||||||
cluster_data,
|
|
||||||
cur_bytes, NULL) < 0) {
|
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out_unlocked;
|
goto out_unlocked;
|
||||||
}
|
}
|
||||||
|
@ -268,6 +268,8 @@ typedef struct Qcow2BitmapHeaderExt {
|
|||||||
uint64_t bitmap_directory_offset;
|
uint64_t bitmap_directory_offset;
|
||||||
} QEMU_PACKED Qcow2BitmapHeaderExt;
|
} QEMU_PACKED Qcow2BitmapHeaderExt;
|
||||||
|
|
||||||
|
#define QCOW2_MAX_THREADS 4
|
||||||
|
|
||||||
typedef struct BDRVQcow2State {
|
typedef struct BDRVQcow2State {
|
||||||
int cluster_bits;
|
int cluster_bits;
|
||||||
int cluster_size;
|
int cluster_size;
|
||||||
@ -744,5 +746,11 @@ qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
|
|||||||
ssize_t coroutine_fn
|
ssize_t coroutine_fn
|
||||||
qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size,
|
qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size,
|
||||||
const void *src, size_t src_size);
|
const void *src, size_t src_size);
|
||||||
|
int coroutine_fn
|
||||||
|
qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
|
||||||
|
uint64_t offset, void *buf, size_t len);
|
||||||
|
int coroutine_fn
|
||||||
|
qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset,
|
||||||
|
uint64_t offset, void *buf, size_t len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user