nvmf: Transports are no longer global

Create one transport per nvmf target. Today, there is just
one global nvmf target, but this paves the way for multiple.

Change-Id: Iaa1f8c5e7b3c1e87621ef2a636c68c2dd8fd929e
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/371748
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
Ben Walker 2017-07-24 16:30:07 -07:00 committed by Daniel Verkamp
parent 269910c05c
commit 31d033f944
14 changed files with 212 additions and 136 deletions

View File

@ -263,7 +263,7 @@ nvmf_tgt_shutdown_subsystem_by_nqn(const char *nqn)
static void static void
acceptor_poll(void *arg) acceptor_poll(void *arg)
{ {
spdk_nvmf_acceptor_poll(); spdk_nvmf_tgt_poll();
} }
static void static void

View File

@ -167,7 +167,7 @@ int spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char
const char *spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem); const char *spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem);
enum spdk_nvmf_subtype spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem); enum spdk_nvmf_subtype spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem);
void spdk_nvmf_acceptor_poll(void); void spdk_nvmf_tgt_poll(void);
void spdk_nvmf_handle_connect(struct spdk_nvmf_request *req); void spdk_nvmf_handle_connect(struct spdk_nvmf_request *req);

View File

@ -163,7 +163,7 @@ nvmf_init_nvme_ctrlr_properties(struct spdk_nvmf_ctrlr *ctrlr)
static void ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr) static void ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
{ {
TAILQ_REMOVE(&ctrlr->subsys->ctrlrs, ctrlr, link); TAILQ_REMOVE(&ctrlr->subsys->ctrlrs, ctrlr, link);
ctrlr->transport->ctrlr_fini(ctrlr); ctrlr->transport->ops->ctrlr_fini(ctrlr);
} }
void void
@ -174,7 +174,7 @@ spdk_nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
TAILQ_REMOVE(&ctrlr->qpairs, qpair, link); TAILQ_REMOVE(&ctrlr->qpairs, qpair, link);
ctrlr->num_qpairs--; ctrlr->num_qpairs--;
qpair->transport->qpair_fini(qpair); qpair->transport->ops->qpair_fini(qpair);
} }
ctrlr_destruct(ctrlr); ctrlr_destruct(ctrlr);
@ -288,7 +288,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_qpair *qpair,
} }
/* Establish a new ctrlr */ /* Establish a new ctrlr */
ctrlr = qpair->transport->ctrlr_init(); ctrlr = qpair->transport->ops->ctrlr_init(qpair->transport);
if (ctrlr == NULL) { if (ctrlr == NULL) {
SPDK_ERRLOG("Memory allocation failure\n"); SPDK_ERRLOG("Memory allocation failure\n");
rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
@ -313,9 +313,9 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_qpair *qpair,
memcpy(ctrlr->hostid, data->hostid, sizeof(ctrlr->hostid)); memcpy(ctrlr->hostid, data->hostid, sizeof(ctrlr->hostid));
if (qpair->transport->ctrlr_add_qpair(ctrlr, qpair)) { if (qpair->transport->ops->ctrlr_add_qpair(ctrlr, qpair)) {
rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
qpair->transport->ctrlr_fini(ctrlr); qpair->transport->ops->ctrlr_fini(ctrlr);
free(ctrlr); free(ctrlr);
return; return;
} }
@ -374,7 +374,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_qpair *qpair,
return; return;
} }
if (qpair->transport->ctrlr_add_qpair(ctrlr, qpair)) { if (qpair->transport->ops->ctrlr_add_qpair(ctrlr, qpair)) {
INVALID_CONNECT_CMD(qid); INVALID_CONNECT_CMD(qid);
return; return;
} }
@ -399,8 +399,8 @@ spdk_nvmf_ctrlr_disconnect(struct spdk_nvmf_qpair *qpair)
ctrlr->num_qpairs--; ctrlr->num_qpairs--;
TAILQ_REMOVE(&ctrlr->qpairs, qpair, link); TAILQ_REMOVE(&ctrlr->qpairs, qpair, link);
qpair->transport->ctrlr_remove_qpair(ctrlr, qpair); qpair->transport->ops->ctrlr_remove_qpair(ctrlr, qpair);
qpair->transport->qpair_fini(qpair); qpair->transport->ops->qpair_fini(qpair);
if (ctrlr->num_qpairs == 0) { if (ctrlr->num_qpairs == 0) {
ctrlr_destruct(ctrlr); ctrlr_destruct(ctrlr);
@ -654,7 +654,7 @@ spdk_nvmf_ctrlr_poll(struct spdk_nvmf_ctrlr *ctrlr)
} }
TAILQ_FOREACH_SAFE(qpair, &ctrlr->qpairs, link, tmp) { TAILQ_FOREACH_SAFE(qpair, &ctrlr->qpairs, link, tmp) {
if (qpair->transport->qpair_poll(qpair) < 0) { if (qpair->transport->ops->qpair_poll(qpair) < 0) {
SPDK_ERRLOG("Transport poll failed for qpair %p; closing connection\n", qpair); SPDK_ERRLOG("Transport poll failed for qpair %p; closing connection\n", qpair);
spdk_nvmf_ctrlr_disconnect(qpair); spdk_nvmf_ctrlr_disconnect(qpair);
} }

View File

@ -51,7 +51,7 @@ enum spdk_nvmf_qpair_type {
}; };
struct spdk_nvmf_qpair { struct spdk_nvmf_qpair {
const struct spdk_nvmf_transport *transport; struct spdk_nvmf_transport *transport;
struct spdk_nvmf_ctrlr *ctrlr; struct spdk_nvmf_ctrlr *ctrlr;
enum spdk_nvmf_qpair_type type; enum spdk_nvmf_qpair_type type;
@ -92,7 +92,7 @@ struct spdk_nvmf_ctrlr {
} async_event_config; } async_event_config;
struct spdk_nvmf_request *aer_req; struct spdk_nvmf_request *aer_req;
uint8_t hostid[16]; uint8_t hostid[16];
const struct spdk_nvmf_transport *transport; struct spdk_nvmf_transport *transport;
TAILQ_ENTRY(spdk_nvmf_ctrlr) link; TAILQ_ENTRY(spdk_nvmf_ctrlr) link;
}; };

