diff mbox series

[1/2] crpyto: support encryt and decrypt parallelly using thread pool

Message ID 7fea2c563ffafa2128fb5af07e98c8fa1aca9441.1732789721.git.tugy@chinatelecom.cn (mailing list archive)
State New
Headers show
Series support block encryption/decryption in parallel | expand

Commit Message

Guoyi Tu Nov. 28, 2024, 10:51 a.m. UTC
From: Guoyi Tu <tugy@chinatelecom.cn>

Currently, disk I/O encryption and decryption operations are performed sequentially
in the main thread or IOthread. When the number of I/O requests increases,
this becomes a performance bottleneck.

To address this issue, this patch using the thread pool to perform I/O encryption
and decryption in parallel to improving overall efficiency.

Signed-off-by: Guoyi Tu <tugy@chinatelecom.cn>
---
 block/crypto.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 97 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/block/crypto.c b/block/crypto.c
index 80b2dba17a..c085f331ce 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -22,6 +22,7 @@ 
 
 #include "block/block_int.h"
 #include "block/qdict.h"
+#include "block/thread-pool.h"
 #include "sysemu/block-backend.h"
 #include "crypto/block.h"
 #include "qapi/opts-visitor.h"
@@ -40,6 +41,7 @@  struct BlockCrypto {
     QCryptoBlock *block;
     bool updating_keys;
     BdrvChild *header;  /* Reference to the detached LUKS header */
+    bool encrypt_in_parallel;
 };
 
 
@@ -460,6 +462,94 @@  static int block_crypto_reopen_prepare(BDRVReopenState *state,
     return 0;
 }
 
+
+typedef struct CryptoAIOData {
+    QCryptoBlock *block;
+    uint64_t offset;
+    uint8_t *buf;
+    size_t len;
+    bool encrypt;
+    Error **errp;
+} CryptoAIOData;
+
+
+static int handle_aiocb_encdec(void *opaque)
+{
+    CryptoAIOData *aiocb = opaque;
+
+    if (aiocb->encrypt) {
+        if (qcrypto_block_encrypt(aiocb->block, aiocb->offset,
+                                  aiocb->buf, aiocb->len, aiocb->errp) < 0) {
+            return -EIO;
+        }
+    } else {
+        if (qcrypto_block_decrypt(aiocb->block, aiocb->offset,
+                                  aiocb->buf, aiocb->len, aiocb->errp) < 0) {
+            return -EIO;
+        }
+    }
+
+    return 0;
+}
+
+
+static int coroutine_fn block_crypto_submit_co(BlockDriverState *bs, uint64_t offset,
+                                               uint8_t *buf, size_t len, bool encrypt,
+                                               Error **errp)
+{
+    BlockCrypto *crypto = bs->opaque;
+    CryptoAIOData acb;
+
+    acb = (CryptoAIOData) {
+        .block = crypto->block,
+        .offset = offset,
+        .buf = buf,
+        .len = len,
+        .encrypt = encrypt,
+        .errp = errp,
+    };
+    return thread_pool_submit_co(handle_aiocb_encdec, &acb);
+}
+
+
+static int coroutine_fn GRAPH_RDLOCK
+block_crypto_encrypt(BlockDriverState *bs, uint64_t offset,
+                     uint8_t *buf, size_t len, Error **errp)
+{
+    BlockCrypto *crypto = bs->opaque;
+    int ret = 0;
+
+    if (crypto->encrypt_in_parallel) {
+        ret = block_crypto_submit_co(bs, offset, buf, len, true, errp);
+    } else {
+        if (qcrypto_block_encrypt(crypto->block, offset, buf, len, errp) < 0) {
+            ret = -EIO;
+        }
+    }
+
+    return ret;
+}
+
+
+static int coroutine_fn GRAPH_RDLOCK
+block_crypto_decrypt(BlockDriverState *bs, uint64_t offset,
+                     uint8_t *buf, size_t len, Error **errp)
+{
+    BlockCrypto *crypto = bs->opaque;
+    int ret = 0;
+
+    if (crypto->encrypt_in_parallel) {
+        ret = block_crypto_submit_co(bs, offset, buf, len, false, errp);
+    } else {
+        if (qcrypto_block_decrypt(crypto->block, offset, buf, len, errp) < 0) {
+            ret = -EIO;
+        }
+    }
+
+    return ret;
+}
+
+
 /*
  * 1 MB bounce buffer gives good performance / memory tradeoff
  * when using cache=none|directsync.
@@ -508,9 +598,10 @@  block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
             goto cleanup;
         }
 
-        if (qcrypto_block_decrypt(crypto->block, offset + bytes_done,
-                                  cipher_data, cur_bytes, NULL) < 0) {
-            ret = -EIO;
+        ret = block_crypto_decrypt(bs, offset + bytes_done,
+                                   cipher_data, cur_bytes, NULL);
+
+        if (ret < 0) {
             goto cleanup;
         }
 
@@ -565,9 +656,9 @@  block_crypto_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
 
         qemu_iovec_to_buf(qiov, bytes_done, cipher_data, cur_bytes);
 
-        if (qcrypto_block_encrypt(crypto->block, offset + bytes_done,
-                                  cipher_data, cur_bytes, NULL) < 0) {
-            ret = -EIO;
+        ret = block_crypto_encrypt(bs, offset + bytes_done,
+                                   cipher_data, cur_bytes, NULL);
+        if (ret < 0) {
             goto cleanup;
         }