diff options
Diffstat (limited to 'drivers/md/dm-crypt.c')
-rw-r--r-- | drivers/md/dm-crypt.c | 21 |
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 | */ |
33 | struct convert_context { | 34 | struct 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 | ||
364 | static int crypt_convert_block(struct crypt_config *cc, | 376 | static 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 | ||