nvmf: Handle wrap-around for global cntlids

64k sessions over the lifetime of a single target is something
that really could happen, so handle this case.

Change-Id: Iaed92b9ff6cd078fcd7c1efe88cf0c860c77c4ac
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Ben Walker 2017-01-19 11:02:17 -07:00
parent d77c030172
commit ec38ec127c
2 changed files with 52 additions and 3 deletions

View File

@ -32,6 +32,7 @@
*/
#include <arpa/inet.h>
#include <stdint.h>
#include <string.h>
#include "session.h"
@ -47,8 +48,6 @@
#define MIN_KEEP_ALIVE_TIMEOUT 10000
static uint16_t g_next_cntlid = 1;
static void
nvmf_init_discovery_session_properties(struct spdk_nvmf_session *session)
{
@ -191,6 +190,44 @@ invalid_connect_response(struct spdk_nvmf_fabric_connect_rsp *rsp, uint8_t iattr
rsp->status_code_specific.invalid.ipo = ipo;
}
static uint16_t
spdk_nvmf_session_gen_cntlid(void)
{
static uint16_t cntlid = 0; /* cntlid is static, so its value is preserved */
struct spdk_nvmf_subsystem *subsystem;
uint16_t count;
count = UINT16_MAX - 1;
do {
/* cntlid is an unsigned 16-bit integer, so let it overflow
* back to 0 if necessary.
*/
cntlid++;
if (cntlid == 0) {
/* 0 is not a valid cntlid because it is the reserved value in the RDMA
* private data for cntlid. This is the value sent by pre-NVMe-oF 1.1
* initiators.
*/
cntlid++;
}
/* Check if a subsystem with this cntlid currently exists. This could
* happen for a very long-lived session on a target with many short-lived
* sessions, where cntlid wraps around.
*/
subsystem = spdk_nvmf_find_subsystem_with_cntlid(cntlid);
count--;
} while (subsystem != NULL && count > 0);
if (count == 0) {
return 0;
}
return cntlid;
}
void
spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
struct spdk_nvmf_fabric_connect_cmd *cmd,
@ -260,7 +297,13 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
TAILQ_INIT(&session->connections);
session->cntlid = g_next_cntlid++;
session->cntlid = spdk_nvmf_session_gen_cntlid();
if (session->cntlid == 0) {
/* Unable to get a cntlid */
SPDK_ERRLOG("Reached max simultaneous sessions\n");
rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
return;
}
session->kato = cmd->kato;
session->async_event_config.raw = 0;
session->num_connections = 0;

View File

@ -44,6 +44,12 @@ SPDK_LOG_REGISTER_TRACE_FLAG("nvmf", SPDK_TRACE_NVMF)
struct spdk_nvmf_globals g_nvmf_tgt;
struct spdk_nvmf_subsystem *
spdk_nvmf_find_subsystem_with_cntlid(uint16_t cntlid)
{
return NULL;
}
struct spdk_nvmf_subsystem *
nvmf_find_subsystem(const char *subnqn)
{