Commit 14451d76 authored by Daniel Verkamp's avatar Daniel Verkamp Committed by Ben Walker
Browse files

nvmf: encapsulate namespace data into a struct



Add a new struct spdk_nvmf_ns to hold namespace information, and add
accessor functions so that it can be moved out of the public API in
future patches.

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


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 81062f60
Loading
Loading
Loading
Loading
+5 −8
Original line number Diff line number Diff line
@@ -99,22 +99,19 @@ dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct nvmf_tgt_subsystem *tg
	spdk_json_write_array_end(w);

	if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) {
		uint32_t i;
		struct spdk_nvmf_ns *ns;

		spdk_json_write_name(w, "serial_number");
		spdk_json_write_string(w, spdk_nvmf_subsystem_get_sn(subsystem));
		spdk_json_write_name(w, "namespaces");
		spdk_json_write_array_begin(w);
		for (i = 0; i < subsystem->dev.max_nsid; i++) {
			if (subsystem->dev.ns_list[i] == NULL) {
				continue;
			}

		for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
		     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
			spdk_json_write_object_begin(w);
			spdk_json_write_name(w, "nsid");
			spdk_json_write_int32(w, i + 1);
			spdk_json_write_int32(w, spdk_nvmf_ns_get_id(ns));
			spdk_json_write_name(w, "name");
			spdk_json_write_string(w, spdk_bdev_get_name(subsystem->dev.ns_list[i]));
			spdk_json_write_string(w, spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns)));
			spdk_json_write_object_end(w);
		}
		spdk_json_write_array_end(w);
+56 −7
Original line number Diff line number Diff line
@@ -80,6 +80,14 @@ struct spdk_nvmf_subsystem_allowed_listener {
	TAILQ_ENTRY(spdk_nvmf_subsystem_allowed_listener)	link;
};

struct spdk_nvmf_ns {
	struct spdk_bdev *bdev;
	struct spdk_bdev_desc *desc;
	struct spdk_io_channel *ch;
	uint32_t id;
	bool allocated;
};

/*
 * The NVMf subsystem, as indicated in the specification, is a collection
 * of controllers.  Any individual controller has
@@ -91,13 +99,10 @@ struct spdk_nvmf_subsystem {
	enum spdk_nvmf_subtype subtype;
	bool is_removed;

	struct {
	char sn[MAX_SN_LEN + 1];
		struct spdk_bdev *ns_list[MAX_VIRTUAL_NAMESPACE];
		struct spdk_bdev_desc *desc[MAX_VIRTUAL_NAMESPACE];
		struct spdk_io_channel *ch[MAX_VIRTUAL_NAMESPACE];

	struct spdk_nvmf_ns			ns[MAX_VIRTUAL_NAMESPACE];
	uint32_t 				max_nsid;
	} dev;

	void					*cb_ctx;
	spdk_nvmf_subsystem_connect_fn		connect_cb;
@@ -157,6 +162,50 @@ void spdk_nvmf_subsystem_poll(struct spdk_nvmf_subsystem *subsystem);
uint32_t spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev,
				    uint32_t nsid);

/**
 * Return the first allocated namespace in a subsystem.
 *
 * \param subsystem Subsystem to query.
 * \return First allocated namespace in this subsystem, or NULL if this subsystem has no namespaces.
 */
struct spdk_nvmf_ns *spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem);

/**
 * Return the next allocated namespace in a subsystem.
 *
 * \param subsystem Subsystem to query.
 * \param prev_ns Previous ns returned from this function.
 * \return Next allocated namespace in this subsystem, or NULL if prev_ns was the last namespace.
 */
struct spdk_nvmf_ns *spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem,
		struct spdk_nvmf_ns *prev_ns);

/**
 * Get a namespace in a subsystem by NSID.
 *
 * \param subsystem Subsystem to search.
 * \param nsid Namespace ID to find.
 * \return Namespace matching nsid, or NULL if nsid was not found.
 */
struct spdk_nvmf_ns *spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem,
		uint32_t nsid);

/**
 * Get a namespace's NSID.
 *
 * \param ns Namespace to query.
 * \return NSID of ns.
 */
uint32_t spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns);

/**
 * Get a namespace's associated bdev.
 *
 * \param ns Namespace to query
 * \return Backing bdev of ns.
 */
struct spdk_bdev *spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns);

const char *spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem);

int spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn);
+12 −20
Original line number Diff line number Diff line
@@ -845,22 +845,16 @@ spdk_nvmf_ctrlr_identify_ns(struct spdk_nvmf_subsystem *subsystem,
			    struct spdk_nvme_cpl *rsp,
			    struct spdk_nvme_ns_data *nsdata)
{
	struct spdk_bdev *bdev;
	struct spdk_nvmf_ns *ns;

