[PATCH 4/4] nvmet: expose discovery subsystem

Hannes Reinecke
2022-04-20T09:28:10Z

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@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