Skip to content

Commit 0618764

Browse files
Ben Collinssnitm
authored andcommitted
dm crypt: fix deadlock when async crypto algorithm returns -EBUSY
I suspect this doesn't show up for most anyone because software algorithms typically don't have a sense of being too busy. However, when working with the Freescale CAAM driver it will return -EBUSY on occasion under heavy -- which resulted in dm-crypt deadlock. After checking the logic in some other drivers, the scheme for crypt_convert() and it's callback, kcryptd_async_done(), were not correctly laid out to properly handle -EBUSY or -EINPROGRESS. Fix this by using the completion for both -EBUSY and -EINPROGRESS. Now crypt_convert()'s use of completion is comparable to af_alg_wait_for_completion(). Similarly, kcryptd_async_done() follows the pattern used in af_alg_complete(). Before this fix dm-crypt would lockup within 1-2 minutes running with the CAAM driver. Fix was regression tested against software algorithms on PPC32 and x86_64, and things seem perfectly happy there as well. Signed-off-by: Ben Collins <[email protected]> Signed-off-by: Mike Snitzer <[email protected]> Cc: [email protected]
1 parent 5977907 commit 0618764

File tree

1 file changed

+6
-6
lines changed

1 file changed

+6
-6
lines changed

drivers/md/dm-crypt.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -925,11 +925,10 @@ static int crypt_convert(struct crypt_config *cc,
925925

926926
switch (r) {
927927
/* async */
928+
case -EINPROGRESS:
928929
case -EBUSY:
929930
wait_for_completion(&ctx->restart);
930931
reinit_completion(&ctx->restart);
931-
/* fall through*/
932-
case -EINPROGRESS:
933932
ctx->req = NULL;
934933
ctx->cc_sector++;
935934
continue;
@@ -1346,10 +1345,8 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
13461345
struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx);
13471346
struct crypt_config *cc = io->cc;
13481347

1349-
if (error == -EINPROGRESS) {
1350-
complete(&ctx->restart);
1348+
if (error == -EINPROGRESS)
13511349
return;
1352-
}
13531350

13541351
if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
13551352
error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
@@ -1360,12 +1357,15 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
13601357
crypt_free_req(cc, req_of_dmreq(cc, dmreq), io->base_bio);
13611358

13621359
if (!atomic_dec_and_test(&ctx->cc_pending))
1363-
return;
1360+
goto done;
13641361

13651362
if (bio_data_dir(io->base_bio) == READ)
13661363
kcryptd_crypt_read_done(io);
13671364
else
13681365
kcryptd_crypt_write_io_submit(io, 1);
1366+
done:
1367+
if (!completion_done(&ctx->restart))
1368+
complete(&ctx->restart);
13691369
}
13701370

13711371
static void kcryptd_crypt(struct work_struct *work)

0 commit comments

Comments
 (0)