[PATCH 4/4] nvmet: expose discovery subsystem

Hannes Reinecke hare at suse.de
Wed Apr 20 02:27:30 PDT 2022


Add a module option 'expose_discovery_subsys' to expose the
default discovery subsystem via configfs.
When this option is enabled the internal discovery subsystem
is disabled, and the admin has to create a discovery
subsystem manually.
The discovery subsystem then has to be linked into the ports
which should present the discovery subsystem.

o- /
  o- ports
  | o- 2
  |   o- subsystems
  |     o- nqn.io-2
  | o- 3
  |   o- subsystems
  |     o- nqn.2014-08.org.nvmexpress.discovery
  |     o- nqn.io-1
  o- subsystems
    o- nqn.2014-08.org.nvmexpress.discovery
    | o- namespaces
    o- nqn.io-1
    | o- namespaces
    o- nqn.io-2
      o- namespaces

So in this example the standard discovery service would be available on
port 3, presenting information about subsystem nqn.io-1.
Port 2 would not present a discovery service, but a controller can connect
to subsystem nqn.io-2 on that port.

Signed-off-by: Hannes Reinecke <hare at suse.de>
---
 drivers/nvme/target/configfs.c  | 10 +++++++---
 drivers/nvme/target/core.c      |  2 +-
 drivers/nvme/target/discovery.c | 20 +++++++++++++++++---
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 44573fe0dfe4..365d374d809d 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1364,13 +1364,17 @@ 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 (nvmet_disc_subsys) {
+			pr_err("can't create discovery subsystem through configfs\n");
+			return ERR_PTR(-EINVAL);
+		}
+		subsys_type = NVME_NQN_CURR;
 	}
 
-	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 afd80999a335..ab458ff516db 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -1505,7 +1505,7 @@ static struct nvmet_subsys *nvmet_find_get_subsys(struct nvmet_port *port,
 
 		disc_subsys = port->disc_subsys ?
 			port->disc_subsys : nvmet_disc_subsys;
-		if (!kref_get_unless_zero(&disc_subsys->ref))
+		if (!disc_subsys || !kref_get_unless_zero(&disc_subsys->ref))
 				return NULL;
 		return disc_subsys;
 	}
diff --git a/drivers/nvme/target/discovery.c b/drivers/nvme/target/discovery.c
index ea8fce538342..3b94b60056cf 100644
--- a/drivers/nvme/target/discovery.c
+++ b/drivers/nvme/target/discovery.c
@@ -12,6 +12,11 @@ struct nvmet_subsys *nvmet_disc_subsys;
 
 static u64 nvmet_genctr;
 
+static int expose_discovery_subsys;
+module_param(expose_discovery_subsys, int, 0644);
+MODULE_PARM_DESC(expose_discovery_subsys,
+		 "Expose discovery subsytem in configfs");
+
 static void __nvmet_disc_changed(struct nvmet_port *port,
 				 struct nvmet_ctrl *ctrl)
 {
@@ -36,6 +41,8 @@ void nvmet_port_disc_changed(struct nvmet_port *port,
 
 	disc_subsys = port->disc_subsys ?
 		port->disc_subsys : nvmet_disc_subsys;
+	if (!disc_subsys)
+		return;
 
 	mutex_lock(&disc_subsys->lock);
 	list_for_each_entry(ctrl, &disc_subsys->ctrls, subsys_entry) {
@@ -59,6 +66,8 @@ static void __nvmet_subsys_disc_changed(struct nvmet_port *port,
 
 	disc_subsys = port->disc_subsys ?
 		port->disc_subsys : nvmet_disc_subsys;
+	if (!disc_subsys)
+		return;
 
 	mutex_lock(&disc_subsys->lock);
 
@@ -180,7 +189,7 @@ static size_t discovery_log_entries(struct nvmet_req *req)
 	struct nvmet_port *r;
 	size_t entries = 0;
 
-	if (!req->port->disc_subsys)
+	if (!req->port->disc_subsys && nvmet_disc_subsys)
 		entries++;
 
 	list_for_each_entry(r, nvmet_ports, global_entry) {
@@ -247,7 +256,7 @@ static void nvmet_execute_disc_get_log_page(struct nvmet_req *req)
 
 	nvmet_set_disc_traddr(req, req->port, traddr);
 
-	if (!req->port->disc_subsys) {
+	if (!req->port->disc_subsys && nvmet_disc_subsys) {
 		nvmet_format_discovery_entry(hdr, req->port,
 				nvmet_disc_subsys->subsysnqn,
 				traddr, NVME_NQN_CURR, numrec);
@@ -441,6 +450,10 @@ u16 nvmet_parse_discovery_cmd(struct nvmet_req *req)
 
 int __init nvmet_init_discovery(void)
 {
+	if (expose_discovery_subsys) {
+		nvmet_disc_subsys = NULL;
+		return 0;
+	}
 	nvmet_disc_subsys =
 		nvmet_subsys_alloc(NVME_DISC_SUBSYS_NAME, NVME_NQN_CURR);
 	return PTR_ERR_OR_ZERO(nvmet_disc_subsys);
@@ -448,5 +461,6 @@ int __init nvmet_init_discovery(void)
 
 void nvmet_exit_discovery(void)
 {
-	nvmet_subsys_put(nvmet_disc_subsys);
+	if (nvmet_disc_subsys)
+		nvmet_subsys_put(nvmet_disc_subsys);
 }
-- 
2.29.2




More information about the Linux-nvme mailing list