lkml.org 
[lkml]   [2015]   [Sep]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.4 045/146] dm crypt: fix deadlock when async crypto algorithm returns -EBUSY
    Date
    From: Ben Collins <ben.c@servergy.com>

    3.4.109-rc1 review patch. If anyone has any objections, please let me know.

    ------------------


    commit 0618764cb25f6fa9fb31152995de42a8a0496475 upstream.

    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 <ben.c@servergy.com>
    Signed-off-by: Mike Snitzer <snitzer@redhat.com>
    [lizf: Backported to 3.4: adjust context]
    Signed-off-by: Zefan Li <lizefan@huawei.com>
    ---
    drivers/md/dm-crypt.c | 12 ++++++------
    1 file changed, 6 insertions(+), 6 deletions(-)

    diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
    index 926989d..a1bd688 100644
    --- a/drivers/md/dm-crypt.c
    +++ b/drivers/md/dm-crypt.c
    @@ -782,11 +782,10 @@ static int crypt_convert(struct crypt_config *cc,

    switch (r) {
    /* async */
    + case -EINPROGRESS:
    case -EBUSY:
    wait_for_completion(&ctx->restart);
    INIT_COMPLETION(ctx->restart);
    - /* fall through*/
    - case -EINPROGRESS:
    this_cc->req = NULL;
    ctx->sector++;
    continue;
    @@ -1195,10 +1194,8 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
    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);
    + if (error == -EINPROGRESS)
    return;
    - }

    if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
    error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
    @@ -1209,12 +1206,15 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
    mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);

    if (!atomic_dec_and_test(&ctx->pending))
    - return;
    + goto done;

    if (bio_data_dir(io->base_bio) == READ)
    kcryptd_crypt_read_done(io);
    else
    kcryptd_crypt_write_io_submit(io, 1);
    +done:
    + if (!completion_done(&ctx->restart))
    + complete(&ctx->restart);
    }

    static void kcryptd_crypt(struct work_struct *work)
    --
    1.9.1


    \
     
     \ /
      Last update: 2015-09-15 12:21    [W:4.032 / U:0.432 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site