Commit d6a499fe authored by Ben Walker's avatar Ben Walker
Browse files

nvmf: Move poller from connection to subsystem



Change-Id: Iea6be8156152367c0fd48b8cee8e2ca1e67f340a
Signed-off-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 96a54158
Loading
Loading
Loading
Loading
+0 −46
Original line number Diff line number Diff line
@@ -60,55 +60,9 @@

*/

static void spdk_nvmf_conn_do_work(void *arg);

int
spdk_nvmf_startup_conn(struct spdk_nvmf_conn *conn)
{
	conn->state = CONN_STATE_RUNNING;
	conn->poller.fn = spdk_nvmf_conn_do_work;
	conn->poller.arg = conn;

	spdk_poller_register(&conn->poller, conn->sess->subsys->lcore, NULL);

	return 0;
}

void
spdk_nvmf_conn_destruct(struct spdk_nvmf_conn *conn)
{
	spdk_poller_unregister(&conn->poller, NULL);

	nvmf_disconnect(conn->sess, conn);
	nvmf_rdma_conn_cleanup(conn);
}

static void
spdk_nvmf_conn_do_work(void *arg)
{
	struct spdk_nvmf_conn *conn = arg;
	struct nvmf_session *session = conn->sess;

	/* process pending NVMe device completions */
	if (session) {
		if (conn->type == CONN_TYPE_AQ) {
			nvmf_check_admin_completions(session);
		} else {
			nvmf_check_io_completions(session);
		}
	}

	/* process pending RDMA completions */
	if (nvmf_check_rdma_completions(conn) < 0) {
		SPDK_ERRLOG("Transport poll failed for conn %p; closing connection\n", conn);
		conn->state = CONN_STATE_EXITING;
	}

	if (conn->state == CONN_STATE_EXITING ||
	    conn->state == CONN_STATE_FABRIC_DISCONNECT) {
		spdk_nvmf_conn_destruct(conn);
		if (session && (session->num_connections == 0)) {
			spdk_nvmf_session_destruct(session);
		}
	}
}
+0 −10
Original line number Diff line number Diff line
@@ -40,14 +40,6 @@
#include "nvmf_internal.h"
#include "spdk/queue.h"

/* RDMA transport connection states */
enum conn_state {
	CONN_STATE_INVALID = 0,
	CONN_STATE_RUNNING = 1,
	CONN_STATE_FABRIC_DISCONNECT = 2,
	CONN_STATE_EXITING = 4,
};

enum conn_type {
	CONN_TYPE_AQ = 0,
	CONN_TYPE_IOQ = 1,
@@ -57,12 +49,10 @@ struct spdk_nvmf_conn {
	struct nvmf_session		*sess;

	enum conn_type			type;
	volatile enum conn_state	state;

	uint16_t			sq_head;

	TAILQ_ENTRY(spdk_nvmf_conn) 	link;
	struct spdk_poller		poller;
};

int spdk_nvmf_startup_conn(struct spdk_nvmf_conn *conn);
+36 −18
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@
#include "request.h"
#include "port.h"
#include "host.h"
#include "session.h"
#include "subsystem.h"
#include "spdk/assert.h"
#include "spdk/log.h"
#include "spdk/trace.h"
@@ -719,36 +721,52 @@ err0:
	return -1;
}

static void
spdk_nvmf_handle_disconnect(spdk_event_t event)
{
	struct nvmf_session		*session = spdk_event_get_arg1(event);
	struct spdk_nvmf_conn		*conn = spdk_event_get_arg2(event);

	nvmf_disconnect(session, conn);
}

