nvmf: Sessions now contain a list of connections.

There was an extra layer of indirection complicating
things for no reason. This removes it.

Change-Id: I8d4e654eb17f8f6ec028d775329794f0745fb0f7
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Ben Walker 2016-06-30 11:18:52 -07:00
parent 2cb8321a35
commit 64f6abea9c
5 changed files with 44 additions and 104 deletions

View File

@ -250,7 +250,7 @@ _conn_destruct(spdk_event_t event)
* going away. If this is the AQ connection then * going away. If this is the AQ connection then
* set state for other connections to abort. * set state for other connections to abort.
*/ */
nvmf_disconnect((void *)conn, conn->sess); nvmf_disconnect(conn->sess, conn);
if (conn->type == CONN_TYPE_AQ) { if (conn->type == CONN_TYPE_AQ) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AQ connection destruct, trigger session closure\n"); SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AQ connection destruct, trigger session closure\n");

View File

@ -59,10 +59,6 @@ struct spdk_nvmf_conn {
struct nvmf_session *sess; struct nvmf_session *sess;
/*
* values saved from fabric connect and private data
*/
uint16_t qid; uint16_t qid;
uint16_t cntlid; uint16_t cntlid;

View File

@ -434,14 +434,18 @@ nvmf_process_connect(struct spdk_nvmf_request *req)
response = &req->rsp->connect_rsp; response = &req->rsp->connect_rsp;
session = nvmf_connect((void *)conn, connect, connect_data, response); conn->qid = connect->qid;
conn->cntlid = connect_data->cntlid;
if (conn->qid > 0) {
conn->type = CONN_TYPE_IOQ;
} else {
conn->type = CONN_TYPE_AQ;
}
session = nvmf_connect(conn, connect, connect_data, response);
if (session != NULL) { if (session != NULL) {
conn->sess = session; conn->sess = session;
conn->qid = connect->qid; if (conn->type == CONN_TYPE_AQ) {
if (connect->qid > 0) {
conn->type = CONN_TYPE_IOQ; /* I/O Connection */
} else {
/* When session first created, set some attributes */
nvmf_init_conn_properites(conn, session, response); nvmf_init_conn_properites(conn, session, response);
} }
} }

View File

@ -236,116 +236,67 @@ nvmf_find_session_by_id(const char *subnqn, uint16_t cntl_id)
} }
struct nvmf_session * struct nvmf_session *
nvmf_connect(void *fabric_conn, nvmf_connect(struct spdk_nvmf_conn *conn,
struct spdk_nvmf_fabric_connect_cmd *connect, struct spdk_nvmf_fabric_connect_cmd *connect,
struct spdk_nvmf_fabric_connect_data *connect_data, struct spdk_nvmf_fabric_connect_data *connect_data,
struct spdk_nvmf_fabric_connect_rsp *response) struct spdk_nvmf_fabric_connect_rsp *response)
{ {
struct nvmf_session *session; struct nvmf_session *session;
struct nvmf_connection_entry *connection = NULL;
connection = calloc(1, sizeof(struct nvmf_connection_entry)); if (conn->type == CONN_TYPE_AQ) {
if (connection == NULL) /* For admin connections, establish a new session */
goto connect_fail; SPDK_TRACELOG(SPDK_TRACE_NVMF, "CONNECT Admin Queue for controller id %d\n", conn->cntlid);
if (conn->cntlid != 0xFFFF) {
/* Figure out if this is the first connect and we /* This NVMf target only supports dynamic mode. */
* need to allocate an nvmf_session or if this is SPDK_ERRLOG("The NVMf target only supports dynamic mode.\n");
* a subsequent connect for an I/O queue and we need
* to return an existing session
*/
if (connect->qid == 0) {
/* first connect for AQ connection */
SPDK_TRACELOG(SPDK_TRACE_NVMF, "AQ connect capsule\n");
if (connect_data->cntlid == 0xffff) {
/* no nvmf session/controller association, allocate one */
session = nvmf_create_session(connect_data->subnqn);
if (session == NULL) {
SPDK_ERRLOG("create session failed\n");
response->status.sc = SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY;
goto connect_fail;
}
} else {
SPDK_ERRLOG("nvmf AQ connection attempt to cntlid %d\n", connect_data->cntlid);
response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM; response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
goto connect_fail; return NULL;
}
session = nvmf_create_session(connect_data->subnqn);
if (session == NULL) {
response->status.sc = SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY;
return NULL;
} }
connection->is_aq_conn = 1;
} else { } else {
SPDK_TRACELOG(SPDK_TRACE_NVMF, "IOQ connect capsule\n"); SPDK_TRACELOG(SPDK_TRACE_NVMF, "CONNECT I/O Queue for controller id %d\n", conn->cntlid);
/* locate the existing session */
session = nvmf_find_session_by_id(connect_data->subnqn, connect_data->cntlid); session = nvmf_find_session_by_id(connect_data->subnqn, connect_data->cntlid);
if (session == NULL) { if (session == NULL) {
SPDK_ERRLOG("invalid nvmf cntlid %d\n", connect_data->cntlid); SPDK_ERRLOG("Unknown controller id %d\n", conn->cntlid);
response->status.sc = SPDK_NVMF_FABRIC_SC_RESTART_DISCOVERY; response->status.sc = SPDK_NVMF_FABRIC_SC_RESTART_DISCOVERY;
goto connect_fail; return NULL;
} }
/* check if we would exceed session connection limit */ /* check if we would exceed session connection limit */
if (session->num_connections >= session->max_connections_allowed) { if (session->num_connections >= session->max_connections_allowed) {
SPDK_ERRLOG("connection limit %d\n", session->num_connections); SPDK_ERRLOG("connection limit %d\n", session->num_connections);
response->status.sc = SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY; response->status.sc = SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY;
goto connect_fail; return NULL;
} }
if (session->is_valid == 0) {
SPDK_ERRLOG("session invalid or at IO connection limit %d\n", session->num_connections);
response->status.sc = SPDK_NVMF_FABRIC_SC_RESTART_DISCOVERY;
goto connect_fail;
}
connection->is_aq_conn = 0;
} }
connection->fabric_conn = fabric_conn;
session->num_connections++; session->num_connections++;
TAILQ_INSERT_HEAD(&session->connections, connection, entries); TAILQ_INSERT_HEAD(&session->connections, conn, link);
response->status_code_specific.success.cntlid = session->cntlid; response->status_code_specific.success.cntlid = session->cntlid;
response->status.sc = 0; response->status.sc = 0;
return session; return session;
connect_fail:
if (connection)
free(connection);
return NULL;
} }
void void
nvmf_disconnect(void *fabric_conn, nvmf_disconnect(struct nvmf_session *session,
struct nvmf_session *session) struct spdk_nvmf_conn *conn)
{ {
struct nvmf_connection_entry *conn, *tconn, *rconn = NULL; if (session) {
if (session->num_connections > 0) {
/* Indication from the fabric transport that a session->num_connections--;
* specific connection has gone way. If the TAILQ_REMOVE(&session->connections, conn, link);
* connection is the AQ connection then expect
* that the complete session will go away
*/
if (session == NULL) {
SPDK_TRACELOG(SPDK_TRACE_NVMF, "nvmf_disconnect: session not active!\n");
return;
}
TAILQ_FOREACH_SAFE(conn, &session->connections, entries, tconn) {
if (conn->fabric_conn == fabric_conn) {
rconn = conn;
break;
} }
}
if (rconn == NULL) {
SPDK_ERRLOG("Session connection did not exist!\n");
return;
}
SPDK_TRACELOG(SPDK_TRACE_NVMF, "Disconnect NVMf conn %p, sess %p\n", rconn, session);
session->num_connections--; if (session->num_connections == 0) {
TAILQ_REMOVE(&session->connections, rconn, entries); nvmf_delete_session(session);
free(rconn); }
if (session->num_connections == 0) {
SPDK_TRACELOG(SPDK_TRACE_NVMF, "Session connection count 0, deleting session %p!\n",
session);
nvmf_delete_session(session);
} }
} }

