Do encryption/decryption in threads, like it is already done for
compression. This improves asynchronous encrypted io.
Signed-off-by: Vladimir Sementsov-Ogievskiy
---
block/qcow2.h | 8 ++
block/qcow2-cluster.c | 7 ++---
block/qcow2-threads.c | 65 +--
block/qcow2.c | 22 +--
4 files changed, 81 insertions(+), 21 deletions(-)
diff --git a/block/qcow2.h b/block/qcow2.h
index 9c2f6749ba..7e75f20373 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -257,6 +257,8 @@ typedef struct Qcow2BitmapHeaderExt {
uint64_t bitmap_directory_offset;
} QEMU_PACKED Qcow2BitmapHeaderExt;
+#define QCOW2_MAX_THREADS 4
+
typedef struct BDRVQcow2State {
int cluster_bits;
int cluster_size;
@@ -701,5 +703,11 @@ qcow2_co_compress(BlockDriverState *bs, void *dest, size_t
dest_size,
ssize_t coroutine_fn
qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_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
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 7815772116..55dd4144de 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -467,13 +467,12 @@ static bool coroutine_fn
do_perform_cow_encrypt(BlockDriverState *bs,
{
if (bytes && bs->encrypted) {
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((bytes & ~BDRV_SECTOR_MASK) == 0);
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;
}
}
diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c
index e3066075da..0e20723a4b 100644
--- a/block/qcow2-threads.c
+++ b/block/qcow2-threads.c
@@ -30,8 +30,7 @@
#include "qcow2.h"
#include "block/thread-pool.h"
-
-#define QCOW2_MAX_THREADS 4
+#include "crypto.h"
static int coroutine_fn
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,
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, );
+}
+
+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);
+}
diff --git a/block/qcow2.c b/block/qcow2.c
index 76d3715350..f94e5960f2 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -296,7 +296,7 @@ static int qcow2_read_extensions(BlockDriverState *bs,
uint64_t start_offset,
}
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",