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 <arpa/inet.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
@ -47,8 +48,6 @@
|
|||||||
|
|
||||||
#define MIN_KEEP_ALIVE_TIMEOUT 10000
|
#define MIN_KEEP_ALIVE_TIMEOUT 10000
|
||||||
|
|
||||||
static uint16_t g_next_cntlid = 1;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nvmf_init_discovery_session_properties(struct spdk_nvmf_session *session)
|
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;
|
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
|
void
|
||||||
spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
|
spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
|
||||||
struct spdk_nvmf_fabric_connect_cmd *cmd,
|
struct spdk_nvmf_fabric_connect_cmd *cmd,
|
||||||
@ -260,7 +297,13 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
|
|||||||
|
|
||||||
TAILQ_INIT(&session->connections);
|
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->kato = cmd->kato;
|
||||||
session->async_event_config.raw = 0;
|
session->async_event_config.raw = 0;
|
||||||
session->num_connections = 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_globals g_nvmf_tgt;
|
||||||
|
|
||||||
|
struct spdk_nvmf_subsystem *
|
||||||
|
spdk_nvmf_find_subsystem_with_cntlid(uint16_t cntlid)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct spdk_nvmf_subsystem *
|
struct spdk_nvmf_subsystem *
|
||||||
nvmf_find_subsystem(const char *subnqn)
|
nvmf_find_subsystem(const char *subnqn)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user