nvme: break completion loop when ctrlr is invalid

This fixes #1423 where the completion loop never
breaks when the NVMe ctrlr is no longer present.
This condition can happen during a hot remove.

Signed-off-by: Michael Haeuptle <michael.haeuptle@hpe.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4831 (master)

(cherry picked from commit 7fc48a5ffc)
Change-Id: Ia238c8aeae720832068de28ce4d34a9d233344fb
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4959
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Michael Haeuptle <michaelhaeuptle@gmail.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Michael Haeuptle 2020-10-22 14:08:33 +00:00 committed by Tomasz Zawadzki
parent ede2227a7c
commit 807019734e
4 changed files with 23 additions and 1 deletions

View File

@ -314,6 +314,14 @@ nvme_wait_for_completion_robust_lock_timeout(
rc = -1;
break;
}
if (qpair->ctrlr->trid.trtype == SPDK_NVME_TRANSPORT_PCIE) {
union spdk_nvme_csts_register csts = spdk_nvme_ctrlr_get_regs_csts(qpair->ctrlr);
if (csts.raw == SPDK_NVME_INVALID_REGISTER_VALUE) {
status->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
status->cpl.status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
break;
}
}
}
if (status->done == false) {

View File

@ -3445,7 +3445,7 @@ union spdk_nvme_csts_register spdk_nvme_ctrlr_get_regs_csts(struct spdk_nvme_ctr
union spdk_nvme_csts_register csts;
if (nvme_ctrlr_get_csts(ctrlr, &csts)) {
csts.raw = 0xFFFFFFFFu;
csts.raw = SPDK_NVME_INVALID_REGISTER_VALUE;
}
return csts;
}

View File

@ -191,6 +191,9 @@ extern pid_t g_spdk_nvme_pid;
#define NVME_FABRIC_CONNECT_COMMAND_TIMEOUT 500000
#endif
/* This value indicates that a read from a PCIe register is invalid. This can happen when a device is no longer present */
#define SPDK_NVME_INVALID_REGISTER_VALUE 0xFFFFFFFFu
enum nvme_payload_type {
NVME_PAYLOAD_TYPE_INVALID = 0,

View File

@ -91,6 +91,13 @@ nvme_ctrlr_destruct_poll_async(struct spdk_nvme_ctrlr *ctrlr,
return 0;
}
union spdk_nvme_csts_register
spdk_nvme_ctrlr_get_regs_csts(struct spdk_nvme_ctrlr *ctrlr)
{
union spdk_nvme_csts_register csts = {};
return csts;
}
void
spdk_nvme_ctrlr_get_default_ctrlr_opts(struct spdk_nvme_ctrlr_opts *opts, size_t opts_size)
{
@ -1270,9 +1277,13 @@ static void
test_nvme_wait_for_completion(void)
{
struct spdk_nvme_qpair qpair;
struct spdk_nvme_ctrlr ctrlr;
int rc = 0;
memset(&ctrlr, 0, sizeof(ctrlr));
ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
memset(&qpair, 0, sizeof(qpair));
qpair.ctrlr = &ctrlr;
/* completion timeout */
memset(&g_status, 0, sizeof(g_status));