Commit 1e481d04 authored by Ben Walker's avatar Ben Walker Committed by Jim Harris
Browse files

nvmf: Do not allow NN to change while connections present



Per the NVMe specification, NN cannot change while there
are connections present. There was originally a check
for this that was removed in commit 763ab888 to match
the behavior in the Linux kernel. However, after a
discussion with the NVMe specification committee, SPDK
was originally correct.

Change-Id: I42414d1ee0c8c83f3335d8790edbf65d813c5c74
Signed-off-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/412544


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent a35b1eb6
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -1271,7 +1271,11 @@ 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;
		if (subsystem->max_allowed_nsid != 0) {
			cdata->nn = subsystem->max_allowed_nsid;
		} else {
			cdata->nn = subsystem->max_nsid;
		}
		cdata->vwc.present = 1;

		cdata->nvmf_specific.ioccsz = sizeof(struct spdk_nvme_cmd) / 16;
+1 −1
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@
#include "spdk/util.h"

#define SPDK_NVMF_DEFAULT_NUM_CTRLRS_PER_LCORE 1
#define SPDK_NVMF_DEFAULT_MAX_NSID 128

enum spdk_nvmf_subsystem_state {
	SPDK_NVMF_SUBSYSTEM_INACTIVE = 0,
@@ -218,7 +219,6 @@ struct spdk_nvmf_subsystem {
	uint32_t				max_nsid;
	/* This is the maximum allowed nsid to a subsystem */
	uint32_t				max_allowed_nsid;
	uint32_t				num_allocated_nsid;

	TAILQ_HEAD(, spdk_nvmf_ctrlr)		ctrlrs;

+27 −34
Original line number Diff line number Diff line
@@ -273,12 +273,7 @@ spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt,
	subsystem->id = sid;
	subsystem->subtype = type;
	subsystem->max_nsid = num_ns;
	/*
	 *  Initially max_nsid and max_allowed_nsid will be same. If max_allowed_nsid is zero nsid range can grow dynamically
	 *  but if it is more than 1 nsid range cannot be extended beyond max_allowed_nsid
	 */
	subsystem->max_allowed_nsid = num_ns;
	subsystem->num_allocated_nsid = 0;
	subsystem->next_cntlid = 0;
	snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn);
	TAILQ_INIT(&subsystem->listeners);
@@ -901,7 +896,6 @@ _spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t n

	spdk_bdev_close(ns->desc);
	free(ns);
	subsystem->num_allocated_nsid--;

	spdk_nvmf_subsystem_ns_changed(subsystem, nsid);

@@ -1006,29 +1000,6 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
		return 0;
	}

	if (opts.nsid > subsystem->max_nsid ||
	    (opts.nsid == 0 && subsystem->num_allocated_nsid == subsystem->max_nsid)) {
		struct spdk_nvmf_ns **new_ns_array;
		uint32_t new_max_nsid;

		if (opts.nsid > subsystem->max_nsid) {
			new_max_nsid = opts.nsid;
		} else {
			new_max_nsid = subsystem->max_nsid + 1;
		}

		new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * new_max_nsid);
		if (new_ns_array == NULL) {
			SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n");
			return 0;
		}

		memset(new_ns_array + subsystem->max_nsid, 0,
		       sizeof(struct spdk_nvmf_ns *) * (new_max_nsid - subsystem->max_nsid));
		subsystem->ns = new_ns_array;
		subsystem->max_nsid = new_max_nsid;
	}

	if (opts.nsid == 0) {
		/* NSID not specified - find a free index */
		for (i = 0; i < subsystem->max_nsid; i++) {
@@ -1038,9 +1009,19 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
			}
		}
		if (opts.nsid == 0) {
			SPDK_ERRLOG("All available NSIDs in use\n");
			/* All of the current slots are full */
			if (TAILQ_EMPTY(&subsystem->ctrlrs) &&
			    (subsystem->max_allowed_nsid == 0 ||
			     subsystem->max_nsid < subsystem->max_allowed_nsid)) {
				/* No controllers are connected and the subsystem is
				* not at its maximum NSID limit, so the array
				* can be expanded. */
				opts.nsid = subsystem->max_nsid + 1;
			} else {
				SPDK_ERRLOG("Can't extend NSID range above MaxNamespaces\n");
				return 0;
			}
		}
	} else {
		/* Specific NSID requested */
		if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid)) {
@@ -1049,6 +1030,21 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
		}
	}

	if (opts.nsid > subsystem->max_nsid) {
		struct spdk_nvmf_ns **new_ns_array;

		new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * opts.nsid);
		if (new_ns_array == NULL) {
			SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n");
			return 0;
		}

		memset(new_ns_array + subsystem->max_nsid, 0,
		       sizeof(struct spdk_nvmf_ns *) * (opts.nsid - subsystem->max_nsid));
		subsystem->ns = new_ns_array;
		subsystem->max_nsid = opts.nsid;
	}

	ns = calloc(1, sizeof(*ns));
	if (ns == NULL) {
		SPDK_ERRLOG("Namespace allocation failed\n");
@@ -1072,9 +1068,6 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
		      spdk_bdev_get_name(bdev),
		      opts.nsid);

	subsystem->max_nsid = spdk_max(subsystem->max_nsid, opts.nsid);
	subsystem->num_allocated_nsid++;

	spdk_nvmf_subsystem_ns_changed(subsystem, opts.nsid);

	return opts.nsid;