[PATCHv5 2/3] dm-crypt: handle memory allocation failures

Keith Busch <[email protected]> Thu, 9 Jul 2026 09:15:18 -0700
Newsgroups dev.linux.lists.dm-devel
Message-ID <[email protected]>
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