diff --git a/module/bdev/nvme/bdev_nvme.c b/module/bdev/nvme/bdev_nvme.c index 081de0b3e..e6c9e10fe 100644 --- a/module/bdev/nvme/bdev_nvme.c +++ b/module/bdev/nvme/bdev_nvme.c @@ -1863,7 +1863,11 @@ bdev_nvme_reconnect_delay_timer_expired(void *ctx) spdk_poller_unregister(&nvme_ctrlr->reconnect_delay_timer); - assert(nvme_ctrlr->reconnect_is_delayed == true); + if (!nvme_ctrlr->reconnect_is_delayed) { + pthread_mutex_unlock(&nvme_ctrlr->mutex); + return SPDK_POLLER_BUSY; + } + nvme_ctrlr->reconnect_is_delayed = false; if (nvme_ctrlr->destruct) { @@ -2081,6 +2085,21 @@ bdev_nvme_reset_destroy_qpairs(struct nvme_ctrlr *nvme_ctrlr) bdev_nvme_reset_ctrlr); } +static void +_bdev_nvme_reconnect(void *ctx) +{ + struct nvme_ctrlr *nvme_ctrlr = ctx; + + assert(nvme_ctrlr->resetting == true); + assert(nvme_ctrlr->thread == spdk_get_thread()); + + spdk_poller_unregister(&nvme_ctrlr->reconnect_delay_timer); + + spdk_poller_resume(nvme_ctrlr->adminq_timer_poller); + + bdev_nvme_reconnect_ctrlr(nvme_ctrlr); +} + static void _bdev_nvme_reset(void *ctx) { @@ -2099,6 +2118,8 @@ _bdev_nvme_reset(void *ctx) static int bdev_nvme_reset(struct nvme_ctrlr *nvme_ctrlr) { + spdk_msg_fn msg_fn; + pthread_mutex_lock(&nvme_ctrlr->mutex); if (nvme_ctrlr->destruct) { pthread_mutex_unlock(&nvme_ctrlr->mutex); @@ -2111,20 +2132,22 @@ bdev_nvme_reset(struct nvme_ctrlr *nvme_ctrlr) return -EBUSY; } - if (nvme_ctrlr->reconnect_is_delayed) { - pthread_mutex_unlock(&nvme_ctrlr->mutex); - SPDK_NOTICELOG("Reconnect is already scheduled.\n"); - return -EBUSY; - } - nvme_ctrlr->resetting = true; - assert(nvme_ctrlr->reset_start_tsc == 0); + if (nvme_ctrlr->reconnect_is_delayed) { + SPDK_DEBUGLOG(bdev_nvme, "Reconnect is already scheduled.\n"); + msg_fn = _bdev_nvme_reconnect; + nvme_ctrlr->reconnect_is_delayed = false; + } else { + msg_fn = _bdev_nvme_reset; + assert(nvme_ctrlr->reset_start_tsc == 0); + } + nvme_ctrlr->reset_start_tsc = spdk_get_ticks(); pthread_mutex_unlock(&nvme_ctrlr->mutex); - spdk_thread_send_msg(nvme_ctrlr->thread, _bdev_nvme_reset, nvme_ctrlr); + spdk_thread_send_msg(nvme_ctrlr->thread, msg_fn, nvme_ctrlr); return 0; } diff --git a/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c b/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c index 82917f3f5..c9a141e59 100644 --- a/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c +++ b/test/unit/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut.c @@ -5251,6 +5251,30 @@ test_reconnect_ctrlr(void) CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL); CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == true); + /* A new reset starts from thread 0. */ + set_thread(1); + + /* The reset should cancel the reconnect timer and should start from reconnection. + * Then, the reset should fail and a reconnect timer should be registered again. + */ + ctrlr.fail_reset = true; + ctrlr.is_failed = true; + + rc = bdev_nvme_reset(nvme_ctrlr); + CU_ASSERT(rc == 0); + CU_ASSERT(nvme_ctrlr->resetting == true); + CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == false); + CU_ASSERT(ctrlr.is_failed == true); + + poll_threads(); + + CU_ASSERT(nvme_ctrlr->resetting == false); + CU_ASSERT(ctrlr.is_failed == false); + CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL); + CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL); + CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL); + CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == true); + /* Then a reconnect retry should suceeed. */ ctrlr.fail_reset = false;