From: Milan Broz <[email-masked]>

dm-crypt: Use crypto ablkcipher interface

Prepare callback function for async crypto operation.

Signed-off-by: Herbert Xu <[email-masked]>
Signed-off-by: Milan Broz <[email-masked]>
---
 drivers/md/dm-crypt.c |   43 +++++++++++++++++++++++++++++++++++++++----
 1 files changed, 39 insertions(+), 4 deletions(-)

Index: linux-2.6.24-rc5/drivers/md/dm-crypt.c
===================================================================
--- linux-2.6.24-rc5.orig/drivers/md/dm-crypt.c	2007-12-12 15:44:07.000000000 +0000
+++ linux-2.6.24-rc5/drivers/md/dm-crypt.c	2007-12-12 15:44:08.000000000 +0000
@@ -399,11 +399,16 @@ static int crypt_convert_block(struct cr
 					 ctx->sector);
 }
 
+static void kcryptd_async_done(struct crypto_async_request *async_req, int error);
 static void crypt_alloc_req(struct crypt_config *cc,
 			    struct convert_context *ctx)
 {
 	if (!cc->req)
 		cc->req = mempool_alloc(cc->req_pool, GFP_NOIO);
+	ablkcipher_request_set_tfm(cc->req, cc->tfm);
+	ablkcipher_request_set_callback(cc->req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+					     CRYPTO_TFM_REQ_MAY_SLEEP,
+					     kcryptd_async_done, ctx);
 }
 
 /*
@@ -606,6 +611,9 @@ static void kcryptd_io_read(struct dm_cr
 
 static void kcryptd_io_write(struct dm_crypt_io *io)
 {
+	struct bio *clone = io->ctx.bio_out;
+
+	generic_make_request(clone);
 }
 
 static void kcryptd_io(struct work_struct *work)
@@ -626,7 +634,8 @@ static void kcryptd_queue_io(struct dm_c
 	queue_work(cc->io_queue, &io->work);
 }
 
-static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int error)
+static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
+					  int error, int async)
 {
 	struct bio *clone = io->ctx.bio_out;
 	struct crypt_config *cc = io->target->private;
@@ -644,8 +653,12 @@ static void kcryptd_crypt_write_io_submi
 	clone->bi_sector = cc->start + io->sector;
 	io->sector += bio_sectors(clone);
 
-	atomic_inc(&io->pending);
-	generic_make_request(clone);
+	if (async)
+		kcryptd_queue_io(io);
+	else {
+		atomic_inc(&io->pending);
+		generic_make_request(clone);
+	}
 }
 
 static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io)
@@ -673,7 +686,7 @@ static void kcryptd_crypt_write_convert_
 
 		r = crypt_convert(cc, &io->ctx);
 
-		kcryptd_crypt_write_io_submit(io, r);
+		kcryptd_crypt_write_io_submit(io, r, 0);
 		if (unlikely(r < 0))
 			return;
 
@@ -718,6 +731,28 @@ static void kcryptd_crypt_read_convert(s
 	kcryptd_crypt_read_done(io, r);
 }
 
+static void kcryptd_async_done(struct crypto_async_request *async_req, int error)
+{
+	struct convert_context *ctx = async_req->data;
+	struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx);
+	struct crypt_config *cc = io->target->private;
+
+	if (error == -EINPROGRESS) {
+		complete(&ctx->restart);
+		return;
+	}
+
+	mempool_free(ablkcipher_request_cast(async_req), cc->req_pool);
+
+	if (!atomic_dec_and_test(&ctx->pending))
+		return;
+
+	if (bio_data_dir(io->base_bio) == READ)
+		kcryptd_crypt_read_done(io, error);
+	else
+		kcryptd_crypt_write_io_submit(io, error, 1);
+}
+
 static void kcryptd_crypt(struct work_struct *work)
 {
 	struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);