module/crypto: handle enqueue errors

A recent change in the CryptoDev API means that failure to enqueue
all attempted submissions does not automtically mean busy. We need
to check the status of the last submitted op and only retry if
busy, otherwise fail the IO.

Signed-off-by: paul luse <paul.e.luse@intel.com>
Change-Id: I0873d07a430a08f5aee25581e47187ef60ba8542
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/472400
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
paul luse 2019-10-25 14:22:35 +00:00 committed by Tomasz Zawadzki
parent c602bd81f6
commit dc8788d150
2 changed files with 44 additions and 18 deletions

View File

@ -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;

View File

@ -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