nvmf: Fail when sessions span RNICs
The shared memory pool for a session is associated with a particular RNIC via the protection domain. New connections attempting to join a session that came in on a different RNIC can't use that memory, so must be rejected. Change-Id: Ibd79fe90566a231f76b7472e5e9b484c3e528454 Signed-off-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
349295caf2
commit
8b487155fa
@ -134,6 +134,8 @@ static TAILQ_HEAD(, spdk_nvmf_rdma_conn) g_pending_conns = TAILQ_HEAD_INITIALIZE
|
|||||||
struct spdk_nvmf_rdma_session {
|
struct spdk_nvmf_rdma_session {
|
||||||
SLIST_HEAD(, spdk_nvmf_rdma_buf) data_buf_pool;
|
SLIST_HEAD(, spdk_nvmf_rdma_buf) data_buf_pool;
|
||||||
|
|
||||||
|
struct ibv_context *verbs;
|
||||||
|
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
struct ibv_mr *buf_mr;
|
struct ibv_mr *buf_mr;
|
||||||
};
|
};
|
||||||
@ -1169,10 +1171,9 @@ spdk_nvmf_rdma_discover(struct spdk_nvmf_listen_addr *listen_addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
spdk_nvmf_rdma_session_init(struct spdk_nvmf_session *session, struct spdk_nvmf_conn *conn)
|
spdk_nvmf_rdma_session_init(struct spdk_nvmf_session *session)
|
||||||
{
|
{
|
||||||
struct spdk_nvmf_rdma_session *rdma_sess;
|
struct spdk_nvmf_rdma_session *rdma_sess;
|
||||||
struct spdk_nvmf_rdma_conn *rdma_conn = get_rdma_conn(conn);
|
|
||||||
int i;
|
int i;
|
||||||
struct spdk_nvmf_rdma_buf *buf;
|
struct spdk_nvmf_rdma_buf *buf;
|
||||||
|
|
||||||
@ -1193,27 +1194,13 @@ spdk_nvmf_rdma_session_init(struct spdk_nvmf_session *session, struct spdk_nvmf_
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdma_sess->buf_mr = ibv_reg_mr(rdma_conn->cm_id->pd, rdma_sess->buf,
|
|
||||||
g_rdma.max_queue_depth * g_rdma.max_io_size,
|
|
||||||
IBV_ACCESS_LOCAL_WRITE);
|
|
||||||
if (!rdma_sess->buf_mr) {
|
|
||||||
SPDK_ERRLOG("Large buffer pool registration failed (%d x %d)\n",
|
|
||||||
g_rdma.max_queue_depth, g_rdma.max_io_size);
|
|
||||||
spdk_free(rdma_sess->buf);
|
|
||||||
free(rdma_sess);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SPDK_TRACELOG(SPDK_TRACE_RDMA, "Session Shared Data Pool: %p Length: %x LKey: %x\n",
|
|
||||||
rdma_sess->buf, g_rdma.max_queue_depth * g_rdma.max_io_size, rdma_sess->buf_mr->lkey);
|
|
||||||
|
|
||||||
SLIST_INIT(&rdma_sess->data_buf_pool);
|
SLIST_INIT(&rdma_sess->data_buf_pool);
|
||||||
for (i = 0; i < g_rdma.max_queue_depth; i++) {
|
for (i = 0; i < g_rdma.max_queue_depth; i++) {
|
||||||
buf = (struct spdk_nvmf_rdma_buf *)(rdma_sess->buf + (i * g_rdma.max_io_size));
|
buf = (struct spdk_nvmf_rdma_buf *)(rdma_sess->buf + (i * g_rdma.max_io_size));
|
||||||
SLIST_INSERT_HEAD(&rdma_sess->data_buf_pool, buf, link);
|
SLIST_INSERT_HEAD(&rdma_sess->data_buf_pool, buf, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
session->transport = conn->transport;
|
session->transport = &spdk_nvmf_transport_rdma;
|
||||||
session->trctx = rdma_sess;
|
session->trctx = rdma_sess;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1234,6 +1221,48 @@ spdk_nvmf_rdma_session_fini(struct spdk_nvmf_session *session)
|
|||||||
session->trctx = NULL;
|
session->trctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
spdk_nvmf_rdma_session_add_conn(struct spdk_nvmf_session *session,
|
||||||
|
struct spdk_nvmf_conn *conn)
|
||||||
|
{
|
||||||
|
struct spdk_nvmf_rdma_session *rdma_sess = session->trctx;
|
||||||
|
struct spdk_nvmf_rdma_conn *rdma_conn = get_rdma_conn(conn);
|
||||||
|
|
||||||
|
if (rdma_sess->verbs != NULL) {
|
||||||
|
if (rdma_sess->verbs != rdma_conn->cm_id->verbs) {
|
||||||
|
SPDK_ERRLOG("Two connections belonging to the same session cannot connect using different RDMA devices.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing else to do. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdma_sess->verbs = rdma_conn->cm_id->verbs;
|
||||||
|
rdma_sess->buf_mr = ibv_reg_mr(rdma_conn->cm_id->pd, rdma_sess->buf,
|
||||||
|
g_rdma.max_queue_depth * g_rdma.max_io_size,
|
||||||
|
IBV_ACCESS_LOCAL_WRITE);
|
||||||
|
if (!rdma_sess->buf_mr) {
|
||||||
|
SPDK_ERRLOG("Large buffer pool registration failed (%d x %d)\n",
|
||||||
|
g_rdma.max_queue_depth, g_rdma.max_io_size);
|
||||||
|
spdk_free(rdma_sess->buf);
|
||||||
|
free(rdma_sess);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDK_TRACELOG(SPDK_TRACE_RDMA, "Session Shared Data Pool: %p Length: %x LKey: %x\n",
|
||||||
|
rdma_sess->buf, g_rdma.max_queue_depth * g_rdma.max_io_size, rdma_sess->buf_mr->lkey);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
spdk_nvmf_rdma_session_remove_conn(struct spdk_nvmf_session *session,
|
||||||
|
struct spdk_nvmf_conn *conn)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
spdk_nvmf_rdma_request_complete(struct spdk_nvmf_request *req)
|
spdk_nvmf_rdma_request_complete(struct spdk_nvmf_request *req)
|
||||||
{
|
{
|
||||||
@ -1412,6 +1441,8 @@ const struct spdk_nvmf_transport spdk_nvmf_transport_rdma = {
|
|||||||
|
|
||||||
.session_init = spdk_nvmf_rdma_session_init,
|
.session_init = spdk_nvmf_rdma_session_init,
|
||||||
.session_fini = spdk_nvmf_rdma_session_fini,
|
.session_fini = spdk_nvmf_rdma_session_fini,
|
||||||
|
.session_add_conn = spdk_nvmf_rdma_session_add_conn,
|
||||||
|
.session_remove_conn = spdk_nvmf_rdma_session_remove_conn,
|
||||||
|
|
||||||
.req_complete = spdk_nvmf_rdma_request_complete,
|
.req_complete = spdk_nvmf_rdma_request_complete,
|
||||||
.req_release = spdk_nvmf_rdma_request_release,
|
.req_release = spdk_nvmf_rdma_request_release,
|
||||||
|
@ -259,7 +259,14 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
|
|||||||
session->num_connections = 0;
|
session->num_connections = 0;
|
||||||
session->subsys = subsystem;
|
session->subsys = subsystem;
|
||||||
session->max_connections_allowed = g_nvmf_tgt.max_queues_per_session;
|
session->max_connections_allowed = g_nvmf_tgt.max_queues_per_session;
|
||||||
if (conn->transport->session_init(session, conn)) {
|
if (conn->transport->session_init(session)) {
|
||||||
|
rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
|
||||||
|
conn->transport->session_fini(session);
|
||||||
|
free(session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn->transport->session_add_conn(session, conn)) {
|
||||||
rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
|
rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
|
||||||
conn->transport->session_fini(session);
|
conn->transport->session_fini(session);
|
||||||
free(session);
|
free(session);
|
||||||
@ -319,6 +326,11 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
|
|||||||
rsp->status.sc = SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY;
|
rsp->status.sc = SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn->transport->session_add_conn(session, conn)) {
|
||||||
|
INVALID_CONNECT_CMD(qid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
session->num_connections++;
|
session->num_connections++;
|
||||||
@ -339,6 +351,8 @@ spdk_nvmf_session_disconnect(struct spdk_nvmf_conn *conn)
|
|||||||
assert(session != NULL);
|
assert(session != NULL);
|
||||||
session->num_connections--;
|
session->num_connections--;
|
||||||
TAILQ_REMOVE(&session->connections, conn, link);
|
TAILQ_REMOVE(&session->connections, conn, link);
|
||||||
|
|
||||||
|
conn->transport->session_remove_conn(session, conn);
|
||||||
conn->transport->conn_fini(conn);
|
conn->transport->conn_fini(conn);
|
||||||
|
|
||||||
if (session->num_connections == 0) {
|
if (session->num_connections == 0) {
|
||||||
|
@ -75,13 +75,23 @@ struct spdk_nvmf_transport {
|
|||||||
/**
|
/**
|
||||||
* Initialize the transport for the given session
|
* Initialize the transport for the given session
|
||||||
*/
|
*/
|
||||||
int (*session_init)(struct spdk_nvmf_session *session, struct spdk_nvmf_conn *conn);
|
int (*session_init)(struct spdk_nvmf_session *session);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deinitiallize the transport for the given session
|
* Deinitiallize the transport for the given session
|
||||||
*/
|
*/
|
||||||
void (*session_fini)(struct spdk_nvmf_session *session);
|
void (*session_fini)(struct spdk_nvmf_session *session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a connection to a session
|
||||||
|
*/
|
||||||
|
int (*session_add_conn)(struct spdk_nvmf_session *session, struct spdk_nvmf_conn *conn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a connection from a session
|
||||||
|
*/
|
||||||
|
int (*session_remove_conn)(struct spdk_nvmf_session *session, struct spdk_nvmf_conn *conn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Signal request completion, which sends a response
|
* Signal request completion, which sends a response
|
||||||
* to the originator. A request can either
|
* to the originator. A request can either
|
||||||
|
Loading…
Reference in New Issue
Block a user