summaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorMilan Broz <mbroz@redhat.com>2008-02-08 02:11:09 +0000
committerAlasdair G Kergon <agk@redhat.com>2008-02-08 02:11:09 +0000
commit43d6903482eec168b727bc4bf76a9f415257d862 (patch)
treecc0f5d3621c052376d2f6cff85af87002e4df344 /drivers/md
parentddd42edfd8ec44595b1501318512bc29a36f015f (diff)
dm crypt: add completion for async
dm-crypt: Use crypto ablkcipher interface Prepare completion for async crypto request. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Milan Broz <mbroz@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-crypt.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 79316580c78..2ea3eb99c91 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -6,6 +6,7 @@
* This file is released under the GPL.
*/
+#include <linux/completion.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -31,6 +32,7 @@
* context holding the current state of a multi-part conversion
*/
struct convert_context {
+ struct completion restart;
struct bio *bio_in;
struct bio *bio_out;
unsigned int offset_in;
@@ -38,6 +40,7 @@ struct convert_context {
unsigned int idx_in;
unsigned int idx_out;
sector_t sector;
+ atomic_t pending;
};
/*
@@ -359,6 +362,15 @@ static void crypt_convert_init(struct crypt_config *cc,
ctx->idx_in = bio_in ? bio_in->bi_idx : 0;
ctx->idx_out = bio_out ? bio_out->bi_idx : 0;
ctx->sector = sector + cc->iv_offset;
+ init_completion(&ctx->restart);
+ /*
+ * Crypto operation can be asynchronous,
+ * ctx->pending is increased after request submission.
+ * We need to ensure that we don't call the crypt finish
+ * operation before pending got incremented
+ * (dependent on crypt submission return code).
+ */
+ atomic_set(&ctx->pending, 2);
}
static int crypt_convert_block(struct crypt_config *cc,
@@ -418,6 +430,15 @@ static int crypt_convert(struct crypt_config *cc,
ctx->sector++;
}
+ /*
+ * If there are pending crypto operation run async
+ * code. Otherwise process return code synchronously.
+ * The step of 2 ensures that async finish doesn't
+ * call crypto finish too early.
+ */
+ if (atomic_sub_return(2, &ctx->pending))
+ return -EINPROGRESS;
+
return r;
}