From: Keith Busch <[email protected]>

There are a few paths that can fail with -ENOMEM, like skcipher_copy_iv,
which had been treated as a generic failure. This is a transient host
resource issue that can be retried later.

Signed-off-by: Keith Busch <[email protected]>
---
 drivers/md/dm-crypt.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 608b617fb817f..fc9c875cccfd2 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1338,6 +1338,8 @@ static int crypt_convert_block_aead(struct crypt_config 
*cc,
                        dm_audit_log_bio(DM_MSG_PREFIX, "integrity-aead",
                                         ctx->bio_in, s, 0);
                }
+       } else if (unlikely(r == -ENOMEM)) {
+               return r;
        }
 
        if (!r && cc->iv_gen_ops && cc->iv_gen_ops->post)
@@ -1417,6 +1419,9 @@ static int crypt_convert_block_skcipher(struct 
crypt_config *cc,
        else
                r = crypto_skcipher_decrypt(req);
 
+       if (unlikely(r == -ENOMEM))
+               return r;
+
        if (!r && cc->iv_gen_ops && cc->iv_gen_ops->post)
                cc->iv_gen_ops->post(cc, org_iv, dmreq);
 
@@ -1593,6 +1598,13 @@ static blk_status_t crypt_convert(struct crypt_config 
*cc,
                case -EBADMSG:
                        atomic_dec(&ctx->cc_pending);
                        return BLK_STS_PROTECTION;
+               /*
+                * There was a host resource issue.
+                */
+               case -ENOMEM:
+                       atomic_dec(&ctx->cc_pending);
+                       complete(&ctx->restart);
+                       return BLK_STS_RESOURCE;
                /*
                 * There was an error while processing the request.
                 */
@@ -2072,10 +2084,11 @@ static void kcryptd_crypt_write_convert(struct 
dm_crypt_io *io)
                          test_bit(DM_CRYPT_NO_WRITE_WORKQUEUE, &cc->flags), 
true);
        /*
         * Crypto API backlogged the request, because its queue was full
-        * and we're in softirq context, so continue from a workqueue
-        * (TODO: is it actually possible to be in softirq in the write path?)
+        * and we're in softirq context, or a host memory allocation
+        * temporarily failed, so continue from a workqueue (TODO: is it
+        * actually possible to be in softirq in the write path?)
         */
-       if (r == BLK_STS_DEV_RESOURCE) {
+       if (r == BLK_STS_DEV_RESOURCE || r == BLK_STS_RESOURCE) {
                INIT_WORK(&io->work, kcryptd_crypt_write_continue);
                queue_work(cc->crypt_queue, &io->work);
                return;
@@ -2148,9 +2161,10 @@ static void kcryptd_crypt_read_convert(struct 
dm_crypt_io *io)
        }
        /*
         * Crypto API backlogged the request, because its queue was full
-        * and we're in softirq context, so continue from a workqueue
+        * and we're in softirq context, or a host memory allocation
+        * temporarily failed, so continue from a workqueue
         */
-       if (r == BLK_STS_DEV_RESOURCE) {
+       if (r == BLK_STS_DEV_RESOURCE || r == BLK_STS_RESOURCE) {
                INIT_WORK(&io->work, kcryptd_crypt_read_continue);
                queue_work(cc->crypt_queue, &io->work);
                return;
-- 
2.52.0


Reply via email to