Commit 2d34864a authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

nvmf: stub out Abort command support



Add handling of the Abort command in virtual subsystems.  This doesn't
actually abort any requests - the spdk_nvmf_request_abort()
implementation just fails all abort requests - but at least this gives
us a place to hook up actual abort handling later.

Change-Id: Iafaa393c6f9e7f404af91747cbd81c64ab4810bb
Signed-off-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/365905


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 27becf40
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -311,3 +311,10 @@ spdk_nvmf_request_exec(struct spdk_nvmf_request *req)

	return 0;
}

int
spdk_nvmf_request_abort(struct spdk_nvmf_request *req)
{
	/* TODO: implement abort, at least for commands that are still queued in software */
	return -1;
}
+2 −0
Original line number Diff line number Diff line
@@ -73,4 +73,6 @@ spdk_nvmf_request_exec(struct spdk_nvmf_request *req);

int spdk_nvmf_request_complete(struct spdk_nvmf_request *req);

int spdk_nvmf_request_abort(struct spdk_nvmf_request *req);

#endif
+21 −0
Original line number Diff line number Diff line
@@ -273,6 +273,7 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
		return;
	}
	conn->sq_head_max = cmd->sqsize;
	conn->qid = cmd->qid;

	if (cmd->qid == 0) {
		conn->type = CONN_TYPE_AQ;
@@ -405,6 +406,26 @@ spdk_nvmf_session_disconnect(struct spdk_nvmf_conn *conn)
	}
}

struct spdk_nvmf_conn *
spdk_nvmf_session_get_conn(struct spdk_nvmf_session *session, uint16_t qid)
{
	struct spdk_nvmf_conn *conn;

	TAILQ_FOREACH(conn, &session->connections, link) {
		if (conn->qid == qid) {
			return conn;
		}
	}
	return NULL;
}

struct spdk_nvmf_request *
spdk_nvmf_conn_get_request(struct spdk_nvmf_conn *conn, uint16_t cid)
{
	/* TODO: track list of outstanding requests in conn? */
	return NULL;
}

static uint64_t
nvmf_prop_get_cap(struct spdk_nvmf_session *session)
{
+5 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ struct spdk_nvmf_conn {
	struct spdk_nvmf_session		*sess;
	enum conn_type				type;

	uint16_t				qid;
	uint16_t				sq_head;
	uint16_t				sq_head_max;

@@ -102,6 +103,10 @@ void spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
			       struct spdk_nvmf_fabric_connect_data *data,
			       struct spdk_nvmf_fabric_connect_rsp *rsp);

struct spdk_nvmf_conn *spdk_nvmf_session_get_conn(struct spdk_nvmf_session *session, uint16_t qid);

struct spdk_nvmf_request *spdk_nvmf_conn_get_request(struct spdk_nvmf_conn *conn, uint16_t cid);

void
spdk_nvmf_property_get(struct spdk_nvmf_session *session,
		       struct spdk_nvmf_fabric_prop_get_cmd *cmd,
+49 −0
Original line number Diff line number Diff line
@@ -286,6 +286,53 @@ nvmf_virtual_ctrlr_identify(struct spdk_nvmf_request *req)
	}
}

static int
nvmf_virtual_ctrlr_abort(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_session *session = req->conn->sess;
	struct spdk_nvme_cpl *rsp = &req->rsp->nvme_cpl;
	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
	uint32_t cdw10 = cmd->cdw10;
	uint16_t cid = cdw10 >> 16;
	uint16_t sqid = cdw10 & 0xFFFFu;
	struct spdk_nvmf_conn *conn;
	struct spdk_nvmf_request *req_to_abort;

	SPDK_TRACELOG(SPDK_TRACE_NVMF, "abort sqid=%u cid=%u\n", sqid, cid);

	rsp->cdw0 = 1; /* Command not aborted */

	conn = spdk_nvmf_session_get_conn(session, sqid);
	if (conn == NULL) {
		SPDK_TRACELOG(SPDK_TRACE_NVMF, "sqid %u not found\n", sqid);
		rsp->status.sct = SPDK_NVME_SCT_GENERIC;
		rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	/*
	 * NOTE: This relies on the assumption that all connections for a session will be handled
	 * on the same thread.  If this assumption becomes untrue, this will need to pass a message
	 * to the thread handling conn, and the abort will need to be asynchronous.
	 */
	req_to_abort = spdk_nvmf_conn_get_request(conn, cid);
	if (req_to_abort == NULL) {
		SPDK_TRACELOG(SPDK_TRACE_NVMF, "cid %u not found\n", cid);
		rsp->status.sct = SPDK_NVME_SCT_GENERIC;
		rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	if (spdk_nvmf_request_abort(req_to_abort) == 0) {
		SPDK_TRACELOG(SPDK_TRACE_NVMF, "abort session=%p req=%p sqid=%u cid=%u successful\n",
			      session, req_to_abort, sqid, cid);
		rsp->cdw0 = 0; /* Command successfully aborted */
	}
	rsp->status.sct = SPDK_NVME_SCT_GENERIC;
	rsp->status.sc = SPDK_NVME_SC_SUCCESS;
	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

static int
nvmf_virtual_ctrlr_get_features(struct spdk_nvmf_request *req)
{
@@ -351,6 +398,8 @@ nvmf_virtual_ctrlr_process_admin_cmd(struct spdk_nvmf_request *req)
		return nvmf_virtual_ctrlr_get_log_page(req);
	case SPDK_NVME_OPC_IDENTIFY:
		return nvmf_virtual_ctrlr_identify(req);
	case SPDK_NVME_OPC_ABORT:
		return nvmf_virtual_ctrlr_abort(req);
	case SPDK_NVME_OPC_GET_FEATURES:
		return nvmf_virtual_ctrlr_get_features(req);
	case SPDK_NVME_OPC_SET_FEATURES:
Loading