[PATCH 2/3] nvmet: expose discovery subsystems

Hannes Reinecke hare at suse.de
Wed Apr 6 07:22:09 PDT 2022


Add a module parameter 'expose_discovery_subsys' to allow creation
of discovery subsystems through configfs.
If the option is enabled no default discovery subsystem is created
per default, and the user is required to create one via configfs.

Signed-off-by: Hannes Reinecke <hare at suse.de>
---
 drivers/nvme/target/configfs.c  | 26 ++++++++++++--
 drivers/nvme/target/core.c      | 19 ++++++++--
 drivers/nvme/target/discovery.c | 63 ++++++++++++++++++++++++++-------
 drivers/nvme/target/nvmet.h     |  2 ++
 4 files changed, 91 insertions(+), 19 deletions(-)

diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 31d2490264e3..1fd4d09e3db4 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -20,6 +20,16 @@ static const struct config_item_type nvmet_subsys_type;
 static LIST_HEAD(nvmet_ports_list);
 struct list_head *nvmet_ports = &nvmet_ports_list;
 
+static int expose_discovery_subsys;
+module_param(expose_discovery_subsys, int, 0644);
+MODULE_PARM_DESC(expose_discovery_subsys,
+		 "Expose discovery subsytem in configfs");
+
+bool nvmet_expose_discovery_subsys(void)
+{
+	return expose_discovery_subsys;
+}
+
 struct nvmet_type_name_map {
 	u8		type;
 	const char	*name;
@@ -1264,6 +1274,11 @@ static ssize_t nvmet_subsys_attr_type_store(struct config_item *item,
 	if (subsys->subsys_discovered)
 		return -EACCES;
 
+	if (!expose_discovery_subsys) {
+		pr_err("Unique discovery subsystem NQNs are not enabled\n");
+		return -EINVAL;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(nvmet_subsys_type_map); i++) {
 		if (sysfs_streq(page, nvmet_subsys_type_map[i].name))
 			goto found;
@@ -1348,13 +1363,18 @@ static struct config_group *nvmet_subsys_make(struct config_group *group,
 		const char *name)
 {
 	struct nvmet_subsys *subsys;
+	enum nvme_subsys_type subsys_type = NVME_NQN_NVME;
 
 	if (sysfs_streq(name, NVME_DISC_SUBSYS_NAME)) {
-		pr_err("can't create discovery subsystem through configfs\n");
-		return ERR_PTR(-EINVAL);
+		if (expose_discovery_subsys)
+			subsys_type = NVME_NQN_CURR;
+		else {
+			pr_err("can't create discovery subsystem through configfs\n");
+			return ERR_PTR(-EINVAL);
+		}
 	}
 
-	subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
+	subsys = nvmet_subsys_alloc(name, subsys_type);
 	if (IS_ERR(subsys))
 		return ERR_CAST(subsys);
 
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 90e75324dae0..2187af97c47e 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -1491,14 +1491,19 @@ static struct nvmet_subsys *nvmet_find_get_subsys(struct nvmet_port *port,
 		const char *subsysnqn)
 {
 	struct nvmet_subsys_link *p;
+	enum nvme_subsys_type subsys_type = NVME_NQN_NVME;
 
 	if (!port)
 		return NULL;
 
 	if (!strcmp(NVME_DISC_SUBSYS_NAME, subsysnqn)) {
-		if (!kref_get_unless_zero(&nvmet_disc_subsys->ref))
-			return NULL;
-		return nvmet_disc_subsys;
+		if (nvmet_expose_discovery_subsys())
+			subsys_type = NVME_NQN_CURR;
+		else {
+			if (!kref_get_unless_zero(&nvmet_disc_subsys->ref))
+				return NULL;
+			return nvmet_disc_subsys;
+		}
 	}
 
 	down_read(&nvmet_config_sem);
@@ -1510,6 +1515,13 @@ static struct nvmet_subsys *nvmet_find_get_subsys(struct nvmet_port *port,
 			up_read(&nvmet_config_sem);
 			return p->subsys;
 		}
+		if (subsys_type == NVME_NQN_CURR &&
+		    p->subsys->type == subsys_type) {
+			if (!kref_get_unless_zero(&p->subsys->ref))
+				break;
+			up_read(&nvmet_config_sem);
+			return p->subsys;
+		}
 	}
 	up_read(&nvmet_config_sem);
 	return NULL;
@@ -1544,6 +1556,7 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
 	case NVME_NQN_DISC:
 	case NVME_NQN_CURR:
 		subsys->max_qid = 0;
+		subsys->allow_any_host = 1;
 		break;
 	default:
 		pr_err("%s: Unknown Subsystem type - %d\n", __func__, type);
diff --git a/drivers/nvme/target/discovery.c b/drivers/nvme/target/discovery.c
index b5012df790d5..13fda8f9d60c 100644
--- a/drivers/nvme/target/discovery.c
+++ b/drivers/nvme/target/discovery.c
@@ -29,18 +29,32 @@ void nvmet_port_disc_changed(struct nvmet_port *port,
 			     struct nvmet_subsys *subsys)
 {
 	struct nvmet_ctrl *ctrl;
+	struct nvmet_subsys *disc_subsys = nvmet_disc_subsys;
 
 	lockdep_assert_held(&nvmet_config_sem);
 	nvmet_genctr++;
 
-	mutex_lock(&nvmet_disc_subsys->lock);
-	list_for_each_entry(ctrl, &nvmet_disc_subsys->ctrls, subsys_entry) {
+	if (nvmet_expose_discovery_subsys()) {
+		struct nvmet_subsys_link *s;
+
+		disc_subsys = NULL;
+		list_for_each_entry(s, &port->subsystems, entry) {
+			if (s->subsys->type == NVME_NQN_CURR) {
+				disc_subsys = s->subsys;
+				break;
+			}
+		}
+		if (!disc_subsys)
+			return;
+	}
+	mutex_lock(&disc_subsys->lock);
+	list_for_each_entry(ctrl, &disc_subsys->ctrls, subsys_entry) {
 		if (subsys && !nvmet_host_allowed(subsys, ctrl->hostnqn))
 			continue;
 
 		__nvmet_disc_changed(port, ctrl);
 	}
-	mutex_unlock(&nvmet_disc_subsys->lock);
+	mutex_unlock(&disc_subsys->lock);
 
 	/* If transport can signal change, notify transport */
 	if (port->tr_ops && port->tr_ops->discovery_chg)
@@ -48,19 +62,33 @@ void nvmet_port_disc_changed(struct nvmet_port *port,
 }
 
 static void __nvmet_subsys_disc_changed(struct nvmet_port *port,
-					struct nvmet_subsys *subsys,
 					struct nvmet_host *host)
 {
 	struct nvmet_ctrl *ctrl;
+	struct nvmet_subsys *disc_subsys = nvmet_disc_subsys;
+
+	if (nvmet_expose_discovery_subsys()) {
+		struct nvmet_subsys_link *s;
+
+		disc_subsys = NULL;
+		list_for_each_entry(s, &port->subsystems, entry) {
+			if (s->subsys->type == NVME_NQN_CURR) {
+				disc_subsys = s->subsys;
+				break;
+			}
+		}
+		if (!disc_subsys)
+			return;
+	}
 
-	mutex_lock(&nvmet_disc_subsys->lock);
-	list_for_each_entry(ctrl, &nvmet_disc_subsys->ctrls, subsys_entry) {
+	mutex_lock(&disc_subsys->lock);
+	list_for_each_entry(ctrl, &disc_subsys->ctrls, subsys_entry) {
 		if (host && strcmp(nvmet_host_name(host), ctrl->hostnqn))
 			continue;
 
 		__nvmet_disc_changed(port, ctrl);
 	}
-	mutex_unlock(&nvmet_disc_subsys->lock);
+	mutex_unlock(&disc_subsys->lock);
 }
 
 void nvmet_subsys_disc_changed(struct nvmet_subsys *subsys,
@@ -76,7 +104,7 @@ void nvmet_subsys_disc_changed(struct nvmet_subsys *subsys,
 		list_for_each_entry(s, &port->subsystems, entry) {
 			if (s->subsys != subsys)
 				continue;
-			__nvmet_subsys_disc_changed(port, subsys, host);
+			__nvmet_subsys_disc_changed(port, host);
 		}
 }
 
@@ -146,7 +174,10 @@ static size_t discovery_log_entries(struct nvmet_req *req)
 	struct nvmet_ctrl *ctrl = req->sq->ctrl;
 	struct nvmet_subsys_link *p;
 	struct nvmet_port *r;
-	size_t entries = 1;
+	size_t entries = 0;
+
+	if (!nvmet_expose_discovery_subsys())
+		entries++;
 
 	list_for_each_entry(p, &req->port->subsystems, entry) {
 		if (!nvmet_host_allowed(p->subsys, ctrl->hostnqn))
@@ -208,10 +239,12 @@ static void nvmet_execute_disc_get_log_page(struct nvmet_req *req)
 
 	nvmet_set_disc_traddr(req, req->port, traddr);
 
-	nvmet_format_discovery_entry(hdr, req->port,
-				     nvmet_disc_subsys->subsysnqn,
-				     traddr, NVME_NQN_CURR, numrec);
-	numrec++;
+	if (!nvmet_expose_discovery_subsys()) {
+		nvmet_format_discovery_entry(hdr, req->port,
+				nvmet_disc_subsys->subsysnqn,
+				traddr, NVME_NQN_CURR, numrec);
+		numrec++;
+	}
 
 	list_for_each_entry(p, &req->port->subsystems, entry) {
 		if (!nvmet_host_allowed(p->subsys, ctrl->hostnqn))
@@ -393,6 +426,8 @@ u16 nvmet_parse_discovery_cmd(struct nvmet_req *req)
 
 int __init nvmet_init_discovery(void)
 {
+	if (nvmet_expose_discovery_subsys())
+		return 0;
 	nvmet_disc_subsys =
 		nvmet_subsys_alloc(NVME_DISC_SUBSYS_NAME, NVME_NQN_CURR);
 	return PTR_ERR_OR_ZERO(nvmet_disc_subsys);
@@ -400,5 +435,7 @@ int __init nvmet_init_discovery(void)
 
 void nvmet_exit_discovery(void)
 {
+	if (nvmet_expose_discovery_subsys())
+		return;
 	nvmet_subsys_put(nvmet_disc_subsys);
 }
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 69818752a33a..4d51d5d95ffb 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -532,6 +532,8 @@ extern u32 nvmet_ana_group_enabled[NVMET_MAX_ANAGRPS + 1];
 extern u64 nvmet_ana_chgcnt;
 extern struct rw_semaphore nvmet_ana_sem;
 
+bool nvmet_expose_discovery_subsys(void);
+
 bool nvmet_host_allowed(struct nvmet_subsys *subsys, const char *hostnqn);
 
 int nvmet_bdev_ns_enable(struct nvmet_ns *ns);
-- 
2.29.2




More information about the Linux-nvme mailing list