diff --git a/module/bdev/crypto/vbdev_crypto.c b/module/bdev/crypto/vbdev_crypto.c index 31135b964..7a9b721c5 100644 --- a/module/bdev/crypto/vbdev_crypto.c +++ b/module/bdev/crypto/vbdev_crypto.c @@ -818,28 +818,46 @@ _crypto_operation(struct spdk_bdev_io *bdev_io, enum rte_crypto_cipher_operation &crypto_ops[0], burst); - /* If any didn't get submitted, queue them for the poller to de-queue later. */ - if (num_enqueued_ops < cryop_cnt) { - for (crypto_index = num_enqueued_ops; crypto_index < cryop_cnt; crypto_index++) { - op_to_queue = (struct vbdev_crypto_op *)rte_crypto_op_ctod_offset(crypto_ops[crypto_index], - uint8_t *, - QUEUED_OP_OFFSET); - op_to_queue->cdev_id = cdev_id; - op_to_queue->qp = crypto_ch->device_qp->qp; - op_to_queue->crypto_op = crypto_ops[crypto_index]; - op_to_queue->bdev_io = bdev_io; - TAILQ_INSERT_TAIL(&crypto_ch->queued_cry_ops, - op_to_queue, - link); - } - - } - /* Add this bdev_io to our outstanding list if any of its crypto ops made it. */ if (num_enqueued_ops > 0) { TAILQ_INSERT_TAIL(&crypto_ch->pending_cry_ios, bdev_io, module_link); io_ctx->on_pending_list = true; } + /* We were unable to enqueue everything but did get some, so need to decide what + * to do based on the status of the last op. + */ + if (num_enqueued_ops < cryop_cnt) { + switch (crypto_ops[num_enqueued_ops]->status) { + case RTE_CRYPTO_OP_STATUS_NOT_PROCESSED: + /* Queue them up on a linked list to be resubmitted via the poller. */ + for (crypto_index = num_enqueued_ops; crypto_index < cryop_cnt; crypto_index++) { + op_to_queue = (struct vbdev_crypto_op *)rte_crypto_op_ctod_offset(crypto_ops[crypto_index], + uint8_t *, QUEUED_OP_OFFSET); + op_to_queue->cdev_id = cdev_id; + op_to_queue->qp = crypto_ch->device_qp->qp; + op_to_queue->crypto_op = crypto_ops[crypto_index]; + op_to_queue->bdev_io = bdev_io; + TAILQ_INSERT_TAIL(&crypto_ch->queued_cry_ops, + op_to_queue, + link); + } + break; + default: + /* For all other statuses, set the io_ctx bdev_io status so that + * the poller will pick the failure up for the overall bdev status. + */ + io_ctx->bdev_io_status = SPDK_BDEV_IO_STATUS_FAILED; + if (num_enqueued_ops == 0) { + /* If nothing was enqueued, but the last one wasn't because of + * busy, fail it now as the poller won't know anything about it. + */ + _crypto_operation_complete(bdev_io); + rc = -EINVAL; + goto error_attach_session; + } + break; + } + } return rc; diff --git a/test/unit/lib/bdev/crypto.c/crypto_ut.c b/test/unit/lib/bdev/crypto.c/crypto_ut.c index 38a0599c1..3625d8a9a 100644 --- a/test/unit/lib/bdev/crypto.c/crypto_ut.c +++ b/test/unit/lib/bdev/crypto.c/crypto_ut.c @@ -539,6 +539,7 @@ test_dev_full(void) { struct vbdev_crypto_op *queued_op; struct rte_crypto_sym_op *sym_op; + struct crypto_bdev_io *io_ctx; /* Two element block size read */ g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS; @@ -553,6 +554,7 @@ test_dev_full(void) g_enqueue_mock = g_dequeue_mock = 1; ut_rte_crypto_op_bulk_alloc = 2; + g_test_crypto_ops[1]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; CU_ASSERT(TAILQ_EMPTY(&g_crypto_ch->queued_cry_ops) == true); vbdev_crypto_submit_request(g_io_ch, g_bdev_io); @@ -582,9 +584,15 @@ test_dev_full(void) CU_ASSERT(sym_op->m_src->userdata == g_bdev_io); CU_ASSERT(sym_op->m_dst == NULL); CU_ASSERT(TAILQ_EMPTY(&g_crypto_ch->queued_cry_ops) == true); - spdk_mempool_put(g_mbuf_mp, g_test_crypto_ops[0]->sym->m_src); spdk_mempool_put(g_mbuf_mp, g_test_crypto_ops[1]->sym->m_src); + + /* Non-busy reason for enqueue failure, all were rejected. */ + g_enqueue_mock = 0; + g_test_crypto_ops[0]->status = RTE_CRYPTO_OP_STATUS_ERROR; + vbdev_crypto_submit_request(g_io_ch, g_bdev_io); + io_ctx = (struct crypto_bdev_io *)g_bdev_io->driver_ctx; + CU_ASSERT(io_ctx->bdev_io_status == SPDK_BDEV_IO_STATUS_FAILED); } static void