bdev/nvme: add a function for specifying a multipath trid.
This is part of a larger series enabling failover at the bdev layer for NVMe. Signed-off-by: Seth Howell <seth.howell@intel.com> Change-Id: Ic5c128244699c1a47275145ca7e41aa5f1366259 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3044 Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
parent
d88915f5ff
commit
0c6979e29b
@ -1361,6 +1361,7 @@ create_ctrlr(struct spdk_nvme_ctrlr *ctrlr,
|
|||||||
uint32_t prchk_flags)
|
uint32_t prchk_flags)
|
||||||
{
|
{
|
||||||
struct nvme_bdev_ctrlr *nvme_bdev_ctrlr;
|
struct nvme_bdev_ctrlr *nvme_bdev_ctrlr;
|
||||||
|
struct nvme_bdev_ctrlr_trid *trid_entry;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -1370,22 +1371,25 @@ create_ctrlr(struct spdk_nvme_ctrlr *ctrlr,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
nvme_bdev_ctrlr->connected_trid = calloc(1, sizeof(*nvme_bdev_ctrlr->connected_trid));
|
TAILQ_INIT(&nvme_bdev_ctrlr->trids);
|
||||||
if (nvme_bdev_ctrlr->connected_trid == NULL) {
|
|
||||||
SPDK_ERRLOG("Failed to allocate device trid struct\n");
|
|
||||||
free(nvme_bdev_ctrlr);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
nvme_bdev_ctrlr->num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr);
|
nvme_bdev_ctrlr->num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr);
|
||||||
nvme_bdev_ctrlr->namespaces = calloc(nvme_bdev_ctrlr->num_ns, sizeof(struct nvme_bdev_ns *));
|
nvme_bdev_ctrlr->namespaces = calloc(nvme_bdev_ctrlr->num_ns, sizeof(struct nvme_bdev_ns *));
|
||||||
if (!nvme_bdev_ctrlr->namespaces) {
|
if (!nvme_bdev_ctrlr->namespaces) {
|
||||||
SPDK_ERRLOG("Failed to allocate block namespaces pointer\n");
|
SPDK_ERRLOG("Failed to allocate block namespaces pointer\n");
|
||||||
free(nvme_bdev_ctrlr->connected_trid);
|
|
||||||
free(nvme_bdev_ctrlr);
|
free(nvme_bdev_ctrlr);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trid_entry = calloc(1, sizeof(*trid_entry));
|
||||||
|
if (trid_entry == NULL) {
|
||||||
|
SPDK_ERRLOG("Failed to allocate trid entry pointer\n");
|
||||||
|
free(nvme_bdev_ctrlr->namespaces);
|
||||||
|
free(nvme_bdev_ctrlr);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
trid_entry->trid = *trid;
|
||||||
|
|
||||||
for (i = 0; i < nvme_bdev_ctrlr->num_ns; i++) {
|
for (i = 0; i < nvme_bdev_ctrlr->num_ns; i++) {
|
||||||
nvme_bdev_ctrlr->namespaces[i] = calloc(1, sizeof(struct nvme_bdev_ns));
|
nvme_bdev_ctrlr->namespaces[i] = calloc(1, sizeof(struct nvme_bdev_ns));
|
||||||
if (nvme_bdev_ctrlr->namespaces[i] == NULL) {
|
if (nvme_bdev_ctrlr->namespaces[i] == NULL) {
|
||||||
@ -1393,8 +1397,8 @@ create_ctrlr(struct spdk_nvme_ctrlr *ctrlr,
|
|||||||
for (; i > 0; i--) {
|
for (; i > 0; i--) {
|
||||||
free(nvme_bdev_ctrlr->namespaces[i - 1]);
|
free(nvme_bdev_ctrlr->namespaces[i - 1]);
|
||||||
}
|
}
|
||||||
|
free(trid_entry);
|
||||||
free(nvme_bdev_ctrlr->namespaces);
|
free(nvme_bdev_ctrlr->namespaces);
|
||||||
free(nvme_bdev_ctrlr->connected_trid);
|
|
||||||
free(nvme_bdev_ctrlr);
|
free(nvme_bdev_ctrlr);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@ -1404,11 +1408,11 @@ create_ctrlr(struct spdk_nvme_ctrlr *ctrlr,
|
|||||||
nvme_bdev_ctrlr->adminq_timer_poller = NULL;
|
nvme_bdev_ctrlr->adminq_timer_poller = NULL;
|
||||||
nvme_bdev_ctrlr->ctrlr = ctrlr;
|
nvme_bdev_ctrlr->ctrlr = ctrlr;
|
||||||
nvme_bdev_ctrlr->ref = 0;
|
nvme_bdev_ctrlr->ref = 0;
|
||||||
*nvme_bdev_ctrlr->connected_trid = *trid;
|
nvme_bdev_ctrlr->connected_trid = &trid_entry->trid;
|
||||||
nvme_bdev_ctrlr->name = strdup(name);
|
nvme_bdev_ctrlr->name = strdup(name);
|
||||||
if (nvme_bdev_ctrlr->name == NULL) {
|
if (nvme_bdev_ctrlr->name == NULL) {
|
||||||
|
free(trid_entry);
|
||||||
free(nvme_bdev_ctrlr->namespaces);
|
free(nvme_bdev_ctrlr->namespaces);
|
||||||
free(nvme_bdev_ctrlr->connected_trid);
|
|
||||||
free(nvme_bdev_ctrlr);
|
free(nvme_bdev_ctrlr);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@ -1417,9 +1421,9 @@ create_ctrlr(struct spdk_nvme_ctrlr *ctrlr,
|
|||||||
rc = bdev_ocssd_init_ctrlr(nvme_bdev_ctrlr);
|
rc = bdev_ocssd_init_ctrlr(nvme_bdev_ctrlr);
|
||||||
if (spdk_unlikely(rc != 0)) {
|
if (spdk_unlikely(rc != 0)) {
|
||||||
SPDK_ERRLOG("Unable to initialize OCSSD controller\n");
|
SPDK_ERRLOG("Unable to initialize OCSSD controller\n");
|
||||||
|
free(trid_entry);
|
||||||
free(nvme_bdev_ctrlr->name);
|
free(nvme_bdev_ctrlr->name);
|
||||||
free(nvme_bdev_ctrlr->namespaces);
|
free(nvme_bdev_ctrlr->namespaces);
|
||||||
free(nvme_bdev_ctrlr->connected_trid);
|
|
||||||
free(nvme_bdev_ctrlr);
|
free(nvme_bdev_ctrlr);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1450,6 +1454,8 @@ create_ctrlr(struct spdk_nvme_ctrlr *ctrlr,
|
|||||||
SPDK_ERRLOG("Failed to initialize Opal\n");
|
SPDK_ERRLOG("Failed to initialize Opal\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TAILQ_INSERT_HEAD(&nvme_bdev_ctrlr->trids, trid_entry, link);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1722,6 +1728,84 @@ bdev_nvme_async_poll(void *arg)
|
|||||||
return SPDK_POLLER_BUSY;
|
return SPDK_POLLER_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bdev_nvme_add_trid(const char *name, struct spdk_nvme_transport_id *trid)
|
||||||
|
{
|
||||||
|
struct nvme_bdev_ctrlr *nvme_bdev_ctrlr;
|
||||||
|
struct spdk_nvme_ctrlr *new_ctrlr;
|
||||||
|
struct spdk_nvme_ctrlr_opts opts;
|
||||||
|
uint32_t i;
|
||||||
|
struct spdk_nvme_ns *ns, *new_ns;
|
||||||
|
const struct spdk_nvme_ns_data *ns_data, *new_ns_data;
|
||||||
|
struct nvme_bdev_ctrlr_trid *new_trid;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
assert(name != NULL);
|
||||||
|
|
||||||
|
nvme_bdev_ctrlr = nvme_bdev_ctrlr_get_by_name(name);
|
||||||
|
if (nvme_bdev_ctrlr == NULL) {
|
||||||
|
SPDK_ERRLOG("Failed to find NVMe controller\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Currently we only support failover to the same transport type. */
|
||||||
|
if (nvme_bdev_ctrlr->connected_trid->trtype != trid->trtype) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Currently we only support failover to the same NQN. */
|
||||||
|
if (strncmp(trid->subnqn, nvme_bdev_ctrlr->connected_trid->subnqn, SPDK_NVMF_NQN_MAX_LEN)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip all the other checks if we've already registered this path. */
|
||||||
|
TAILQ_FOREACH(new_trid, &nvme_bdev_ctrlr->trids, link) {
|
||||||
|
if (!spdk_nvme_transport_id_compare(&new_trid->trid, trid)) {
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spdk_nvme_ctrlr_get_default_ctrlr_opts(&opts, sizeof(opts));
|
||||||
|
opts.transport_retry_count = g_opts.retry_count;
|
||||||
|
|
||||||
|
new_ctrlr = spdk_nvme_connect(trid, &opts, sizeof(opts));
|
||||||
|
|
||||||
|
if (new_ctrlr == NULL) {
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spdk_nvme_ctrlr_get_num_ns(new_ctrlr) != nvme_bdev_ctrlr->num_ns) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i <= nvme_bdev_ctrlr->num_ns; i++) {
|
||||||
|
ns = spdk_nvme_ctrlr_get_ns(nvme_bdev_ctrlr->ctrlr, i);
|
||||||
|
new_ns = spdk_nvme_ctrlr_get_ns(new_ctrlr, i);
|
||||||
|
assert(ns != NULL);
|
||||||
|
assert(new_ns != NULL);
|
||||||
|
|
||||||
|
ns_data = spdk_nvme_ns_get_data(ns);
|
||||||
|
new_ns_data = spdk_nvme_ns_get_data(new_ns);
|
||||||
|
if (memcmp(ns_data->nguid, new_ns_data->nguid, sizeof(ns_data->nguid))) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_trid = calloc(1, sizeof(*new_trid));
|
||||||
|
if (new_trid == NULL) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
new_trid->trid = *trid;
|
||||||
|
TAILQ_INSERT_TAIL(&nvme_bdev_ctrlr->trids, new_trid, link);
|
||||||
|
|
||||||
|
out:
|
||||||
|
spdk_nvme_detach(new_ctrlr);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bdev_nvme_create(struct spdk_nvme_transport_id *trid,
|
bdev_nvme_create(struct spdk_nvme_transport_id *trid,
|
||||||
struct spdk_nvme_host_id *hostid,
|
struct spdk_nvme_host_id *hostid,
|
||||||
|
@ -66,6 +66,7 @@ struct spdk_nvme_qpair *bdev_nvme_get_io_qpair(struct spdk_io_channel *ctrlr_io_
|
|||||||
void bdev_nvme_get_opts(struct spdk_bdev_nvme_opts *opts);
|
void bdev_nvme_get_opts(struct spdk_bdev_nvme_opts *opts);
|
||||||
int bdev_nvme_set_opts(const struct spdk_bdev_nvme_opts *opts);
|
int bdev_nvme_set_opts(const struct spdk_bdev_nvme_opts *opts);
|
||||||
int bdev_nvme_set_hotplug(bool enabled, uint64_t period_us, spdk_msg_fn cb, void *cb_ctx);
|
int bdev_nvme_set_hotplug(bool enabled, uint64_t period_us, spdk_msg_fn cb, void *cb_ctx);
|
||||||
|
int bdev_nvme_add_trid(const char *name, struct spdk_nvme_transport_id *trid);
|
||||||
|
|
||||||
int bdev_nvme_create(struct spdk_nvme_transport_id *trid,
|
int bdev_nvme_create(struct spdk_nvme_transport_id *trid,
|
||||||
struct spdk_nvme_host_id *hostid,
|
struct spdk_nvme_host_id *hostid,
|
||||||
|
@ -116,6 +116,7 @@ static void
|
|||||||
nvme_bdev_unregister_cb(void *io_device)
|
nvme_bdev_unregister_cb(void *io_device)
|
||||||
{
|
{
|
||||||
struct nvme_bdev_ctrlr *nvme_bdev_ctrlr = io_device;
|
struct nvme_bdev_ctrlr *nvme_bdev_ctrlr = io_device;
|
||||||
|
struct nvme_bdev_ctrlr_trid *trid, *tmp_trid;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
pthread_mutex_lock(&g_bdev_nvme_mutex);
|
pthread_mutex_lock(&g_bdev_nvme_mutex);
|
||||||
@ -127,8 +128,13 @@ nvme_bdev_unregister_cb(void *io_device)
|
|||||||
for (i = 0; i < nvme_bdev_ctrlr->num_ns; i++) {
|
for (i = 0; i < nvme_bdev_ctrlr->num_ns; i++) {
|
||||||
free(nvme_bdev_ctrlr->namespaces[i]);
|
free(nvme_bdev_ctrlr->namespaces[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(trid, &nvme_bdev_ctrlr->trids, link, tmp_trid) {
|
||||||
|
TAILQ_REMOVE(&nvme_bdev_ctrlr->trids, trid, link);
|
||||||
|
free(trid);
|
||||||
|
}
|
||||||
|
|
||||||
free(nvme_bdev_ctrlr->namespaces);
|
free(nvme_bdev_ctrlr->namespaces);
|
||||||
free(nvme_bdev_ctrlr->connected_trid);
|
|
||||||
free(nvme_bdev_ctrlr);
|
free(nvme_bdev_ctrlr);
|
||||||
|
|
||||||
pthread_mutex_lock(&g_bdev_nvme_mutex);
|
pthread_mutex_lock(&g_bdev_nvme_mutex);
|
||||||
|
@ -69,38 +69,45 @@ struct nvme_bdev_ns {
|
|||||||
|
|
||||||
struct ocssd_bdev_ctrlr;
|
struct ocssd_bdev_ctrlr;
|
||||||
|
|
||||||
|
struct nvme_bdev_ctrlr_trid {
|
||||||
|
struct spdk_nvme_transport_id trid;
|
||||||
|
TAILQ_ENTRY(nvme_bdev_ctrlr_trid) link;
|
||||||
|
};
|
||||||
|
|
||||||
struct nvme_bdev_ctrlr {
|
struct nvme_bdev_ctrlr {
|
||||||
/**
|
/**
|
||||||
* points to pinned, physically contiguous memory region;
|
* points to pinned, physically contiguous memory region;
|
||||||
* contains 4KB IDENTIFY structure for controller which is
|
* contains 4KB IDENTIFY structure for controller which is
|
||||||
* target for CONTROLLER IDENTIFY command during initialization
|
* target for CONTROLLER IDENTIFY command during initialization
|
||||||
*/
|
*/
|
||||||
struct spdk_nvme_ctrlr *ctrlr;
|
struct spdk_nvme_ctrlr *ctrlr;
|
||||||
struct spdk_nvme_transport_id *connected_trid;
|
struct spdk_nvme_transport_id *connected_trid;
|
||||||
char *name;
|
char *name;
|
||||||
int ref;
|
int ref;
|
||||||
bool resetting;
|
bool resetting;
|
||||||
bool destruct;
|
bool destruct;
|
||||||
/**
|
/**
|
||||||
* PI check flags. This flags is set to NVMe controllers created only
|
* PI check flags. This flags is set to NVMe controllers created only
|
||||||
* through bdev_nvme_attach_controller RPC or .INI config file. Hot added
|
* through bdev_nvme_attach_controller RPC or .INI config file. Hot added
|
||||||
* NVMe controllers are not included.
|
* NVMe controllers are not included.
|
||||||
*/
|
*/
|
||||||
uint32_t prchk_flags;
|
uint32_t prchk_flags;
|
||||||
uint32_t num_ns;
|
uint32_t num_ns;
|
||||||
/** Array of pointers to namespaces indexed by nsid - 1 */
|
/** Array of pointers to namespaces indexed by nsid - 1 */
|
||||||
struct nvme_bdev_ns **namespaces;
|
struct nvme_bdev_ns **namespaces;
|
||||||
|
|
||||||
struct spdk_opal_dev *opal_dev;
|
struct spdk_opal_dev *opal_dev;
|
||||||
|
|
||||||
struct spdk_poller *adminq_timer_poller;
|
struct spdk_poller *adminq_timer_poller;
|
||||||
struct spdk_poller *destruct_poller;
|
struct spdk_poller *destruct_poller;
|
||||||
struct spdk_thread *thread;
|
struct spdk_thread *thread;
|
||||||
|
|
||||||
struct ocssd_bdev_ctrlr *ocssd_ctrlr;
|
struct ocssd_bdev_ctrlr *ocssd_ctrlr;
|
||||||
|
|
||||||
/** linked list pointer for device list */
|
/** linked list pointer for device list */
|
||||||
TAILQ_ENTRY(nvme_bdev_ctrlr) tailq;
|
TAILQ_ENTRY(nvme_bdev_ctrlr) tailq;
|
||||||
|
|
||||||
|
TAILQ_HEAD(, nvme_bdev_ctrlr_trid) trids;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nvme_bdev {
|
struct nvme_bdev {
|
||||||
|
@ -198,6 +198,7 @@ create_nvme_bdev_controller(const struct spdk_nvme_transport_id *trid, const cha
|
|||||||
{
|
{
|
||||||
struct spdk_nvme_ctrlr *ctrlr;
|
struct spdk_nvme_ctrlr *ctrlr;
|
||||||
struct nvme_bdev_ctrlr *nvme_bdev_ctrlr;
|
struct nvme_bdev_ctrlr *nvme_bdev_ctrlr;
|
||||||
|
struct nvme_bdev_ctrlr_trid *trid_entry;
|
||||||
uint32_t nsid;
|
uint32_t nsid;
|
||||||
|
|
||||||
ctrlr = find_controller(trid);
|
ctrlr = find_controller(trid);
|
||||||
@ -211,15 +212,15 @@ create_nvme_bdev_controller(const struct spdk_nvme_transport_id *trid, const cha
|
|||||||
nvme_bdev_ctrlr->namespaces = calloc(ctrlr->ns_count, sizeof(struct nvme_bdev_ns *));
|
nvme_bdev_ctrlr->namespaces = calloc(ctrlr->ns_count, sizeof(struct nvme_bdev_ns *));
|
||||||
SPDK_CU_ASSERT_FATAL(nvme_bdev_ctrlr->namespaces != NULL);
|
SPDK_CU_ASSERT_FATAL(nvme_bdev_ctrlr->namespaces != NULL);
|
||||||
|
|
||||||
nvme_bdev_ctrlr->connected_trid = calloc(1, sizeof(struct spdk_nvme_transport_id));
|
trid_entry = calloc(1, sizeof(struct nvme_bdev_ctrlr_trid));
|
||||||
SPDK_CU_ASSERT_FATAL(nvme_bdev_ctrlr->connected_trid != NULL);
|
SPDK_CU_ASSERT_FATAL(trid_entry != NULL);
|
||||||
|
trid_entry->trid = *trid;
|
||||||
|
|
||||||
nvme_bdev_ctrlr->ctrlr = ctrlr;
|
nvme_bdev_ctrlr->ctrlr = ctrlr;
|
||||||
nvme_bdev_ctrlr->num_ns = ctrlr->ns_count;
|
nvme_bdev_ctrlr->num_ns = ctrlr->ns_count;
|
||||||
nvme_bdev_ctrlr->ref = 0;
|
nvme_bdev_ctrlr->ref = 0;
|
||||||
*nvme_bdev_ctrlr->connected_trid = *trid;
|
nvme_bdev_ctrlr->connected_trid = &trid_entry->trid;
|
||||||
nvme_bdev_ctrlr->name = strdup(name);
|
nvme_bdev_ctrlr->name = strdup(name);
|
||||||
|
|
||||||
for (nsid = 0; nsid < ctrlr->ns_count; ++nsid) {
|
for (nsid = 0; nsid < ctrlr->ns_count; ++nsid) {
|
||||||
nvme_bdev_ctrlr->namespaces[nsid] = calloc(1, sizeof(struct nvme_bdev_ns));
|
nvme_bdev_ctrlr->namespaces[nsid] = calloc(1, sizeof(struct nvme_bdev_ns));
|
||||||
SPDK_CU_ASSERT_FATAL(nvme_bdev_ctrlr->namespaces[nsid] != NULL);
|
SPDK_CU_ASSERT_FATAL(nvme_bdev_ctrlr->namespaces[nsid] != NULL);
|
||||||
@ -239,6 +240,9 @@ create_nvme_bdev_controller(const struct spdk_nvme_transport_id *trid, const cha
|
|||||||
|
|
||||||
TAILQ_INSERT_TAIL(&g_nvme_bdev_ctrlrs, nvme_bdev_ctrlr, tailq);
|
TAILQ_INSERT_TAIL(&g_nvme_bdev_ctrlrs, nvme_bdev_ctrlr, tailq);
|
||||||
|
|
||||||
|
TAILQ_INIT(&nvme_bdev_ctrlr->trids);
|
||||||
|
TAILQ_INSERT_HEAD(&nvme_bdev_ctrlr->trids, trid_entry, link);
|
||||||
|
|
||||||
return nvme_bdev_ctrlr;
|
return nvme_bdev_ctrlr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user