Commit fcca8ea6 authored by Jacek Kalwas's avatar Jacek Kalwas Committed by Tomasz Zawadzki
Browse files

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: default avatarJacek Kalwas <jacek.kalwas@intel.com>
Change-Id: I998cb72ed773094faacc6668cf069ba9e2a6bf50
Signed-off-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/481409


Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarAlexey 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: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 489815dc
Loading
Loading
Loading
Loading
+63 −36
Original line number Diff line number Diff line
@@ -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);
		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)) {
	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_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);
+1 −0
Original line number Diff line number Diff line
@@ -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);
+21 −21
Original line number Diff line number Diff line
@@ -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);