aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-crypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-crypt.c')
-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 79316580c780..2ea3eb99c91f 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -6,6 +6,7 @@
6 * This file is released under the GPL. 6 * This file is released under the GPL.
7 */ 7 */
8 8
9#include <linux/completion.h>
9#include <linux/err.h> 10#include <linux/err.h>
10#include <linux/module.h> 11#include <linux/module.h>
11#include <linux/init.h> 12#include <linux/init.h>
@@ -31,6 +32,7 @@
31 * context holding the current state of a multi-part conversion 32 * context holding the current state of a multi-part conversion
32 */ 33 */
33struct convert_context { 34struct convert_context {
35 struct completion restart;
34 struct bio *bio_in; 36 struct bio *bio_in;
35 struct bio *bio_out; 37 struct bio *bio_out;
36 unsigned int offset_in; 38 unsigned int offset_in;
@@ -38,6 +40,7 @@ struct convert_context {
38 unsigned int idx_in; 40 unsigned int idx_in;
39 unsigned int idx_out; 41 unsigned int idx_out;
40 sector_t sector; 42 sector_t sector;
43 atomic_t pending;
41}; 44};
42 45
43/* 46/*
@@ -359,6 +362,15 @@ static void crypt_convert_init(struct crypt_config *cc,
359 ctx->idx_in = bio_in ? bio_in->bi_idx : 0; 362 ctx->idx_in = bio_in ? bio_in->bi_idx : 0;
360 ctx->idx_out = bio_out ? bio_out->bi_idx : 0; 363 ctx->idx_out = bio_out ? bio_out->bi_idx : 0;
361 ctx->sector = sector + cc->iv_offset; 364 ctx->sector = sector + cc->iv_offset;
365 init_completion(&ctx->restart);
366 /*
367 * Crypto operation can be asynchronous,
368 * ctx->pending is increased after request submission.
369 * We need to ensure that we don't call the crypt finish
370 * operation before pending got incremented
371 * (dependent on crypt submission return code).
372 */
373 atomic_set(&ctx->pending, 2);
362} 374}
363 375
364static int crypt_convert_block(struct crypt_config *cc, 376static int crypt_convert_block(struct crypt_config *cc,
@@ -418,6 +430,15 @@ static int crypt_convert(struct crypt_config *cc,
418 ctx->sector++; 430 ctx->sector++;
419 } 431 }
420 432
433 /*
434 * If there are pending crypto operation run async
435 * code. Otherwise process return code synchronously.
436 * The step of 2 ensures that async finish doesn't
437 * call crypto finish too early.
438 */
439 if (atomic_sub_return(2, &ctx->pending))
440 return -EINPROGRESS;
441
421 return r; 442 return r;
422} 443}
423 444