nvme: Add an API for updating a controller trid.

This can be useful when trying to perform multipath failover at the
application level. However, the controller must be in the failed state
before calling this function.

Change-Id: I5403c0036fed5dd3600ee20592925297494ba8aa
Signed-off-by: Seth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/470699
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Seth Howell 2019-10-07 16:41:23 -07:00 committed by Jim Harris
parent 7d3771f93c
commit 5215fad6ef
3 changed files with 81 additions and 0 deletions

View File

@ -693,6 +693,25 @@ int spdk_nvme_probe_poll_async(struct spdk_nvme_probe_ctx *probe_ctx);
*/
int spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr);
/**
* Update the transport ID for a given controller.
*
* This function allows the user to set a new trid for a controller only if the
* controller is failed. The controller's failed state can be obtained from
* spdk_nvme_ctrlr_is_failed(). The controller can also be forced to the failed
* state using spdk_nvme_ctrlr_fail().
*
* This function also requires that the transport type and subnqn of the new trid
* be the same as the old trid.
*
* \param ctrlr Opaque handle to an NVMe controller.
* \param trid The new transport ID.
*
* \return 0 on success, -EINVAL if the trid is invalid,
* -EPERM if the ctrlr is not failed.
*/
int spdk_nvme_ctrlr_set_trid(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_transport_id *trid);
/**
* Perform a full hardware reset of the NVMe controller.
*

View File

@ -1107,6 +1107,35 @@ out:
return rc;
}
int
spdk_nvme_ctrlr_set_trid(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_transport_id *trid)
{
int rc = 0;
nvme_robust_mutex_lock(&ctrlr->ctrlr_lock);
if (ctrlr->is_failed == false) {
rc = -EPERM;
goto out;
}
if (trid->trtype != ctrlr->trid.trtype) {
rc = -EINVAL;
goto out;
}
if (strncmp(trid->subnqn, ctrlr->trid.subnqn, SPDK_NVMF_NQN_MAX_LEN)) {
rc = -EINVAL;
goto out;
}
ctrlr->trid = *trid;
out:
nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock);
return rc;
}
static void
nvme_ctrlr_identify_done(void *arg, const struct spdk_nvme_cpl *cpl)
{

View File

@ -1890,6 +1890,38 @@ test_nvme_ctrlr_init_delay(void)
nvme_ctrlr_destruct(&ctrlr);
}
static void
test_spdk_nvme_ctrlr_set_trid(void)
{
struct spdk_nvme_ctrlr ctrlr = {0};
struct spdk_nvme_transport_id new_trid = {0};
ctrlr.is_failed = false;
ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_RDMA;
snprintf(ctrlr.trid.subnqn, SPDK_NVMF_NQN_MAX_LEN, "%s", "nqn.2016-06.io.spdk:cnode1");
snprintf(ctrlr.trid.traddr, SPDK_NVMF_TRADDR_MAX_LEN, "%s", "192.168.100.8");
snprintf(ctrlr.trid.trsvcid, SPDK_NVMF_TRSVCID_MAX_LEN, "%s", "4420");
CU_ASSERT(spdk_nvme_ctrlr_set_trid(&ctrlr, &new_trid) == -EPERM);
ctrlr.is_failed = true;
new_trid.trtype = SPDK_NVME_TRANSPORT_TCP;
CU_ASSERT(spdk_nvme_ctrlr_set_trid(&ctrlr, &new_trid) == -EINVAL);
CU_ASSERT(ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_RDMA);
new_trid.trtype = SPDK_NVME_TRANSPORT_RDMA;
snprintf(new_trid.subnqn, SPDK_NVMF_NQN_MAX_LEN, "%s", "nqn.2016-06.io.spdk:cnode2");
CU_ASSERT(spdk_nvme_ctrlr_set_trid(&ctrlr, &new_trid) == -EINVAL);
CU_ASSERT(strncmp(ctrlr.trid.subnqn, "nqn.2016-06.io.spdk:cnode1", SPDK_NVMF_NQN_MAX_LEN) == 0);
snprintf(new_trid.subnqn, SPDK_NVMF_NQN_MAX_LEN, "%s", "nqn.2016-06.io.spdk:cnode1");
snprintf(new_trid.traddr, SPDK_NVMF_TRADDR_MAX_LEN, "%s", "192.168.100.9");
snprintf(new_trid.trsvcid, SPDK_NVMF_TRSVCID_MAX_LEN, "%s", "4421");
CU_ASSERT(spdk_nvme_ctrlr_set_trid(&ctrlr, &new_trid) == 0);
CU_ASSERT(strncmp(ctrlr.trid.traddr, "192.168.100.9", SPDK_NVMF_TRADDR_MAX_LEN) == 0);
CU_ASSERT(strncmp(ctrlr.trid.trsvcid, "4421", SPDK_NVMF_TRSVCID_MAX_LEN) == 0);
}
int main(int argc, char **argv)
{
CU_pSuite suite = NULL;
@ -1944,6 +1976,7 @@ int main(int argc, char **argv)
test_nvme_ctrlr_test_active_ns) == NULL
|| CU_add_test(suite, "test_spdk_nvme_ctrlr_reconnect_io_qpair",
test_spdk_nvme_ctrlr_reconnect_io_qpair) == NULL
|| CU_add_test(suite, "test_spdk_nvme_ctrlr_set_trid", test_spdk_nvme_ctrlr_set_trid) == NULL
) {
CU_cleanup_registry();
return CU_get_error();