From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
To: qemu-devel@nongnu.org, qemu-block@nongnu.org
Cc: mreitz@redhat.com, kwolf@redhat.com, berrange@redhat.com,
berto@igalia.com, vsementsov@virtuozzo.com, den@openvz.org
Subject: [Qemu-devel] [PATCH 07/11] qcow2-threads: add encryption
Date: Fri, 23 Nov 2018 19:55:07 +0300 [thread overview]
Message-ID: <20181123165511.416480-8-vsementsov@virtuozzo.com> (raw)
In-Reply-To: <20181123165511.416480-1-vsementsov@virtuozzo.com>
Add thread-based encrypt/decrypt. QCrypto don't support parallel
operations with one block, so we need QCryptoBlock for each thread.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
block/qcow2.h | 12 +++++++++
block/qcow2-threads.c | 62 +++++++++++++++++++++++++++++++++++++++++++
block/qcow2.c | 57 ++++++++++++++++++++++++++++++++-------
3 files changed, 122 insertions(+), 9 deletions(-)
diff --git a/block/qcow2.h b/block/qcow2.h
index 7bef0393ce..351ad8d3e7 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -260,6 +260,12 @@ typedef struct Qcow2BitmapHeaderExt {
#define QCOW2_MAX_THREADS 4
typedef struct Qcow2PerThreadData {
bool in_use;
+
+ /* QCryptoBlock doesn't support parallel operations in threads, so we can't
+ * use BDRVQcow2State.crypto and instead we need separate crypto block for
+ * each thread.
+ */
+ QCryptoBlock *crypto;
} Qcow2PerThreadData;
typedef struct Qcow2ThreadsState {
@@ -711,5 +717,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-threads.c b/block/qcow2-threads.c
index 3ed990ef2f..0a75c1aead 100644
--- a/block/qcow2-threads.c
+++ b/block/qcow2-threads.c
@@ -30,6 +30,7 @@
#include "qcow2.h"
#include "block/thread-pool.h"
+#include "crypto.h"
typedef struct Qcow2ProcessData {
Qcow2PerThreadData *self;
@@ -217,3 +218,64 @@ 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);
}
+
+
+/*
+ * Encryption
+ */
+
+typedef int (*Qcow2EncryptFunc)(QCryptoBlock *block, uint64_t offset,
+ uint8_t *buf, size_t len, Error **errp);
+/*
+ * encrypt functions are qcrypto_block_encrypt() and qcrypto_block_decrypt()
+ */
+
+typedef struct Qcow2EncryptData {
+ uint64_t offset;
+ uint8_t *buf;
+ size_t len;
+
+ Qcow2EncryptFunc func;
+} Qcow2EncryptData;
+
+static int qcow2_encrypt_pool_func(void *opaque)
+{
+ Qcow2ProcessData *pdata = opaque;
+ Qcow2EncryptData *data = pdata->arg;
+
+ return data->func(pdata->self->crypto,
+ data->offset, data->buf, data->len, NULL);
+}
+
+static int coroutine_fn
+qcow2_co_do_crypt(BlockDriverState *bs, uint64_t file_cluster_offset,
+ uint64_t offset, void *buf, size_t len, Qcow2EncryptFunc func)
+{
+ BDRVQcow2State *s = bs->opaque;
+ Qcow2EncryptData arg = {
+ .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_encrypt_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_do_crypt(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_do_crypt(bs, file_cluster_offset, offset, buf, len,
+ qcrypto_block_decrypt);
+}
diff --git a/block/qcow2.c b/block/qcow2.c
index 295ae926ee..1e28f17373 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -170,6 +170,47 @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
return ret;
}
+static void qcow2_crypto_blocks_free(BDRVQcow2State *s)
+{
+ int i;
+
+ qcrypto_block_free(s->crypto);
+ s->crypto = NULL;
+
+ for (i = 0; i < QCOW2_MAX_THREADS; i++) {
+ qcrypto_block_free(s->threads.per_thread[i].crypto);
+ s->threads.per_thread[i].crypto = NULL;
+ }
+}
+
+static int qcow2_crypto_blocks_open(BDRVQcow2State *s,
+ const char *optprefix,
+ QCryptoBlockReadFunc readfunc,
+ void *opaque,
+ unsigned int flags,
+ Error **errp)
+{
+ int i;
+
+ s->crypto = qcrypto_block_open(s->crypto_opts, optprefix,
+ readfunc, opaque, flags, errp);
+ if (!s->crypto) {
+ qcrypto_block_free(s->crypto);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < QCOW2_MAX_THREADS; i++) {
+ s->threads.per_thread[i].crypto =
+ qcrypto_block_open(s->crypto_opts, optprefix,
+ readfunc, opaque, flags, errp);
+ if (!s->threads.per_thread[i].crypto) {
+ qcow2_crypto_blocks_free(s);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
/*
* read qcow2 extension and fill bs
@@ -295,11 +336,11 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
if (flags & BDRV_O_NO_IO) {
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
}
- s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
+ ret = qcow2_crypto_blocks_open(s, "encrypt.",
qcow2_crypto_hdr_read_func,
bs, cflags, errp);
- if (!s->crypto) {
- return -EINVAL;
+ if (ret < 0) {
+ return ret;
}
} break;
@@ -1446,10 +1487,9 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
if (flags & BDRV_O_NO_IO) {
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
}
- s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
+ ret = qcow2_crypto_blocks_open(s, "encrypt.",
NULL, NULL, cflags, errp);
- if (!s->crypto) {
- ret = -EINVAL;
+ if (ret < 0) {
goto fail;
}
} else if (!(flags & BDRV_O_NO_IO)) {
@@ -1619,7 +1659,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
if (s->refcount_block_cache) {
qcow2_cache_destroy(s->refcount_block_cache);
}
- qcrypto_block_free(s->crypto);
+ qcow2_crypto_blocks_free(s);
qapi_free_QCryptoBlockOpenOptions(s->crypto_opts);
return ret;
}
@@ -2214,8 +2254,7 @@ static void qcow2_close(BlockDriverState *bs)
qcow2_cache_destroy(s->l2_table_cache);
qcow2_cache_destroy(s->refcount_block_cache);
- qcrypto_block_free(s->crypto);
- s->crypto = NULL;
+ qcow2_crypto_blocks_free(s);
g_free(s->unknown_header_fields);
cleanup_unknown_header_ext(bs);
--
2.18.0
next prev parent reply other threads:[~2018-11-23 16:55 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-11-23 16:55 [Qemu-devel] [PATCH 00/11] qcow2: encryption threads Vladimir Sementsov-Ogievskiy
2018-11-23 16:55 ` [Qemu-devel] [PATCH 01/11] qcow2.h: add missing include Vladimir Sementsov-Ogievskiy
2018-11-23 16:55 ` [Qemu-devel] [PATCH 02/11] qcow2: add separate file for threaded data processing functions Vladimir Sementsov-Ogievskiy
2018-11-23 16:55 ` [Qemu-devel] [PATCH 03/11] qcow2-threads: use thread_pool_submit_co Vladimir Sementsov-Ogievskiy
2018-11-23 16:55 ` [Qemu-devel] [PATCH 04/11] qcow2: split out data processing threads state from BDRVQcow2State Vladimir Sementsov-Ogievskiy
2018-11-23 16:55 ` [Qemu-devel] [PATCH 05/11] qcow2-threads: split out generic path Vladimir Sementsov-Ogievskiy
2018-11-23 16:55 ` [Qemu-devel] [PATCH 06/11] qcow2-threads: add per-thread data Vladimir Sementsov-Ogievskiy
2018-11-23 16:55 ` Vladimir Sementsov-Ogievskiy [this message]
2018-11-27 16:21 ` [Qemu-devel] [PATCH 07/11] qcow2-threads: add encryption Daniel P. Berrangé
2018-11-23 16:55 ` [Qemu-devel] [PATCH 08/11] qcow2: bdrv_co_preadv: improve locking Vladimir Sementsov-Ogievskiy
2018-11-23 16:55 ` [Qemu-devel] [PATCH 09/11] qcow2: qcow2_co_preadv: skip using hd_qiov when possible Vladimir Sementsov-Ogievskiy
2018-11-23 16:55 ` [Qemu-devel] [PATCH 10/11] qcow2: bdrv_co_pwritev: move encryption code out of the lock Vladimir Sementsov-Ogievskiy
2018-11-23 16:55 ` [Qemu-devel] [PATCH 11/11] qcow2: do encryption in threads Vladimir Sementsov-Ogievskiy
2018-11-27 16:23 ` [Qemu-devel] [PATCH 00/11] qcow2: encryption threads Daniel P. Berrangé
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181123165511.416480-8-vsementsov@virtuozzo.com \
--to=vsementsov@virtuozzo.com \
--cc=berrange@redhat.com \
--cc=berto@igalia.com \
--cc=den@openvz.org \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).