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:
parent
d77c030172
commit
ec38ec127c
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user