nvme: Update spdk_nvme_wait_for_completion_timeout error handling

Update error handling of spdk_nvme_wait_for_completion_timeout to
differentiate cases when request is completed (possibly with error)
or polling was aborted by timeout or transport/device error
The function returns 0 on success, -ECANCELED if transport/device
error occurred or operation timed out and -EIO if the
request is completed with error

Change-Id: I314f40d1acaa6cfa9b88e5417b1ee2c9801bbbd6
Signed-off-by: Alexey Marchuk <alexeymar@mellanox.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/481528
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com>
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Alexey Marchuk 2020-01-10 16:30:38 +03:00 committed by Tomasz Zawadzki
parent 39965ab048
commit 9ad2046ae1
2 changed files with 45 additions and 10 deletions

View File

@ -1,8 +1,8 @@
/*- /*-
* BSD LICENSE * BSD LICENSE
* *
* Copyright (c) Intel Corporation. * Copyright (c) Intel Corporation. All rights reserved.
* All rights reserved. * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -143,12 +143,27 @@ spdk_nvme_wait_for_completion(struct spdk_nvme_qpair *qpair,
return spdk_nvme_wait_for_completion_robust_lock(qpair, status, NULL); return spdk_nvme_wait_for_completion_robust_lock(qpair, status, NULL);
} }
/**
* Poll qpair for completions until a command completes.
*
* \param qpair queue to poll
* \param status completion status
* \param timeout_in_secs optional timeout
*
* \return 0 if command completed without error,
* -EIO if command completed with error,
* -ECANCELED if command is not completed due to transport/device error or time expired
*
* The command to wait upon must be submitted with nvme_completion_poll_cb as the callback
* and status as the callback argument.
*/
int int
spdk_nvme_wait_for_completion_timeout(struct spdk_nvme_qpair *qpair, spdk_nvme_wait_for_completion_timeout(struct spdk_nvme_qpair *qpair,
struct nvme_completion_poll_status *status, struct nvme_completion_poll_status *status,
uint64_t timeout_in_secs) uint64_t timeout_in_secs)
{ {
uint64_t timeout_tsc = 0; uint64_t timeout_tsc = 0;
int rc = 0;
memset(&status->cpl, 0, sizeof(status->cpl)); memset(&status->cpl, 0, sizeof(status->cpl));
status->done = false; status->done = false;
@ -157,14 +172,20 @@ spdk_nvme_wait_for_completion_timeout(struct spdk_nvme_qpair *qpair,
} }
while (status->done == false) { while (status->done == false) {
spdk_nvme_qpair_process_completions(qpair, 0); rc = spdk_nvme_qpair_process_completions(qpair, 0);
if (rc < 0) {
status->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
status->cpl.status.sc = SPDK_NVME_SC_ABORTED_SQ_DELETION;
break;
}
if (timeout_tsc && spdk_get_ticks() > timeout_tsc) { if (timeout_tsc && spdk_get_ticks() > timeout_tsc) {
break; break;
} }
} }
if (status->done == false) { if (status->done == false || rc < 0) {
return -EIO; return -ECANCELED;
} }
return spdk_nvme_cpl_is_error(&status->cpl) ? -EIO : 0; return spdk_nvme_cpl_is_error(&status->cpl) ? -EIO : 0;

View File

@ -1,8 +1,8 @@
/*- /*-
* BSD LICENSE * BSD LICENSE
* *
* Copyright (c) Intel Corporation. * Copyright (c) Intel Corporation. All rights reserved.
* All rights reserved. * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -1210,14 +1210,16 @@ test_nvme_request_check_timeout(void)
struct nvme_completion_poll_status g_status; struct nvme_completion_poll_status g_status;
uint64_t completion_delay, timeout_in_secs; uint64_t completion_delay, timeout_in_secs;
int g_process_comp_result;
int int
spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions) spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
{ {
spdk_delay_us(completion_delay * spdk_get_ticks_hz()); spdk_delay_us(completion_delay * spdk_get_ticks_hz());
g_status.done = completion_delay < timeout_in_secs ? true : false; g_status.done = completion_delay < timeout_in_secs && g_process_comp_result == 0 ? true : false;
return 0; return g_process_comp_result;
} }
static void static void
@ -1235,7 +1237,19 @@ test_nvme_wait_for_completion(void)
g_status.done = true; g_status.done = true;
rc = spdk_nvme_wait_for_completion_timeout(&qpair, &g_status, timeout_in_secs); rc = spdk_nvme_wait_for_completion_timeout(&qpair, &g_status, timeout_in_secs);
CU_ASSERT(g_status.done == false); CU_ASSERT(g_status.done == false);
CU_ASSERT(rc == -EIO); CU_ASSERT(rc == -ECANCELED);
/* spdk_nvme_qpair_process_completions returns error */
g_process_comp_result = -1;
completion_delay = 1;
timeout_in_secs = 2;
rc = spdk_nvme_wait_for_completion_timeout(&qpair, &g_status, timeout_in_secs);
CU_ASSERT(rc == -ECANCELED);
CU_ASSERT(g_status.done == false);
CU_ASSERT(g_status.cpl.status.sct == SPDK_NVME_SCT_GENERIC);
CU_ASSERT(g_status.cpl.status.sc == SPDK_NVME_SC_ABORTED_SQ_DELETION);
g_process_comp_result = 0;
/* complete in time */ /* complete in time */
completion_delay = 1; completion_delay = 1;