View File

@ -58,7 +58,7 @@ nvmf_update_discovery_log(void)
struct spdk_nvmf_subsystem_allowed_listener *allowed_listener; struct spdk_nvmf_subsystem_allowed_listener *allowed_listener;
struct spdk_nvmf_listen_addr *listen_addr; struct spdk_nvmf_listen_addr *listen_addr;
struct spdk_nvmf_discovery_log_page_entry *entry; struct spdk_nvmf_discovery_log_page_entry *entry;
const struct spdk_nvmf_transport *transport; struct spdk_nvmf_transport *transport;
struct spdk_nvmf_discovery_log_page *disc_log; struct spdk_nvmf_discovery_log_page *disc_log;
size_t cur_size; size_t cur_size;
@ -99,10 +99,10 @@ nvmf_update_discovery_log(void)
entry->subtype = subsystem->subtype; entry->subtype = subsystem->subtype;
snprintf(entry->subnqn, sizeof(entry->subnqn), "%s", subsystem->subnqn); snprintf(entry->subnqn, sizeof(entry->subnqn), "%s", subsystem->subnqn);
transport = spdk_nvmf_transport_get(listen_addr->trid.trtype); transport = spdk_nvmf_tgt_get_transport(&g_nvmf_tgt, listen_addr->trid.trtype);
assert(transport != NULL); assert(transport != NULL);
transport->listen_addr_discover(listen_addr, entry); transport->ops->listen_addr_discover(transport, listen_addr, entry);
numrec++; numrec++;
} }

View File

