diff --git a/lib/nvme/nvme.c b/lib/nvme/nvme.c index 7d7a7abf8..83cca14bf 100644 --- a/lib/nvme/nvme.c +++ b/lib/nvme/nvme.c @@ -1,8 +1,8 @@ /*- * BSD LICENSE * - * Copyright (c) Intel Corporation. - * All rights reserved. + * Copyright (c) Intel Corporation. All rights reserved. + * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * 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); } +/** + * 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 spdk_nvme_wait_for_completion_timeout(struct spdk_nvme_qpair *qpair, struct nvme_completion_poll_status *status, uint64_t timeout_in_secs) { uint64_t timeout_tsc = 0; + int rc = 0; memset(&status->cpl, 0, sizeof(status->cpl)); status->done = false; @@ -157,14 +172,20 @@ spdk_nvme_wait_for_completion_timeout(struct spdk_nvme_qpair *qpair, } 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) { break; } } - if (status->done == false) { - return -EIO; + if (status->done == false || rc < 0) { + return -ECANCELED; } return spdk_nvme_cpl_is_error(&status->cpl) ? -EIO : 0; diff --git a/test/unit/lib/nvme/nvme.c/nvme_ut.c b/test/unit/lib/nvme/nvme.c/nvme_ut.c index 808f22a62..b95beb34c 100644 --- a/test/unit/lib/nvme/nvme.c/nvme_ut.c +++ b/test/unit/lib/nvme/nvme.c/nvme_ut.c @@ -1,8 +1,8 @@ /*- * BSD LICENSE * - * Copyright (c) Intel Corporation. - * All rights reserved. + * Copyright (c) Intel Corporation. All rights reserved. + * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * 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; uint64_t completion_delay, timeout_in_secs; +int g_process_comp_result; + int spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions) { 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 @@ -1235,7 +1237,19 @@ test_nvme_wait_for_completion(void) g_status.done = true; rc = spdk_nvme_wait_for_completion_timeout(&qpair, &g_status, timeout_in_secs); 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 */ completion_delay = 1;