nvmf: Add support for multiple sessions per subsystem.

This feature should only be used if clients are coordinating
with one another.

Change-Id: I89a437441a7e3fbcc1e5f6efa1c8e970ade7c2ec
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Ben Walker 2016-09-19 13:29:17 -07:00
parent 0bde77082d
commit 1ad2c3ea73
5 changed files with 44 additions and 37 deletions

View File

@ -91,7 +91,7 @@ nvmf_init_nvme_session_properties(struct spdk_nvmf_session *session)
session->subsys->ops->ctrlr_get_data(session);
session->vcdata.aerl = 0;
session->vcdata.cntlid = 0;
session->vcdata.cntlid = session->id;
session->vcdata.kas = 10;
session->vcdata.maxcmd = g_nvmf_tgt.max_queue_depth;
session->vcdata.mdts = nvmf_u32log2(g_nvmf_tgt.max_io_size / 4096);
@ -158,7 +158,7 @@ nvmf_init_nvme_session_properties(struct spdk_nvmf_session *session)
static void session_destruct(struct spdk_nvmf_session *session)
{
session->subsys->session = NULL;
TAILQ_REMOVE(&session->subsys->sessions, session, link);
session->transport->session_fini(session);
free(session);
}
@ -245,15 +245,8 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
return;
}
if (subsystem->session) {
SPDK_ERRLOG("Cannot connect to already-connected controller\n");
rsp->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
rsp->status.sc = SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY;
return;
}
/* Establish a new session */
subsystem->session = session = calloc(1, sizeof(struct spdk_nvmf_session));
session = calloc(1, sizeof(struct spdk_nvmf_session));
if (session == NULL) {
SPDK_ERRLOG("Memory allocation failure\n");
rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
@ -261,6 +254,7 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
}
TAILQ_INIT(&session->connections);
session->id = subsystem->session_id++;
session->kato = cmd->kato;
session->num_connections = 0;
session->subsys = subsystem;
@ -269,7 +263,6 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
conn->transport->session_fini(session);
free(session);
subsystem->session = NULL;
return;
}
@ -278,19 +271,28 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
} else {
nvmf_init_discovery_session_properties(session);
}
TAILQ_INSERT_TAIL(&subsystem->sessions, session, link);
} else {
struct spdk_nvmf_session *tmp;
conn->type = CONN_TYPE_IOQ;
SPDK_TRACELOG(SPDK_TRACE_NVMF, "Connect I/O Queue for controller id 0x%x\n", data->cntlid);
/* We always return CNTLID 0, so verify that the I/O connect CNTLID matches */
if (data->cntlid != 0) {
session = NULL;
TAILQ_FOREACH(tmp, &subsystem->sessions, link) {
if (tmp->id == data->cntlid) {
session = tmp;
break;
}
}
if (session == NULL) {
SPDK_ERRLOG("Unknown controller ID 0x%x\n", data->cntlid);
INVALID_CONNECT_DATA(cntlid);
return;
}
session = subsystem->session;
if (session == NULL || !session->vcprop.cc.bits.en) {
if (!session->vcprop.cc.bits.en) {
SPDK_ERRLOG("Got I/O connect before ctrlr was enabled\n");
INVALID_CONNECT_CMD(qid);
return;

View File

@ -67,7 +67,8 @@ struct spdk_nvmf_conn {
* At least one admin connection and additional IOQ connections.
*/
struct spdk_nvmf_session {
struct spdk_nvmf_subsystem *subsys;
uint32_t id;
struct spdk_nvmf_subsystem *subsys;
struct {
union spdk_nvme_cap_register cap;
@ -86,6 +87,8 @@ struct spdk_nvmf_session {
/* This is filled in by calling the transport's
* session_init function. */
void *trctx;
TAILQ_ENTRY(spdk_nvmf_session) link;
};
void spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,

View File

@ -76,20 +76,17 @@ nvmf_find_subsystem(const char *subnqn, const char *hostnqn)
void
spdk_nvmf_subsystem_poll(struct spdk_nvmf_subsystem *subsystem)
{
struct spdk_nvmf_session *session = subsystem->session;
struct spdk_nvmf_session *session;
if (!session) {
/* No active connections, so just return */
return;
TAILQ_FOREACH(session, &subsystem->sessions, link) {
/* For NVMe subsystems, check the backing physical device for completions. */
if (subsystem->subtype == SPDK_NVMF_SUBTYPE_NVME) {
session->subsys->ops->poll_for_completions(session);
}
/* For each connection in the session, check for completions */
spdk_nvmf_session_poll(session);
}
/* For NVMe subsystems, check the backing physical device for completions. */
if (subsystem->subtype == SPDK_NVMF_SUBTYPE_NVME) {
session->subsys->ops->poll_for_completions(session);
}
/* For each connection in the session, check for completions */
spdk_nvmf_session_poll(session);
}
static bool
@ -143,6 +140,7 @@ spdk_nvmf_create_subsystem(int num, const char *name,
snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", name);
TAILQ_INIT(&subsystem->listen_addrs);
TAILQ_INIT(&subsystem->hosts);
TAILQ_INIT(&subsystem->sessions);
TAILQ_INSERT_HEAD(&g_subsystems, subsystem, entries);
@ -154,6 +152,7 @@ spdk_nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem)
{
struct spdk_nvmf_listen_addr *listen_addr, *listen_addr_tmp;
struct spdk_nvmf_host *host, *host_tmp;
struct spdk_nvmf_session *session, *session_tmp;
if (!subsystem) {
return;
@ -176,9 +175,10 @@ spdk_nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem)
subsystem->num_hosts--;
}
if (subsystem->session) {
spdk_nvmf_session_destruct(subsystem->session);
TAILQ_FOREACH_SAFE(session, &subsystem->sessions, link, session_tmp) {
spdk_nvmf_session_destruct(session);
}
if (subsystem->ops) {
subsystem->ops->detach(subsystem);
}

View File

@ -106,7 +106,6 @@ struct spdk_nvmf_subsystem {
char subnqn[SPDK_NVMF_NQN_MAX_LEN];
enum spdk_nvmf_subsystem_mode mode;
enum spdk_nvmf_subtype subtype;
struct spdk_nvmf_session *session;
union {
struct {
@ -129,6 +128,9 @@ struct spdk_nvmf_subsystem {
spdk_nvmf_subsystem_connect_fn connect_cb;
spdk_nvmf_subsystem_disconnect_fn disconnect_cb;
TAILQ_HEAD(, spdk_nvmf_session) sessions;
uint32_t session_id;
TAILQ_HEAD(, spdk_nvmf_listen_addr) listen_addrs;
uint32_t num_listen_addrs;

View File

@ -58,12 +58,12 @@ struct __attribute__((packed)) nvme_read_cdw12 {
uint8_t lr : 1; /* limited retry */
};
static void nvmf_virtual_set_dsm(struct spdk_nvmf_subsystem *subsys)
static void nvmf_virtual_set_dsm(struct spdk_nvmf_session *session)
{
int i;
for (i = 0; i < subsys->dev.virtual.ns_count; i++) {
struct spdk_bdev *bdev = subsys->dev.virtual.ns_list[i];
for (i = 0; i < session->subsys->dev.virtual.ns_count; i++) {
struct spdk_bdev *bdev = session->subsys->dev.virtual.ns_list[i];
if (!spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
SPDK_TRACELOG(SPDK_TRACE_NVMF,
@ -74,8 +74,8 @@ static void nvmf_virtual_set_dsm(struct spdk_nvmf_subsystem *subsys)
}
SPDK_TRACELOG(SPDK_TRACE_NVMF, "All devices in Subsystem%d support unmap - enabling DSM\n",
subsys->num);
subsys->session->vcdata.oncs.dsm = 1;
session->subsys->num);
session->vcdata.oncs.dsm = 1;
}
static void
@ -108,7 +108,7 @@ nvmf_virtual_ctrlr_get_data(struct spdk_nvmf_session *session)
session->vcdata.vwc.present = 1;
session->vcdata.sgls.supported = 1;
strncpy(session->vcdata.subnqn, session->subsys->subnqn, sizeof(session->vcdata.subnqn));
nvmf_virtual_set_dsm(subsys);
nvmf_virtual_set_dsm(session);
}
static void