From 807019734e97c7b80476098145d42f559118c719 Mon Sep 17 00:00:00 2001 From: Michael Haeuptle Date: Thu, 22 Oct 2020 14:08:33 +0000 Subject: [PATCH] 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 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4831 (master) (cherry picked from commit 7fc48a5ffc2c7926c09adae3f5fcc2a29e938540) Change-Id: Ia238c8aeae720832068de28ce4d34a9d233344fb Signed-off-by: Tomasz Zawadzki Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4959 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Michael Haeuptle Reviewed-by: Shuhei Matsumoto --- lib/nvme/nvme.c | 8 ++++++++ lib/nvme/nvme_ctrlr.c | 2 +- lib/nvme/nvme_internal.h | 3 +++ test/unit/lib/nvme/nvme.c/nvme_ut.c | 11 +++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/nvme/nvme.c b/lib/nvme/nvme.c index 7aa75e7a3..32f60e2a3 100644 --- a/lib/nvme/nvme.c +++ b/lib/nvme/nvme.c @@ -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) { diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index 7d57a093e..a9dc4bf7f 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -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; } diff --git a/lib/nvme/nvme_internal.h b/lib/nvme/nvme_internal.h index 69847304c..30419781e 100644 --- a/lib/nvme/nvme_internal.h +++ b/lib/nvme/nvme_internal.h @@ -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, diff --git a/test/unit/lib/nvme/nvme.c/nvme_ut.c b/test/unit/lib/nvme/nvme.c/nvme_ut.c index c0549f6e7..bef45c63f 100644 --- a/test/unit/lib/nvme/nvme.c/nvme_ut.c +++ b/test/unit/lib/nvme/nvme.c/nvme_ut.c @@ -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));