Commit bc0867dc authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

nvmf: move subsytem poller to nvmf_tgt app



The application is now entirely responsible for scheduling subsystem
pollers and sending events between threads.

Change-Id: I88da1f53b5e8852c7c4acd6f0a7a1e2219fbed41
Signed-off-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent 9f2fc78e
Loading
Loading
Loading
Loading
+18 −15
Original line number Diff line number Diff line
@@ -82,11 +82,11 @@ struct spdk_nvmf_tgt_conf g_spdk_nvmf_tgt_conf;
static int
spdk_add_nvmf_discovery_subsystem(void)
{
	struct spdk_nvmf_subsystem *subsystem;
	struct nvmf_tgt_subsystem *app_subsys;

	subsystem = nvmf_create_subsystem(0, SPDK_NVMF_DISCOVERY_NQN, SPDK_NVMF_SUBTYPE_DISCOVERY,
	app_subsys = nvmf_tgt_create_subsystem(0, SPDK_NVMF_DISCOVERY_NQN, SPDK_NVMF_SUBTYPE_DISCOVERY,
					       rte_get_master_lcore());
	if (subsystem == NULL) {
	if (app_subsys == NULL) {
		SPDK_ERRLOG("Failed creating discovery nvmf library subsystem\n");
		return -1;
	}
@@ -354,6 +354,7 @@ static int
spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
{
	const char *nqn, *mode;
	struct nvmf_tgt_subsystem *app_subsys;
	struct spdk_nvmf_subsystem *subsystem;
	int i, ret;
	uint64_t mask;
@@ -377,14 +378,16 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
	}
	lcore = spdk_nvmf_allocate_lcore(mask, lcore);

	subsystem = nvmf_create_subsystem(sp->num, nqn, SPDK_NVMF_SUBTYPE_NVME, lcore);
	if (subsystem == NULL) {
	app_subsys = nvmf_tgt_create_subsystem(sp->num, nqn, SPDK_NVMF_SUBTYPE_NVME, lcore);
	if (app_subsys == NULL) {
		SPDK_ERRLOG("Subsystem createion failed\n");
		return -1;
	}
	subsystem = app_subsys->subsystem;

	mode = spdk_conf_section_get_val(sp, "Mode");
	if (mode == NULL) {
		nvmf_delete_subsystem(subsystem);
		nvmf_tgt_delete_subsystem(app_subsys);
		SPDK_ERRLOG("No Mode specified for Subsystem %d\n", sp->num);
		return -1;
	}
@@ -394,7 +397,7 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
	} else if (strcasecmp(mode, "Virtual") == 0) {
		subsystem->mode = NVMF_SUBSYSTEM_MODE_VIRTUAL;
	} else {
		nvmf_delete_subsystem(subsystem);
		nvmf_tgt_delete_subsystem(app_subsys);
		SPDK_ERRLOG("Invalid Subsystem mode: %s\n", mode);
		return -1;
	}
@@ -450,7 +453,7 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
		bdf = spdk_conf_section_get_val(sp, "NVMe");
		if (bdf == NULL) {
			SPDK_ERRLOG("Subsystem %d: missing NVMe directive\n", sp->num);
			nvmf_delete_subsystem(subsystem);
			nvmf_tgt_delete_subsystem(app_subsys);
			return -1;
		}

@@ -477,18 +480,18 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
		sn = spdk_conf_section_get_val(sp, "SN");
		if (sn == NULL) {
			SPDK_ERRLOG("Subsystem %d: missing serial number\n", sp->num);
			nvmf_delete_subsystem(subsystem);
			nvmf_tgt_delete_subsystem(app_subsys);
			return -1;
		}
		if (spdk_nvmf_validate_sn(sn) != 0) {
			nvmf_delete_subsystem(subsystem);
			nvmf_tgt_delete_subsystem(app_subsys);
			return -1;
		}

		namespace = spdk_conf_section_get_val(sp, "Namespace");
		if (namespace == NULL) {
			SPDK_ERRLOG("Subsystem %d: missing Namespace directive\n", sp->num);
			nvmf_delete_subsystem(subsystem);
			nvmf_tgt_delete_subsystem(app_subsys);
			return -1;
		}

@@ -504,19 +507,19 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
			namespace = spdk_conf_section_get_nmval(sp, "Namespace", i, 0);
			if (!namespace) {
				SPDK_ERRLOG("Namespace %d: missing block device\n", i);
				nvmf_delete_subsystem(subsystem);
				nvmf_tgt_delete_subsystem(app_subsys);
				return -1;
			}

			bdev = spdk_bdev_get_by_name(namespace);
			if (!bdev) {
				SPDK_ERRLOG("bdev is NULL\n");
				nvmf_delete_subsystem(subsystem);
				nvmf_tgt_delete_subsystem(app_subsys);
				return -1;
			}

			if (spdk_nvmf_subsystem_add_ns(subsystem, bdev)) {
				nvmf_delete_subsystem(subsystem);
				nvmf_tgt_delete_subsystem(app_subsys);
				return -1;
			}

+134 −1
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@

#include "nvmf/transport.h"
#include "nvmf/subsystem.h"
#include "nvmf/request.h"
#include "nvmf/session.h"

#include "spdk/log.h"
#include "spdk/nvme.h"
@@ -61,12 +63,67 @@ struct rte_mempool *request_mempool;

static struct spdk_poller *g_acceptor_poller = NULL;

static TAILQ_HEAD(, nvmf_tgt_subsystem) g_subsystems = TAILQ_HEAD_INITIALIZER(g_subsystems);
static bool g_subsystems_shutdown;

static void
shutdown_complete(void)
{
	int rc;

	rc = spdk_nvmf_check_pools();

	spdk_app_stop(rc);
}

static void
subsystem_delete_event(struct spdk_event *event)
{
	struct nvmf_tgt_subsystem *app_subsys = spdk_event_get_arg1(event);
	struct spdk_nvmf_subsystem *subsystem = app_subsys->subsystem;

	TAILQ_REMOVE(&g_subsystems, app_subsys, tailq);
	free(app_subsys);

	spdk_nvmf_delete_subsystem(subsystem);

	if (g_subsystems_shutdown && TAILQ_EMPTY(&g_subsystems)) {
		/* Finished shutting down all subsystems - continue the shutdown process. */
		shutdown_complete();
	}
}

void
nvmf_tgt_delete_subsystem(struct nvmf_tgt_subsystem *app_subsys)
{
	struct spdk_event *event;

	/*
	 * Unregister the poller - this starts a chain of events that will eventually free
	 * the subsystem's memory.
	 */
	event = spdk_event_allocate(spdk_app_get_current_core(), subsystem_delete_event,
				    app_subsys, NULL, NULL);
	spdk_poller_unregister(&app_subsys->poller, event);
}

static void
shutdown_subsystems(void)
{
	struct nvmf_tgt_subsystem *app_subsys, *tmp;

	g_subsystems_shutdown = true;
	TAILQ_FOREACH_SAFE(app_subsys, &g_subsystems, tailq, tmp) {
		nvmf_tgt_delete_subsystem(app_subsys);
	}
}

static void
acceptor_poller_unregistered_event(struct spdk_event *event)
{
	spdk_nvmf_acceptor_fini();
	spdk_nvmf_transport_fini();
	spdk_shutdown_nvmf_subsystems();
	shutdown_subsystems();
}

static void
@@ -83,6 +140,82 @@ spdk_nvmf_shutdown_cb(void)
	spdk_poller_unregister(&g_acceptor_poller, event);
}

static void
subsystem_poll(void *arg)
{
	struct nvmf_tgt_subsystem *app_subsys = arg;

	spdk_nvmf_subsystem_poll(app_subsys->subsystem);
}

static void
connect_event(struct spdk_event *event)
{
	struct spdk_nvmf_request *req = spdk_event_get_arg1(event);

	spdk_nvmf_handle_connect(req);
}

static void
connect_cb(void *cb_ctx, struct spdk_nvmf_request *req)
{
	struct nvmf_tgt_subsystem *app_subsys = cb_ctx;
	struct spdk_event *event;

	/* Pass an event to the lcore that owns this subsystem */
	event = spdk_event_allocate(app_subsys->lcore, connect_event, req, NULL, NULL);
	spdk_event_call(event);
}

static void
disconnect_event(struct spdk_event *event)
{
	struct spdk_nvmf_conn *conn = spdk_event_get_arg1(event);

	spdk_nvmf_handle_disconnect(conn);
}

static void
disconnect_cb(void *cb_ctx, struct spdk_nvmf_conn *conn)
{
	struct nvmf_tgt_subsystem *app_subsys = cb_ctx;
	struct spdk_event *event;

	/* Pass an event to the core that owns this connection */
	event = spdk_event_allocate(app_subsys->lcore, disconnect_event, conn, NULL, NULL);
	spdk_event_call(event);
}

struct nvmf_tgt_subsystem *
nvmf_tgt_create_subsystem(int num, const char *name, enum spdk_nvmf_subtype subtype, uint32_t lcore)
{
	struct spdk_nvmf_subsystem *subsystem;
	struct nvmf_tgt_subsystem *app_subsys;

	app_subsys = calloc(1, sizeof(*app_subsys));
	if (app_subsys == NULL) {
		SPDK_ERRLOG("Subsystem allocation failed\n");
		return NULL;
	}

	subsystem = spdk_nvmf_create_subsystem(num, name, subtype, app_subsys, connect_cb, disconnect_cb);
	if (subsystem == NULL) {
		SPDK_ERRLOG("Subsystem creation failed\n");
		free(app_subsys);
		return NULL;
	}

	app_subsys->subsystem = subsystem;
	app_subsys->lcore = lcore;

	SPDK_TRACELOG(SPDK_TRACE_NVMF, "allocated subsystem %p on lcore %u\n", subsystem, lcore);

	TAILQ_INSERT_TAIL(&g_subsystems, app_subsys, tailq);
	spdk_poller_register(&app_subsys->poller, subsystem_poll, app_subsys, lcore, NULL, 0);

	return app_subsys;
}

static void
usage(void)
{
+21 −0
Original line number Diff line number Diff line
@@ -34,12 +34,33 @@
#ifndef NVMF_TGT_H
#define NVMF_TGT_H

#include <stdint.h>

#include "spdk/nvmf_spec.h"
#include "spdk/queue.h"

struct spdk_nvmf_tgt_conf {
	uint32_t acceptor_lcore;
};

struct nvmf_tgt_subsystem {
	struct spdk_nvmf_subsystem *subsystem;
	struct spdk_poller *poller;

	TAILQ_ENTRY(nvmf_tgt_subsystem) tailq;

	uint32_t lcore;
};

extern struct spdk_nvmf_tgt_conf g_spdk_nvmf_tgt_conf;

int spdk_nvmf_parse_conf(void);

struct nvmf_tgt_subsystem *nvmf_tgt_create_subsystem(int num,
		const char *name,
		enum spdk_nvmf_subtype subtype,
		uint32_t lcore);

void nvmf_tgt_delete_subsystem(struct nvmf_tgt_subsystem *app_subsys);

#endif
+4 −15
Original line number Diff line number Diff line
@@ -734,22 +734,13 @@ 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 *evt)
{
	struct spdk_nvmf_conn		*conn;
	struct nvmf_session		*session;
	struct spdk_nvmf_subsystem	*subsystem;
	struct spdk_nvmf_rdma_conn 	*rdma_conn;
	spdk_event_t			event;

	if (evt->id == NULL) {
		SPDK_ERRLOG("disconnect request: missing cm_id\n");
@@ -775,11 +766,9 @@ nvmf_rdma_disconnect(struct rdma_cm_event *evt)
		return 0;
	}

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

	subsystem->disconnect_cb(subsystem->cb_ctx, conn);

	return 0;
}
+3 −7
Original line number Diff line number Diff line
@@ -148,10 +148,9 @@ nvmf_process_property_set(struct spdk_nvmf_request *req)
	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

static void
nvmf_handle_connect(spdk_event_t event)
void
spdk_nvmf_handle_connect(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_request *req = spdk_event_get_arg1(event);
	struct spdk_nvmf_fabric_connect_cmd *connect = &req->cmd->connect_cmd;
	struct spdk_nvmf_fabric_connect_data *connect_data = (struct spdk_nvmf_fabric_connect_data *)
			req->data;
@@ -180,7 +179,6 @@ static spdk_nvmf_request_exec_status
nvmf_process_connect(struct spdk_nvmf_request *req)
{
	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_cmd *cmd = &req->cmd->connect_cmd;
@@ -224,9 +222,7 @@ nvmf_process_connect(struct spdk_nvmf_request *req)
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

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

	return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS;
}
Loading