View File

@ -37,22 +37,11 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "conn.h"
#include "request.h" #include "request.h"
#include "spdk/nvmf_spec.h" #include "spdk/nvmf_spec.h"
#include "spdk/queue.h" #include "spdk/queue.h"
/*
* This structure maintains local NVMf library specific connection
* state that includes an opaque pointer back to its parent fabric
* transport connection context.
*/
struct nvmf_connection_entry {
void *fabric_conn;
int is_aq_conn;
TAILQ_ENTRY(nvmf_connection_entry) entries;
};
/* define a virtual controller limit to the number of QPs supported */ /* define a virtual controller limit to the number of QPs supported */
#define MAX_SESSION_IO_QUEUES 64 #define MAX_SESSION_IO_QUEUES 64
@ -76,7 +65,7 @@ struct nvmf_session {
} vcprop; /* virtual controller properties */ } vcprop; /* virtual controller properties */
struct spdk_nvme_ctrlr_data vcdata; /* virtual controller data */ struct spdk_nvme_ctrlr_data vcdata; /* virtual controller data */
TAILQ_HEAD(connection_q, nvmf_connection_entry) connections; TAILQ_HEAD(connection_q, spdk_nvmf_conn) connections;
int num_connections; int num_connections;
int max_connections_allowed; int max_connections_allowed;
@ -86,13 +75,13 @@ struct nvmf_session {
}; };
struct nvmf_session * struct nvmf_session *
nvmf_connect(void *fabric_conn, nvmf_connect(struct spdk_nvmf_conn *conn,
struct spdk_nvmf_fabric_connect_cmd *connect, struct spdk_nvmf_fabric_connect_cmd *connect,
struct spdk_nvmf_fabric_connect_data *connect_data, struct spdk_nvmf_fabric_connect_data *connect_data,
struct spdk_nvmf_fabric_connect_rsp *response); struct spdk_nvmf_fabric_connect_rsp *response);
void void
nvmf_disconnect(void *fabric_conn, struct nvmf_session *session); nvmf_disconnect(struct nvmf_session *session, struct spdk_nvmf_conn *conn);
void void
nvmf_init_session_properties(struct nvmf_session *session, int aq_depth); nvmf_init_session_properties(struct nvmf_session *session, int aq_depth);