static int
nvmf_rdma_disconnect(struct rdma_cm_event *event)
nvmf_rdma_disconnect(struct rdma_cm_event *evt)
{
	struct rdma_cm_id		*conn_id;
	struct spdk_nvmf_conn		*conn;
	struct nvmf_session		*session;
	struct spdk_nvmf_rdma_conn 	*rdma_conn;
	spdk_event_t			event;

	/* Check to make sure we know about this rdma device */
	if (event->id == NULL) {
	if (evt->id == NULL) {
		SPDK_ERRLOG("disconnect request: missing cm_id\n");
		goto err0;
		return -1;
	}
	conn_id = event->id;

	conn = conn_id->context;
	conn = evt->id->context;
	if (conn == NULL) {
		SPDK_ERRLOG("disconnect request: no active connection\n");
		goto err0;
		return -1;
	}

	/*
	 * Modify connection state to trigger async termination
	 * next time the connection poller executes
	 */
	conn->state = CONN_STATE_FABRIC_DISCONNECT;
	rdma_conn = get_rdma_conn(conn);

	session = conn->sess;
	if (session == NULL) {
		/* No session has been established yet. That means the conn
		 * must be in the pending connections list. Remove it. */
		TAILQ_REMOVE(&g_pending_conns, rdma_conn, link);
		nvmf_rdma_conn_cleanup(conn);
		return 0;
	}

	/* Pass an event to the core that owns this connection */
	event = spdk_event_allocate(session->subsys->poller.lcore,
				    spdk_nvmf_handle_disconnect,
				    session, conn, NULL);
	spdk_event_call(event);

	SPDK_TRACELOG(SPDK_TRACE_DEBUG, "rdma connection %p state set to CONN_STATE_FABRIC_DISCONNECT\n",
		      conn);
	return 0;
err0:
	return -1;
}

#ifdef DEBUG
+27 −15
Original line number Diff line number Diff line
@@ -398,23 +398,13 @@ nvmf_handle_connect(spdk_event_t event)
			req->data;
	struct spdk_nvmf_fabric_connect_rsp *response = &req->rsp->connect_rsp;
	struct spdk_nvmf_conn *conn = req->conn;
	int rc;

	spdk_nvmf_session_connect(conn, connect, connect_data, response);

	/* Allocate RDMA reqs according to the queue depth and conn type*/
	if (spdk_nvmf_rdma_alloc_reqs(conn)) {
		SPDK_ERRLOG("Unable to allocate sufficient RDMA work requests\n");
		/* TODO: Needs to shutdown poller */
		req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
		spdk_nvmf_request_complete(req);
		return;
	}

	/* Start the connection poller */
	rc = spdk_nvmf_startup_conn(conn);
	if (rc) {
		SPDK_ERRLOG("Unable to start connection poller\n");
		nvmf_disconnect(conn->sess, conn);
		req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
		spdk_nvmf_request_complete(req);
		return;
@@ -427,11 +417,25 @@ nvmf_handle_connect(spdk_event_t event)
	return;
}

static void
invalid_connect_response(struct spdk_nvmf_fabric_connect_rsp *rsp, uint8_t iattr, uint16_t ipo)
{
	rsp->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
	rsp->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
	rsp->status_code_specific.invalid.iattr = iattr;
	rsp->status_code_specific.invalid.ipo = ipo;
}

static bool
nvmf_process_connect(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_conn *conn = req->conn;
	struct spdk_nvmf_subsystem	*subsystem;
	spdk_event_t			event;
	struct spdk_nvmf_fabric_connect_data *data = (struct spdk_nvmf_fabric_connect_data *)
			req->data;
	struct spdk_nvmf_fabric_connect_rsp *rsp = &req->rsp->connect_rsp;

#define INVALID_CONNECT_DATA(field) invalid_connect_response(rsp, 1, offsetof(struct spdk_nvmf_fabric_connect_data, field))

	if (req->length < sizeof(struct spdk_nvmf_fabric_connect_data)) {
		SPDK_ERRLOG("Connect command data length 0x%x too small\n", req->length);
@@ -439,8 +443,16 @@ nvmf_process_connect(struct spdk_nvmf_request *req)
		return true;
	}

	/* Pass an event to the lcore that owns this connection */
	event = spdk_event_allocate(conn->poller.lcore, nvmf_handle_connect, req, NULL, NULL);
	/* Look up the requested subsystem */
	subsystem = nvmf_find_subsystem(data->subnqn);
	if (subsystem == NULL) {
		SPDK_ERRLOG("Could not find subsystem '%s'\n", data->subnqn);
		INVALID_CONNECT_DATA(subnqn);
		return true;
	}

	/* Pass an event to the lcore that owns this subsystem */
	event = spdk_event_allocate(subsystem->poller.lcore, nvmf_handle_connect, req, NULL, NULL);
	spdk_event_call(event);

	return false;
+10 −10
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@

#include "session.h"
#include "nvmf_internal.h"
#include "rdma.h"
#include "subsystem.h"
#include "spdk/log.h"
#include "spdk/trace.h"
@@ -457,17 +458,16 @@ nvmf_property_set(struct nvmf_session *session,
	}
}

void
nvmf_check_admin_completions(struct nvmf_session *session)
int
spdk_nvmf_session_poll(struct nvmf_session *session)
{
	/* Discovery subsystem won't have a real NVMe controller, so check ctrlr first */
	if (session->subsys->ctrlr) {
		spdk_nvme_ctrlr_process_admin_completions(session->subsys->ctrlr);
	struct spdk_nvmf_conn	*conn, *tmp;

	TAILQ_FOREACH_SAFE(conn, &session->connections, link, tmp) {
		if (nvmf_check_rdma_completions(conn) < 0) {
			nvmf_disconnect(session, conn);
		}
	}

void
nvmf_check_io_completions(struct nvmf_session *session)
{
	spdk_nvme_qpair_process_completions(session->subsys->io_qpair, 0);
	return 0;
}
Loading