[PATCH 3/3] nvmet: include all configured port in the discovery log page

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


When exposed discovery subsystems are enabled we should include
all configured ports in the discovery log page, not just those
through which the controller was connected.

Signed-off-by: Hannes Reinecke <hare at suse.de>
---
 drivers/nvme/target/discovery.c | 72 ++++++++++++++++++++++++++++-----
 1 file changed, 61 insertions(+), 11 deletions(-)

diff --git a/drivers/nvme/target/discovery.c b/drivers/nvme/target/discovery.c
index 13fda8f9d60c..d23353a750dd 100644
--- a/drivers/nvme/target/discovery.c
+++ b/drivers/nvme/target/discovery.c
@@ -172,6 +172,7 @@ static void nvmet_set_disc_traddr(struct nvmet_req *req, struct nvmet_port *port
 static size_t discovery_log_entries(struct nvmet_req *req)
 {
 	struct nvmet_ctrl *ctrl = req->sq->ctrl;
+	struct nvmet_subsys *disc_subsys = ctrl->subsys;
 	struct nvmet_subsys_link *p;
 	struct nvmet_port *r;
 	size_t entries = 0;
@@ -179,10 +180,27 @@ static size_t discovery_log_entries(struct nvmet_req *req)
 	if (!nvmet_expose_discovery_subsys())
 		entries++;
 
-	list_for_each_entry(p, &req->port->subsystems, entry) {
-		if (!nvmet_host_allowed(p->subsys, ctrl->hostnqn))
-			continue;
-		entries++;
+	list_for_each_entry(r, nvmet_ports, global_entry) {
+		if (!nvmet_expose_discovery_subsys()) {
+			if (r != req->port)
+				continue;
+		} else {
+			bool linked = false;
+
+			list_for_each_entry(p, &r->subsystems, entry) {
+				if (p->subsys == disc_subsys) {
+					linked = true;
+					break;
+				}
+			}
+			if (!linked)
+				continue;
+		}
+		list_for_each_entry(p, &r->subsystems, entry) {
+			if (!nvmet_host_allowed(p->subsys, ctrl->hostnqn))
+				continue;
+			entries++;
+		}
 	}
 	list_for_each_entry(r, &req->port->referrals, entry)
 		entries++;
@@ -193,6 +211,7 @@ static void nvmet_execute_disc_get_log_page(struct nvmet_req *req)
 {
 	const int entry_size = sizeof(struct nvmf_disc_rsp_page_entry);
 	struct nvmet_ctrl *ctrl = req->sq->ctrl;
+	struct nvmet_subsys *disc_subsys = ctrl->subsys;
 	struct nvmf_disc_rsp_page_hdr *hdr;
 	u64 offset = nvmet_get_log_page_offset(req->cmd);
 	size_t data_len = nvmet_get_log_page_len(req->cmd);
@@ -246,14 +265,45 @@ static void nvmet_execute_disc_get_log_page(struct nvmet_req *req)
 		numrec++;
 	}
 
-	list_for_each_entry(p, &req->port->subsystems, entry) {
-		if (!nvmet_host_allowed(p->subsys, ctrl->hostnqn))
-			continue;
+	list_for_each_entry(r, nvmet_ports, global_entry) {
+		nvmet_set_disc_traddr(req, r, traddr);
+
+		if (!nvmet_expose_discovery_subsys()) {
+			/*
+			 * If the discovery subsystem is not exposed fall
+			 * back to the original design of only presenting
+			 * information about the port to which the controller
+			 * is connected.
+			 */
+			if (r != req->port)
+				continue;
+		} else {
+			bool linked = false;
+
+			/*
+			 * If the discovery subsystem is exposed present
+			 * information about all ports into which the
+			 * discovery subsystem is linked.
+			 */
+			list_for_each_entry(p, &r->subsystems, entry) {
+				if (p->subsys == disc_subsys) {
+					linked = true;
+					break;
+				}
+			}
+			if (!linked)
+				continue;
+		}
 
-		nvmet_format_discovery_entry(hdr, req->port,
-				p->subsys->subsysnqn, traddr,
-				p->subsys->type, numrec);
-		numrec++;
+		list_for_each_entry(p, &r->subsystems, entry) {
+			if (!nvmet_host_allowed(p->subsys, ctrl->hostnqn))
+				continue;
+
+			nvmet_format_discovery_entry(hdr, r,
+					p->subsys->subsysnqn, traddr,
+					p->subsys->type, numrec);
+			numrec++;
+		}
 	}
 
 	list_for_each_entry(r, &req->port->referrals, entry) {
-- 
2.29.2




More information about the Linux-nvme mailing list