nvmf/ctrlr: introduce ctrlr connect backdoor

This internal interface allows to create nvmf ctrlr and connect io
qpairs on add listener rpc request (i.e. when subsystem is stopped
and listener is not yet on subsystem's list).

Signed-off-by: Jacek Kalwas <jacek.kalwas@intel.com>
Change-Id: I998cb72ed773094faacc6668cf069ba9e2a6bf50
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/481409
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Alexey Marchuk <alexeymar@mellanox.com>
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Jacek Kalwas 2020-01-13 10:05:25 +01:00 committed by Tomasz Zawadzki
parent 489815dcf5
commit fcca8ea6a9
3 changed files with 85 additions and 57 deletions

View File

@ -491,7 +491,7 @@ spdk_nvmf_qpair_access_allowed(struct spdk_nvmf_qpair *qpair, struct spdk_nvmf_s
}
static int
spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
_spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
{
struct spdk_nvmf_fabric_connect_data *data = req->data;
struct spdk_nvmf_fabric_connect_cmd *cmd = &req->cmd->connect_cmd;
@ -501,12 +501,6 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
struct spdk_nvmf_ctrlr *ctrlr;
struct spdk_nvmf_subsystem *subsystem;
if (req->length < sizeof(struct spdk_nvmf_fabric_connect_data)) {
SPDK_ERRLOG("Connect command data length 0x%x too small\n", req->length);
rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "recfmt 0x%x qid %u sqsize %u\n",
cmd->recfmt, cmd->qid, cmd->sqsize);
@ -520,13 +514,8 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
data->hostid[9],
ntohs(*(uint16_t *)&data->hostid[10]),
ntohl(*(uint32_t *)&data->hostid[12]));
if (cmd->recfmt != 0) {
SPDK_ERRLOG("Connect command unsupported RECFMT %u\n", cmd->recfmt);
rsp->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
rsp->status.sc = SPDK_NVMF_FABRIC_SC_INCOMPATIBLE_FORMAT;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
SPDK_DEBUGLOG(SPDK_LOG_NVMF, " subnqn: \"%s\"\n", data->subnqn);
SPDK_DEBUGLOG(SPDK_LOG_NVMF, " hostnqn: \"%s\"\n", data->hostnqn);
subsystem = spdk_nvmf_tgt_find_subsystem(transport->tgt, data->subnqn);
if (!subsystem) {
@ -534,28 +523,10 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
if ((subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE) ||
(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSING) ||
(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED) ||
(subsystem->state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING)) {
SPDK_ERRLOG("Subsystem '%s' is not ready\n", subsystem->subnqn);
if (cmd->recfmt != 0) {
SPDK_ERRLOG("Connect command unsupported RECFMT %u\n", cmd->recfmt);
rsp->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
rsp->status.sc = SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
/* Ensure that hostnqn is null terminated */
if (!memchr(data->hostnqn, '\0', SPDK_NVMF_NQN_MAX_LEN + 1)) {
SPDK_ERRLOG("Connect HOSTNQN is not null terminated\n");
SPDK_NVMF_INVALID_CONNECT_DATA(rsp, hostnqn);
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
SPDK_DEBUGLOG(SPDK_LOG_NVMF, " hostnqn: \"%s\"\n", data->hostnqn);
if (!spdk_nvmf_qpair_access_allowed(req->qpair, subsystem, data->hostnqn)) {
rsp->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
rsp->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_HOST;
rsp->status.sc = SPDK_NVMF_FABRIC_SC_INCOMPATIBLE_FORMAT;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
@ -617,6 +588,62 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
}
}
int
spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
{
struct spdk_nvmf_qpair *qpair = req->qpair;
TAILQ_INSERT_TAIL(&qpair->outstanding, req, link);
return _spdk_nvmf_ctrlr_connect(req);
}
static int
spdk_nvmf_ctrlr_cmd_connect(struct spdk_nvmf_request *req)
{
struct spdk_nvmf_fabric_connect_data *data = req->data;
struct spdk_nvmf_fabric_connect_rsp *rsp = &req->rsp->connect_rsp;
struct spdk_nvmf_transport *transport = req->qpair->transport;
struct spdk_nvmf_subsystem *subsystem;
if (req->length < sizeof(struct spdk_nvmf_fabric_connect_data)) {
SPDK_ERRLOG("Connect command data length 0x%x too small\n", req->length);
rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
subsystem = spdk_nvmf_tgt_find_subsystem(transport->tgt, data->subnqn);
if (!subsystem) {
SPDK_NVMF_INVALID_CONNECT_DATA(rsp, subnqn);
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
if ((subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE) ||
(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSING) ||
(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED) ||
(subsystem->state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING)) {
SPDK_ERRLOG("Subsystem '%s' is not ready\n", subsystem->subnqn);
rsp->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
rsp->status.sc = SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
/* Ensure that hostnqn is null terminated */
if (!memchr(data->hostnqn, '\0', SPDK_NVMF_NQN_MAX_LEN + 1)) {
SPDK_ERRLOG("Connect HOSTNQN is not null terminated\n");
SPDK_NVMF_INVALID_CONNECT_DATA(rsp, hostnqn);
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
if (!spdk_nvmf_qpair_access_allowed(req->qpair, subsystem, data->hostnqn)) {
rsp->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
rsp->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_HOST;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
return _spdk_nvmf_ctrlr_connect(req);
}
static uint64_t
nvmf_prop_get_cap(struct spdk_nvmf_ctrlr *ctrlr)
{
@ -2130,7 +2157,7 @@ spdk_nvmf_ctrlr_process_fabrics_cmd(struct spdk_nvmf_request *req)
if (qpair->ctrlr == NULL) {
/* No ctrlr established yet; the only valid command is Connect */
if (cap_hdr->fctype == SPDK_NVMF_FABRIC_COMMAND_CONNECT) {
return spdk_nvmf_ctrlr_connect(req);
return spdk_nvmf_ctrlr_cmd_connect(req);
} else {
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Got fctype 0x%x, expected Connect\n",
cap_hdr->fctype);

View File

@ -410,6 +410,7 @@ void spdk_nvmf_get_discovery_log_page(struct spdk_nvmf_tgt *tgt, const char *hos
void spdk_nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr);
int spdk_nvmf_ctrlr_process_fabrics_cmd(struct spdk_nvmf_request *req);
int spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req);
int spdk_nvmf_ctrlr_process_admin_cmd(struct spdk_nvmf_request *req);
int spdk_nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req);
bool spdk_nvmf_ctrlr_dsm_supported(struct spdk_nvmf_ctrlr *ctrlr);

View File

@ -388,7 +388,7 @@ test_connect(void)
/* Valid admin connect command */
memset(&rsp, 0, sizeof(rsp));
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status));
@ -402,7 +402,7 @@ test_connect(void)
cmd.connect_cmd.kato = 0;
memset(&rsp, 0, sizeof(rsp));
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status));
@ -416,7 +416,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
req.length = sizeof(connect_data) - 1;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
@ -428,7 +428,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
cmd.connect_cmd.recfmt = 1234;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -440,7 +440,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
MOCK_SET(spdk_nvmf_tgt_find_subsystem, NULL);
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -454,7 +454,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
memset(connect_data.hostnqn, 'b', sizeof(connect_data.hostnqn));
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -468,7 +468,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
MOCK_SET(spdk_nvmf_subsystem_host_allowed, false);
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -480,7 +480,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
cmd.connect_cmd.sqsize = 0;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -494,7 +494,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
cmd.connect_cmd.sqsize = 32;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -509,7 +509,7 @@ test_connect(void)
cmd.connect_cmd.qid = 1;
cmd.connect_cmd.sqsize = 64;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -524,7 +524,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
connect_data.cntlid = 0x1234;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -543,7 +543,7 @@ test_connect(void)
cmd.connect_cmd.qid = 1;
cmd.connect_cmd.sqsize = 63;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status));
@ -555,7 +555,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, NULL);
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -570,7 +570,7 @@ test_connect(void)
subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY;
subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -586,7 +586,7 @@ test_connect(void)
subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY;
subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status));
@ -605,7 +605,7 @@ test_connect(void)
subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY;
subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status));
@ -623,7 +623,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
ctrlr.vcprop.cc.bits.en = 0;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -637,7 +637,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
ctrlr.vcprop.cc.bits.iosqes = 3;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -651,7 +651,7 @@ test_connect(void)
memset(&rsp, 0, sizeof(rsp));
ctrlr.vcprop.cc.bits.iocqes = 3;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -667,7 +667,7 @@ test_connect(void)
spdk_bit_array_set(ctrlr.qpair_mask, 1);
spdk_bit_array_set(ctrlr.qpair_mask, 2);
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
@ -685,7 +685,7 @@ test_connect(void)
spdk_bit_array_set(ctrlr.qpair_mask, 1);
cmd.connect_cmd.qid = 1;
TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link);
rc = spdk_nvmf_ctrlr_connect(&req);
rc = spdk_nvmf_ctrlr_cmd_connect(&req);
poll_threads();
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS);
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);