	if (cmd->nsid > subsystem->dev.max_nsid || cmd->nsid == 0) {
	ns = _spdk_nvmf_subsystem_get_ns(subsystem, cmd->nsid);
	if (ns == NULL || ns->bdev == NULL) {
		SPDK_ERRLOG("Identify Namespace for invalid NSID %u\n", cmd->nsid);
		rsp->status.sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	bdev = subsystem->dev.ns_list[cmd->nsid - 1];

	if (bdev == NULL) {
		memset(nsdata, 0, sizeof(*nsdata));
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	return spdk_nvmf_bdev_ctrlr_identify_ns(bdev, nsdata);
	return spdk_nvmf_bdev_ctrlr_identify_ns(ns->bdev, nsdata);
}

static int
@@ -906,7 +900,7 @@ spdk_nvmf_ctrlr_identify_ctrlr(struct spdk_nvmf_ctrlr *ctrlr, struct spdk_nvme_c
		cdata->sqes.max = 6;
		cdata->cqes.min = 4;
		cdata->cqes.max = 4;
		cdata->nn = subsystem->dev.max_nsid;
		cdata->nn = subsystem->max_nsid;
		cdata->vwc.present = 1;

		cdata->nvmf_specific.ioccsz = sizeof(struct spdk_nvme_cmd) / 16;
@@ -941,7 +935,8 @@ spdk_nvmf_ctrlr_identify_active_ns_list(struct spdk_nvmf_subsystem *subsystem,
					struct spdk_nvme_cpl *rsp,
					struct spdk_nvme_ns_list *ns_list)
{
	uint32_t i, num_ns, count = 0;
	struct spdk_nvmf_ns *ns;
	uint32_t count = 0;

	if (cmd->nsid >= 0xfffffffeUL) {
		SPDK_ERRLOG("Identify Active Namespace List with invalid NSID %u\n", cmd->nsid);
@@ -949,16 +944,13 @@ spdk_nvmf_ctrlr_identify_active_ns_list(struct spdk_nvmf_subsystem *subsystem,
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	num_ns = subsystem->dev.max_nsid;

	for (i = 1; i <= num_ns; i++) {
		if (i <= cmd->nsid) {
			continue;
		}
		if (subsystem->dev.ns_list[i - 1] == NULL) {
	for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
	     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
		if (ns->id <= cmd->nsid) {
			continue;
		}
		ns_list->ns_list[count++] = i;

		ns_list->ns_list[count++] = ns->id;
		if (count == SPDK_COUNTOF(ns_list->ns_list)) {
			break;
		}
+59 −45
Original line number Diff line number Diff line
@@ -61,25 +61,26 @@ struct __attribute__((packed)) nvme_read_cdw12 {
bool
spdk_nvmf_ctrlr_dsm_supported(struct spdk_nvmf_ctrlr *ctrlr)
{
	uint32_t i;
	struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys;
	struct spdk_nvmf_ns *ns;

	for (i = 0; i < ctrlr->subsys->dev.max_nsid; i++) {
		struct spdk_bdev *bdev = ctrlr->subsys->dev.ns_list[i];

		if (bdev == NULL) {
	for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
	     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
		if (ns->bdev == NULL) {
			continue;
		}

		if (!spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
		if (!spdk_bdev_io_type_supported(ns->bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
			SPDK_TRACELOG(SPDK_TRACE_NVMF,
				      "Subsystem%u Namespace %s does not support unmap - not enabling DSM\n",
				      i, spdk_bdev_get_name(bdev));
				      "Subsystem %s namespace %u (%s) does not support unmap - not enabling DSM\n",
				      spdk_nvmf_subsystem_get_nqn(subsystem),
				      ns->id, spdk_bdev_get_name(ns->bdev));
			return false;
		}
	}

	SPDK_TRACELOG(SPDK_TRACE_NVMF, "All devices in Subsystem %s support unmap - enabling DSM\n",
		      spdk_nvmf_subsystem_get_nqn(ctrlr->subsys));
		      spdk_nvmf_subsystem_get_nqn(subsystem));
	return true;
}

@@ -296,6 +297,7 @@ int
spdk_nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req)
{
	uint32_t nsid;
	struct spdk_nvmf_ns *ns;
	struct spdk_bdev *bdev;
	struct spdk_bdev_desc *desc;
	struct spdk_io_channel *ch;
@@ -307,20 +309,16 @@ spdk_nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req)
	response->status.sc = SPDK_NVME_SC_SUCCESS;
	nsid = cmd->nsid;

	if (nsid > subsystem->dev.max_nsid || nsid == 0) {
	ns = _spdk_nvmf_subsystem_get_ns(subsystem, nsid);
	if (ns == NULL || ns->bdev == NULL) {
		SPDK_ERRLOG("Unsuccessful query for nsid %u\n", cmd->nsid);
		response->status.sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	bdev = subsystem->dev.ns_list[nsid - 1];
	if (bdev == NULL) {
		response->status.sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	desc = subsystem->dev.desc[nsid - 1];
	ch = subsystem->dev.ch[nsid - 1];
	bdev = ns->bdev;
	desc = ns->desc;
	ch = ns->ch;
	switch (cmd->opc) {
	case SPDK_NVME_OPC_READ:
	case SPDK_NVME_OPC_WRITE:
@@ -334,47 +332,63 @@ spdk_nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req)
	}
}

int
spdk_nvmf_subsystem_bdev_attach(struct spdk_nvmf_subsystem *subsystem)
static int
spdk_nvmf_ns_bdev_attach(struct spdk_nvmf_ns *ns)
{
	struct spdk_bdev *bdev;
	struct spdk_io_channel *ch;
	uint32_t i;

	for (i = 0; i < subsystem->dev.max_nsid; i++) {
		bdev = subsystem->dev.ns_list[i];
		if (bdev == NULL) {
			continue;
	if (ns->bdev == NULL) {
		return 0;
	}

		ch = spdk_bdev_get_io_channel(subsystem->dev.desc[i]);
		if (ch == NULL) {
	ns->ch = spdk_bdev_get_io_channel(ns->desc);
	if (ns->ch == NULL) {
		SPDK_ERRLOG("io_channel allocation failed\n");
		return -1;
	}
		subsystem->dev.ch[i] = ch;
	}

	return 0;
}

void
spdk_nvmf_subsystem_bdev_detach(struct spdk_nvmf_subsystem *subsystem)
static void
spdk_nvmf_ns_bdev_detach(struct spdk_nvmf_ns *ns)
{
	uint32_t i;
	if (ns->bdev == NULL) {
		return;
	}

	for (i = 0; i < subsystem->dev.max_nsid; i++) {
		if (subsystem->dev.ns_list[i]) {
			if (subsystem->dev.ch[i]) {
				spdk_put_io_channel(subsystem->dev.ch[i]);
				subsystem->dev.ch[i] = NULL;
	if (ns->ch) {
		spdk_put_io_channel(ns->ch);
		ns->ch = NULL;
	}
	if (ns->desc) {
		spdk_bdev_close(ns->desc);
		ns->desc = NULL;
	}
	ns->bdev = NULL;
}
			if (subsystem->dev.desc[i]) {
				spdk_bdev_close(subsystem->dev.desc[i]);
				subsystem->dev.desc[i] = NULL;

int
spdk_nvmf_subsystem_bdev_attach(struct spdk_nvmf_subsystem *subsystem)
{
	struct spdk_nvmf_ns *ns;

	for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
	     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
		if (spdk_nvmf_ns_bdev_attach(ns)) {
			return -1;
		}
			subsystem->dev.ns_list[i] = NULL;
	}

	return 0;
}

void
spdk_nvmf_subsystem_bdev_detach(struct spdk_nvmf_subsystem *subsystem)
{
	struct spdk_nvmf_ns *ns;

	for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
	     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
		spdk_nvmf_ns_bdev_detach(ns);
	}
	subsystem->dev.max_nsid = 0;
	subsystem->max_nsid = 0;
}
+19 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@

#include "spdk/stdinc.h"

#include "spdk/likely.h"
#include "spdk/nvmf.h"
#include "spdk/nvmf_spec.h"
#include "spdk/assert.h"
@@ -71,6 +72,24 @@ void spdk_nvmf_listen_addr_destroy(struct spdk_nvmf_listen_addr *addr);
struct spdk_nvmf_transport *spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt,
		enum spdk_nvme_transport_type);

static inline struct spdk_nvmf_ns *
_spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
{
	struct spdk_nvmf_ns *ns;

	/* NOTE: This implicitly also checks for 0, since 0 - 1 wraps around to UINT32_MAX. */
	if (spdk_unlikely(nsid - 1 >= subsystem->max_nsid)) {
		return NULL;
	}

	ns = &subsystem->ns[nsid - 1];
	if (!ns->allocated) {
		return NULL;
	}

	return ns;
}

#define OBJECT_NVMF_IO				0x30

#define TRACE_GROUP_NVMF			0x3
Loading