@ -52,8 +52,6 @@ int
spdk_nvmf_tgt_init(uint16_t max_queue_depth, uint16_t max_qpairs_per_ctrlr, spdk_nvmf_tgt_init(uint16_t max_queue_depth, uint16_t max_qpairs_per_ctrlr,
uint32_t in_capsule_data_size, uint32_t max_io_size) uint32_t in_capsule_data_size, uint32_t max_io_size)
{ {
int rc;
g_nvmf_tgt.max_qpairs_per_ctrlr = max_qpairs_per_ctrlr; g_nvmf_tgt.max_qpairs_per_ctrlr = max_qpairs_per_ctrlr;
g_nvmf_tgt.max_queue_depth = max_queue_depth; g_nvmf_tgt.max_queue_depth = max_queue_depth;
g_nvmf_tgt.in_capsule_data_size = in_capsule_data_size; g_nvmf_tgt.in_capsule_data_size = in_capsule_data_size;
@ -64,18 +62,13 @@ spdk_nvmf_tgt_init(uint16_t max_queue_depth, uint16_t max_qpairs_per_ctrlr,
g_nvmf_tgt.current_subsystem_id = 0; g_nvmf_tgt.current_subsystem_id = 0;
TAILQ_INIT(&g_nvmf_tgt.subsystems); TAILQ_INIT(&g_nvmf_tgt.subsystems);
TAILQ_INIT(&g_nvmf_tgt.listen_addrs); TAILQ_INIT(&g_nvmf_tgt.listen_addrs);
TAILQ_INIT(&g_nvmf_tgt.transports);
SPDK_TRACELOG(SPDK_TRACE_NVMF, "Max Queue Pairs Per Controller: %d\n", max_qpairs_per_ctrlr); SPDK_TRACELOG(SPDK_TRACE_NVMF, "Max Queue Pairs Per Controller: %d\n", max_qpairs_per_ctrlr);
SPDK_TRACELOG(SPDK_TRACE_NVMF, "Max Queue Depth: %d\n", max_queue_depth); SPDK_TRACELOG(SPDK_TRACE_NVMF, "Max Queue Depth: %d\n", max_queue_depth);
SPDK_TRACELOG(SPDK_TRACE_NVMF, "Max In Capsule Data: %d bytes\n", in_capsule_data_size); SPDK_TRACELOG(SPDK_TRACE_NVMF, "Max In Capsule Data: %d bytes\n", in_capsule_data_size);
SPDK_TRACELOG(SPDK_TRACE_NVMF, "Max I/O Size: %d bytes\n", max_io_size); SPDK_TRACELOG(SPDK_TRACE_NVMF, "Max I/O Size: %d bytes\n", max_io_size);
rc = spdk_nvmf_transport_init();
if (rc < 0) {
SPDK_ERRLOG("Transport initialization failed\n");
return -1;
}
return 0; return 0;
} }
@ -83,6 +76,7 @@ int
spdk_nvmf_tgt_fini(void) spdk_nvmf_tgt_fini(void)
{ {
struct spdk_nvmf_listen_addr *listen_addr, *listen_addr_tmp; struct spdk_nvmf_listen_addr *listen_addr, *listen_addr_tmp;
struct spdk_nvmf_transport *transport, *transport_tmp;
TAILQ_FOREACH_SAFE(listen_addr, &g_nvmf_tgt.listen_addrs, link, listen_addr_tmp) { TAILQ_FOREACH_SAFE(listen_addr, &g_nvmf_tgt.listen_addrs, link, listen_addr_tmp) {
TAILQ_REMOVE(&g_nvmf_tgt.listen_addrs, listen_addr, link); TAILQ_REMOVE(&g_nvmf_tgt.listen_addrs, listen_addr, link);
@ -91,21 +85,32 @@ spdk_nvmf_tgt_fini(void)
spdk_nvmf_listen_addr_destroy(listen_addr); spdk_nvmf_listen_addr_destroy(listen_addr);
} }
spdk_nvmf_transport_fini(); TAILQ_FOREACH_SAFE(transport, &g_nvmf_tgt.transports, link, transport_tmp) {
TAILQ_REMOVE(&g_nvmf_tgt.transports, transport, link);
spdk_nvmf_transport_destroy(transport);
}
return 0; return 0;
} }
struct spdk_nvmf_transport *
spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, enum spdk_nvme_transport_type type)
{
struct spdk_nvmf_transport *transport;
TAILQ_FOREACH(transport, &tgt->transports, link) {
if (transport->ops->type == type) {
return transport;
}
}
return NULL;
}
struct spdk_nvmf_listen_addr * struct spdk_nvmf_listen_addr *
spdk_nvmf_listen_addr_create(struct spdk_nvme_transport_id *trid) spdk_nvmf_listen_addr_create(struct spdk_nvme_transport_id *trid)
{ {
struct spdk_nvmf_listen_addr *listen_addr; struct spdk_nvmf_listen_addr *listen_addr;
const struct spdk_nvmf_transport *transport;
transport = spdk_nvmf_transport_get(trid->trtype);
if (!transport) {
return NULL;
}
listen_addr = calloc(1, sizeof(*listen_addr)); listen_addr = calloc(1, sizeof(*listen_addr));
if (!listen_addr) { if (!listen_addr) {
@ -120,15 +125,28 @@ spdk_nvmf_listen_addr_create(struct spdk_nvme_transport_id *trid)
void void
spdk_nvmf_listen_addr_destroy(struct spdk_nvmf_listen_addr *addr) spdk_nvmf_listen_addr_destroy(struct spdk_nvmf_listen_addr *addr)
{ {
const struct spdk_nvmf_transport *transport; struct spdk_nvmf_transport *transport;
transport = spdk_nvmf_transport_get(addr->trid.trtype); transport = spdk_nvmf_tgt_get_transport(&g_nvmf_tgt, addr->trid.trtype);
assert(transport != NULL); if (!transport) {
transport->listen_addr_remove(addr); SPDK_ERRLOG("Attempted to destroy listener without a valid transport\n");
return;
}
transport->ops->listen_addr_remove(transport, addr);
free(addr); free(addr);
} }
void
spdk_nvmf_tgt_poll(void)
{
struct spdk_nvmf_transport *transport, *tmp;
TAILQ_FOREACH_SAFE(transport, &g_nvmf_tgt.transports, link, tmp) {
transport->ops->acceptor_poll(transport);
}
}
SPDK_TRACE_REGISTER_FN(nvmf_trace) SPDK_TRACE_REGISTER_FN(nvmf_trace)
{ {
spdk_trace_register_object(OBJECT_NVMF_IO, 'r'); spdk_trace_register_object(OBJECT_NVMF_IO, 'r');

View File

@ -87,6 +87,7 @@ struct spdk_nvmf_tgt {
size_t discovery_log_page_size; size_t discovery_log_page_size;
TAILQ_HEAD(, spdk_nvmf_listen_addr) listen_addrs; TAILQ_HEAD(, spdk_nvmf_listen_addr) listen_addrs;
uint32_t current_subsystem_id; uint32_t current_subsystem_id;
TAILQ_HEAD(, spdk_nvmf_transport) transports;
}; };
extern struct spdk_nvmf_tgt g_nvmf_tgt; extern struct spdk_nvmf_tgt g_nvmf_tgt;
@ -94,6 +95,9 @@ extern struct spdk_nvmf_tgt g_nvmf_tgt;
struct spdk_nvmf_listen_addr *spdk_nvmf_listen_addr_create(struct spdk_nvme_transport_id *trid); struct spdk_nvmf_listen_addr *spdk_nvmf_listen_addr_create(struct spdk_nvme_transport_id *trid);
void spdk_nvmf_listen_addr_destroy(struct spdk_nvmf_listen_addr *addr); void spdk_nvmf_listen_addr_destroy(struct spdk_nvmf_listen_addr *addr);
struct spdk_nvmf_transport *spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt,
enum spdk_nvme_transport_type);
#define OBJECT_NVMF_IO 0x30 #define OBJECT_NVMF_IO 0x30
#define TRACE_GROUP_NVMF 0x3 #define TRACE_GROUP_NVMF 0x3

View File

@ -258,7 +258,8 @@ spdk_nvmf_rdma_qpair_destroy(struct spdk_nvmf_rdma_qpair *rdma_qpair)
} }
static struct spdk_nvmf_rdma_qpair * static struct spdk_nvmf_rdma_qpair *
spdk_nvmf_rdma_qpair_create(struct rdma_cm_id *id, struct ibv_comp_channel *channel, spdk_nvmf_rdma_qpair_create(struct spdk_nvmf_transport *transport,
struct rdma_cm_id *id, struct ibv_comp_channel *channel,
uint16_t max_queue_depth, uint16_t max_rw_depth, uint32_t subsystem_id) uint16_t max_queue_depth, uint16_t max_rw_depth, uint32_t subsystem_id)
{ {
struct spdk_nvmf_rdma_qpair *rdma_qpair; struct spdk_nvmf_rdma_qpair *rdma_qpair;
@ -310,7 +311,7 @@ spdk_nvmf_rdma_qpair_create(struct rdma_cm_id *id, struct ibv_comp_channel *chan
} }
qpair = &rdma_qpair->qpair; qpair = &rdma_qpair->qpair;
qpair->transport = &spdk_nvmf_transport_rdma; qpair->transport = transport;
id->context = qpair; id->context = qpair;
rdma_qpair->cm_id = id; rdma_qpair->cm_id = id;
@ -534,7 +535,7 @@ spdk_nvmf_rdma_request_transfer_data(struct spdk_nvmf_request *req)
} }
static int static int
nvmf_rdma_connect(struct rdma_cm_event *event) nvmf_rdma_connect(struct spdk_nvmf_transport *transport, struct rdma_cm_event *event)
{ {
struct spdk_nvmf_rdma_qpair *rdma_qpair = NULL; struct spdk_nvmf_rdma_qpair *rdma_qpair = NULL;
struct spdk_nvmf_rdma_listen_addr *addr; struct spdk_nvmf_rdma_listen_addr *addr;
@ -613,7 +614,7 @@ nvmf_rdma_connect(struct rdma_cm_event *event)
max_queue_depth, max_rw_depth); max_queue_depth, max_rw_depth);
/* Init the NVMf rdma transport connection */ /* Init the NVMf rdma transport connection */
rdma_qpair = spdk_nvmf_rdma_qpair_create(event->id, addr->comp_channel, max_queue_depth, rdma_qpair = spdk_nvmf_rdma_qpair_create(transport, event->id, addr->comp_channel, max_queue_depth,
max_rw_depth, subsystem_id); max_rw_depth, subsystem_id);
if (rdma_qpair == NULL) { if (rdma_qpair == NULL) {
SPDK_ERRLOG("Error on nvmf connection creation\n"); SPDK_ERRLOG("Error on nvmf connection creation\n");
@ -912,35 +913,45 @@ spdk_nvmf_rdma_handle_pending_rdma_rw(struct spdk_nvmf_qpair *qpair)
/* Public API callbacks begin here */ /* Public API callbacks begin here */
static int static struct spdk_nvmf_transport *
spdk_nvmf_rdma_init(uint16_t max_queue_depth, uint32_t max_io_size, spdk_nvmf_rdma_create(struct spdk_nvmf_tgt *tgt)
uint32_t in_capsule_data_size)
{ {
int rc; int rc;
struct spdk_nvmf_transport *transport;
transport = calloc(1, sizeof(*transport));
if (!transport) {
return NULL;
}
transport->tgt = tgt;
transport->ops = &spdk_nvmf_transport_rdma;
SPDK_NOTICELOG("*** RDMA Transport Init ***\n"); SPDK_NOTICELOG("*** RDMA Transport Init ***\n");
pthread_mutex_lock(&g_rdma.lock); pthread_mutex_lock(&g_rdma.lock);
g_rdma.max_queue_depth = max_queue_depth; g_rdma.max_queue_depth = tgt->max_queue_depth;
g_rdma.max_io_size = max_io_size; g_rdma.max_io_size = tgt->max_io_size;
g_rdma.in_capsule_data_size = in_capsule_data_size; g_rdma.in_capsule_data_size = tgt->in_capsule_data_size;
g_rdma.event_channel = rdma_create_event_channel(); g_rdma.event_channel = rdma_create_event_channel();
if (g_rdma.event_channel == NULL) { if (g_rdma.event_channel == NULL) {
SPDK_ERRLOG("rdma_create_event_channel() failed, %s\n", strerror(errno)); SPDK_ERRLOG("rdma_create_event_channel() failed, %s\n", strerror(errno));
free(transport);
pthread_mutex_unlock(&g_rdma.lock); pthread_mutex_unlock(&g_rdma.lock);
return -1; return NULL;
} }
rc = fcntl(g_rdma.event_channel->fd, F_SETFL, O_NONBLOCK); rc = fcntl(g_rdma.event_channel->fd, F_SETFL, O_NONBLOCK);
if (rc < 0) { if (rc < 0) {
SPDK_ERRLOG("fcntl to set fd to non-blocking failed\n"); SPDK_ERRLOG("fcntl to set fd to non-blocking failed\n");
free(transport);
pthread_mutex_unlock(&g_rdma.lock); pthread_mutex_unlock(&g_rdma.lock);
return -1; return NULL;
} }
pthread_mutex_unlock(&g_rdma.lock); pthread_mutex_unlock(&g_rdma.lock);
return 0; return transport;
} }
static void static void
@ -953,7 +964,7 @@ spdk_nvmf_rdma_listen_addr_free(struct spdk_nvmf_rdma_listen_addr *addr)
free(addr); free(addr);
} }
static int static int
spdk_nvmf_rdma_fini(void) spdk_nvmf_rdma_destroy(struct spdk_nvmf_transport *transport)
{ {
pthread_mutex_lock(&g_rdma.lock); pthread_mutex_lock(&g_rdma.lock);
@ -963,11 +974,14 @@ spdk_nvmf_rdma_fini(void)
} }
pthread_mutex_unlock(&g_rdma.lock); pthread_mutex_unlock(&g_rdma.lock);
free(transport);
return 0; return 0;
} }
static int static int
spdk_nvmf_rdma_listen_remove(struct spdk_nvmf_listen_addr *listen_addr) spdk_nvmf_rdma_listen_remove(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_listen_addr *listen_addr)
{ {
struct spdk_nvmf_rdma_listen_addr *addr, *tmp; struct spdk_nvmf_rdma_listen_addr *addr, *tmp;
@ -1017,7 +1031,7 @@ spdk_nvmf_rdma_addr_listen_init(struct spdk_nvmf_rdma_listen_addr *addr)
} }
static void static void
spdk_nvmf_rdma_acceptor_poll(void) spdk_nvmf_rdma_acceptor_poll(struct spdk_nvmf_transport *transport)
{ {
struct rdma_cm_event *event; struct rdma_cm_event *event;
int rc; int rc;
@ -1057,7 +1071,7 @@ spdk_nvmf_rdma_acceptor_poll(void)
switch (event->event) { switch (event->event) {
case RDMA_CM_EVENT_CONNECT_REQUEST: case RDMA_CM_EVENT_CONNECT_REQUEST:
rc = nvmf_rdma_connect(event); rc = nvmf_rdma_connect(transport, event);
if (rc < 0) { if (rc < 0) {
SPDK_ERRLOG("Unable to process connect event. rc: %d\n", rc); SPDK_ERRLOG("Unable to process connect event. rc: %d\n", rc);
break; break;
@ -1091,7 +1105,8 @@ spdk_nvmf_rdma_acceptor_poll(void)
} }
static int static int
spdk_nvmf_rdma_listen(struct spdk_nvmf_listen_addr *listen_addr) spdk_nvmf_rdma_listen(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_listen_addr *listen_addr)
{ {
struct spdk_nvmf_rdma_listen_addr *addr; struct spdk_nvmf_rdma_listen_addr *addr;
struct sockaddr_in saddr; struct sockaddr_in saddr;
@ -1177,7 +1192,8 @@ spdk_nvmf_rdma_listen(struct spdk_nvmf_listen_addr *listen_addr)
} }
static void static void
spdk_nvmf_rdma_discover(struct spdk_nvmf_listen_addr *listen_addr, spdk_nvmf_rdma_discover(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_listen_addr *listen_addr,
struct spdk_nvmf_discovery_log_page_entry *entry) struct spdk_nvmf_discovery_log_page_entry *entry)
{ {
entry->trtype = SPDK_NVMF_TRTYPE_RDMA; entry->trtype = SPDK_NVMF_TRTYPE_RDMA;
@ -1193,7 +1209,7 @@ spdk_nvmf_rdma_discover(struct spdk_nvmf_listen_addr *listen_addr,
} }
static struct spdk_nvmf_ctrlr * static struct spdk_nvmf_ctrlr *
spdk_nvmf_rdma_ctrlr_init(void) spdk_nvmf_rdma_ctrlr_init(struct spdk_nvmf_transport *transport)
{ {
struct spdk_nvmf_rdma_ctrlr *rdma_ctrlr; struct spdk_nvmf_rdma_ctrlr *rdma_ctrlr;
int i; int i;
@ -1222,7 +1238,7 @@ spdk_nvmf_rdma_ctrlr_init(void)
SLIST_INSERT_HEAD(&rdma_ctrlr->data_buf_pool, buf, link); SLIST_INSERT_HEAD(&rdma_ctrlr->data_buf_pool, buf, link);
} }
rdma_ctrlr->ctrlr.transport = &spdk_nvmf_transport_rdma; rdma_ctrlr->ctrlr.transport = transport;
return &rdma_ctrlr->ctrlr; return &rdma_ctrlr->ctrlr;
} }
@ -1575,10 +1591,10 @@ spdk_nvmf_rdma_qpair_is_idle(struct spdk_nvmf_qpair *qpair)
return false; return false;
} }
const struct spdk_nvmf_transport spdk_nvmf_transport_rdma = { const struct spdk_nvmf_transport_ops spdk_nvmf_transport_rdma = {
.type = SPDK_NVME_TRANSPORT_RDMA, .type = SPDK_NVME_TRANSPORT_RDMA,
.transport_init = spdk_nvmf_rdma_init, .create = spdk_nvmf_rdma_create,
.transport_fini = spdk_nvmf_rdma_fini, .destroy = spdk_nvmf_rdma_destroy,
.acceptor_poll = spdk_nvmf_rdma_acceptor_poll, .acceptor_poll = spdk_nvmf_rdma_acceptor_poll,

View File

@ -59,7 +59,7 @@ spdk_nvmf_request_complete(struct spdk_nvmf_request *req)
response->cid, response->cdw0, response->rsvd1, response->cid, response->cdw0, response->rsvd1,
*(uint16_t *)&response->status); *(uint16_t *)&response->status);
if (req->qpair->transport->req_complete(req)) { if (req->qpair->transport->ops->req_complete(req)) {
SPDK_ERRLOG("Transport request completion error!\n"); SPDK_ERRLOG("Transport request completion error!\n");
return -1; return -1;
} }

View File

@ -118,7 +118,7 @@ nvmf_subsystem_removable(struct spdk_nvmf_subsystem *subsystem)
if (subsystem->is_removed) { if (subsystem->is_removed) {
TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) { TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
TAILQ_FOREACH(qpair, &ctrlr->qpairs, link) { TAILQ_FOREACH(qpair, &ctrlr->qpairs, link) {
if (!qpair->transport->qpair_is_idle(qpair)) { if (!qpair->transport->ops->qpair_is_idle(qpair)) {
return false; return false;
} }
} }
@ -262,7 +262,7 @@ struct spdk_nvmf_listen_addr *
spdk_nvmf_tgt_listen(struct spdk_nvme_transport_id *trid) spdk_nvmf_tgt_listen(struct spdk_nvme_transport_id *trid)
{ {
struct spdk_nvmf_listen_addr *listen_addr; struct spdk_nvmf_listen_addr *listen_addr;
const struct spdk_nvmf_transport *transport; struct spdk_nvmf_transport *transport;
int rc; int rc;
TAILQ_FOREACH(listen_addr, &g_nvmf_tgt.listen_addrs, link) { TAILQ_FOREACH(listen_addr, &g_nvmf_tgt.listen_addrs, link) {
@ -271,18 +271,23 @@ spdk_nvmf_tgt_listen(struct spdk_nvme_transport_id *trid)
} }
} }
transport = spdk_nvmf_transport_get(trid->trtype); transport = spdk_nvmf_tgt_get_transport(&g_nvmf_tgt, trid->trtype);
if (!transport) { if (!transport) {
SPDK_ERRLOG("Unknown transport '%u'\n", trid->trtype); transport = spdk_nvmf_transport_create(&g_nvmf_tgt, trid->trtype);
return NULL; if (!transport) {
SPDK_ERRLOG("Transport initialization failed\n");
return NULL;
}
TAILQ_INSERT_TAIL(&g_nvmf_tgt.transports, transport, link);
} }
listen_addr = spdk_nvmf_listen_addr_create(trid); listen_addr = spdk_nvmf_listen_addr_create(trid);
if (!listen_addr) { if (!listen_addr) {
return NULL; return NULL;
} }
rc = transport->listen_addr_add(listen_addr); rc = transport->ops->listen_addr_add(transport, listen_addr);
if (rc < 0) { if (rc < 0) {
free(listen_addr); free(listen_addr);
SPDK_ERRLOG("Unable to listen on address '%s'\n", trid->traddr); SPDK_ERRLOG("Unable to listen on address '%s'\n", trid->traddr);

View File

@ -42,71 +42,56 @@
#include "nvmf_internal.h" #include "nvmf_internal.h"
static const struct spdk_nvmf_transport *const g_transports[] = { static const struct spdk_nvmf_transport_ops *const g_transport_ops[] = {
#ifdef SPDK_CONFIG_RDMA #ifdef SPDK_CONFIG_RDMA
&spdk_nvmf_transport_rdma, &spdk_nvmf_transport_rdma,
#endif #endif
}; };
#define NUM_TRANSPORTS (SPDK_COUNTOF(g_transports)) #define NUM_TRANSPORTS (SPDK_COUNTOF(g_transport_ops))
int struct spdk_nvmf_transport *
spdk_nvmf_transport_init(void) spdk_nvmf_transport_create(struct spdk_nvmf_tgt *tgt,
enum spdk_nvme_transport_type type)
{ {
size_t i; size_t i;
int count = 0; const struct spdk_nvmf_transport_ops *ops = NULL;
struct spdk_nvmf_transport *transport;
for (i = 0; i != NUM_TRANSPORTS; i++) { for (i = 0; i != NUM_TRANSPORTS; i++) {
if (g_transports[i]->transport_init(g_nvmf_tgt.max_queue_depth, g_nvmf_tgt.max_io_size, if (g_transport_ops[i]->type == type) {
g_nvmf_tgt.in_capsule_data_size) < 0) { ops = g_transport_ops[i];
SPDK_NOTICELOG("Transport type %s init failed\n", break;
spdk_nvme_transport_id_trtype_str(g_transports[i]->type));
} else {
count++;
} }
} }
return count; if (!ops) {
SPDK_ERRLOG("Transport type %s unavailable.\n",
spdk_nvme_transport_id_trtype_str(type));
return NULL;
}
transport = ops->create(tgt);
if (!transport) {
SPDK_ERRLOG("Unable to create new transport of type %s\n",
spdk_nvme_transport_id_trtype_str(type));
return NULL;
}
transport->ops = ops;
transport->tgt = tgt;
return transport;
} }
int int
spdk_nvmf_transport_fini(void) spdk_nvmf_transport_destroy(struct spdk_nvmf_transport *transport)
{ {
size_t i; return transport->ops->destroy(transport);
int count = 0;
for (i = 0; i != NUM_TRANSPORTS; i++) {
if (g_transports[i]->transport_fini() < 0) {
SPDK_NOTICELOG("Transport type %s fini failed\n",
spdk_nvme_transport_id_trtype_str(g_transports[i]->type));
} else {
count++;
}
}
return count;
} }
void void
spdk_nvmf_acceptor_poll(void) spdk_nvmf_transport_poll(struct spdk_nvmf_transport *transport)
{ {
size_t i; transport->ops->acceptor_poll(transport);
for (i = 0; i != NUM_TRANSPORTS; i++) {
g_transports[i]->acceptor_poll();
}
}
const struct spdk_nvmf_transport *
spdk_nvmf_transport_get(enum spdk_nvme_transport_type type)
{
size_t i;
for (i = 0; i != NUM_TRANSPORTS; i++) {
if (type == g_transports[i]->type) {
return g_transports[i];
}
}
return NULL;
} }

View File

@ -42,49 +42,58 @@
struct spdk_nvmf_listen_addr; struct spdk_nvmf_listen_addr;
struct spdk_nvmf_transport { struct spdk_nvmf_transport {
struct spdk_nvmf_tgt *tgt;
const struct spdk_nvmf_transport_ops *ops;
TAILQ_ENTRY(spdk_nvmf_transport) link;
};
struct spdk_nvmf_transport_ops {
/** /**
* Transport type * Transport type
*/ */
enum spdk_nvme_transport_type type; enum spdk_nvme_transport_type type;
/** /**
* Initialize the transport. * Create a transport for the given target
*/ */
int (*transport_init)(uint16_t max_queue_depth, uint32_t max_io_size, struct spdk_nvmf_transport *(*create)(struct spdk_nvmf_tgt *tgt);
uint32_t in_capsule_data_size);
/** /**
* Shut down the transport. * Destroy the transport
*/ */
int (*transport_fini)(void); int (*destroy)(struct spdk_nvmf_transport *transport);
/** /**
* Check for new connections on the transport. * Check for new connections on the transport.
*/ */
void (*acceptor_poll)(void); void (*acceptor_poll)(struct spdk_nvmf_transport *transport);
/** /**
* Instruct the acceptor to listen on the address provided. This * Instruct the acceptor to listen on the address provided. This
* may be called multiple times. * may be called multiple times.
*/ */
int (*listen_addr_add)(struct spdk_nvmf_listen_addr *listen_addr); int (*listen_addr_add)(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_listen_addr *listen_addr);
/** /**
* Instruct to remove listening on the address provided. This * Instruct to remove listening on the address provided. This
* may be called multiple times. * may be called multiple times.
*/ */
int (*listen_addr_remove)(struct spdk_nvmf_listen_addr *listen_addr); int (*listen_addr_remove)(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_listen_addr *listen_addr);
/** /**
* Fill out a discovery log entry for a specific listen address. * Fill out a discovery log entry for a specific listen address.
*/ */
void (*listen_addr_discover)(struct spdk_nvmf_listen_addr *listen_addr, void (*listen_addr_discover)(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_listen_addr *listen_addr,
struct spdk_nvmf_discovery_log_page_entry *entry); struct spdk_nvmf_discovery_log_page_entry *entry);
/** /**
* Create a new ctrlr * Create a new ctrlr
*/ */
struct spdk_nvmf_ctrlr *(*ctrlr_init)(void); struct spdk_nvmf_ctrlr *(*ctrlr_init)(struct spdk_nvmf_transport *transport);
/** /**
* Destroy a ctrlr * Destroy a ctrlr
@ -123,11 +132,12 @@ struct spdk_nvmf_transport {
bool (*qpair_is_idle)(struct spdk_nvmf_qpair *qpair); bool (*qpair_is_idle)(struct spdk_nvmf_qpair *qpair);
}; };
int spdk_nvmf_transport_init(void); struct spdk_nvmf_transport *spdk_nvmf_transport_create(struct spdk_nvmf_tgt *tgt,
int spdk_nvmf_transport_fini(void); enum spdk_nvme_transport_type type);
int spdk_nvmf_transport_destroy(struct spdk_nvmf_transport *transport);
const struct spdk_nvmf_transport *spdk_nvmf_transport_get(enum spdk_nvme_transport_type type); void spdk_nvmf_transport_poll(struct spdk_nvmf_transport *transport);
extern const struct spdk_nvmf_transport spdk_nvmf_transport_rdma; extern const struct spdk_nvmf_transport_ops spdk_nvmf_transport_rdma;
#endif /* SPDK_NVMF_TRANSPORT_H */ #endif /* SPDK_NVMF_TRANSPORT_H */

View File

@ -80,27 +80,46 @@ spdk_bdev_get_name(const struct spdk_bdev *bdev)
} }
static int static int
test_transport1_listen_addr_add(struct spdk_nvmf_listen_addr *listen_addr) test_transport1_listen_addr_add(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_listen_addr *listen_addr)
{ {
return 0; return 0;
} }
static void static void
test_transport1_listen_addr_discover(struct spdk_nvmf_listen_addr *listen_addr, test_transport1_listen_addr_discover(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_listen_addr *listen_addr,
struct spdk_nvmf_discovery_log_page_entry *entry) struct spdk_nvmf_discovery_log_page_entry *entry)
{ {
entry->trtype = 42; entry->trtype = 42;
} }
static const struct spdk_nvmf_transport test_transport1 = { static const struct spdk_nvmf_transport_ops test_transport1_ops = {
.listen_addr_add = test_transport1_listen_addr_add, .listen_addr_add = test_transport1_listen_addr_add,
.listen_addr_discover = test_transport1_listen_addr_discover, .listen_addr_discover = test_transport1_listen_addr_discover,
}; };
const struct spdk_nvmf_transport * static struct spdk_nvmf_transport test_transport1 = {
spdk_nvmf_transport_get(enum spdk_nvme_transport_type trtype) .ops = &test_transport1_ops,
};
struct spdk_nvmf_transport *
spdk_nvmf_transport_create(struct spdk_nvmf_tgt *tgt,
enum spdk_nvme_transport_type type)
{
if (type == SPDK_NVME_TRANSPORT_RDMA) {
test_transport1.tgt = tgt;
return &test_transport1;
}
return NULL;
}
struct spdk_nvmf_transport *
spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, enum spdk_nvme_transport_type trtype)
{ {
if (trtype == SPDK_NVME_TRANSPORT_RDMA) { if (trtype == SPDK_NVME_TRANSPORT_RDMA) {
test_transport1.tgt = tgt;
return &test_transport1; return &test_transport1;
} }

View File

@ -67,27 +67,46 @@ spdk_nvmf_listen_addr_destroy(struct spdk_nvmf_listen_addr *addr)
} }
static int static int
test_transport1_listen_addr_add(struct spdk_nvmf_listen_addr *listen_addr) test_transport1_listen_addr_add(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_listen_addr *listen_addr)
{ {
return 0; return 0;
} }
static void static void
test_transport1_listen_addr_discover(struct spdk_nvmf_listen_addr *listen_addr, test_transport1_listen_addr_discover(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_listen_addr *listen_addr,
struct spdk_nvmf_discovery_log_page_entry *entry) struct spdk_nvmf_discovery_log_page_entry *entry)
{ {
entry->trtype = 42; entry->trtype = 42;
} }
static const struct spdk_nvmf_transport test_transport1 = { static const struct spdk_nvmf_transport_ops test_transport1_ops = {
.listen_addr_add = test_transport1_listen_addr_add, .listen_addr_add = test_transport1_listen_addr_add,
.listen_addr_discover = test_transport1_listen_addr_discover, .listen_addr_discover = test_transport1_listen_addr_discover,
}; };
const struct spdk_nvmf_transport * static struct spdk_nvmf_transport test_transport1 = {
spdk_nvmf_transport_get(enum spdk_nvme_transport_type trtype) .ops = &test_transport1_ops,
};
struct spdk_nvmf_transport *
spdk_nvmf_transport_create(struct spdk_nvmf_tgt *tgt,
enum spdk_nvme_transport_type type)
{
if (type == SPDK_NVME_TRANSPORT_RDMA) {
test_transport1.tgt = tgt;
return &test_transport1;
}
return NULL;
}
struct spdk_nvmf_transport *
spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, enum spdk_nvme_transport_type trtype)
{ {
if (trtype == SPDK_NVME_TRANSPORT_RDMA) { if (trtype == SPDK_NVME_TRANSPORT_RDMA) {
test_transport1.tgt = tgt;
return &test_transport1; return &test_transport1;
} }