From: Daniel Wagner <dwagner@suse.de>
Date: Thu, 2 Jun 2022 10:58:42 +0200
Subject: nvme-print: Show ANA state only for one namespace
Git-commit: cdeaab8fca6e86514b85dd285a23b8161999b75e
References: bsc#1200044 bsc#1199956 bsc#1199990

'nvme list-subsys' shows the state of all controllers belonging to a
subsystem. The ANA state is a per namespace attribute hence it only
makes sense to show it if the user lists the subsystem for a
namespace.

Fixes: 7435ed9ae6a6 ("nvme-print: Show paths from the first namespace only")
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
 nvme-print.c |   71 +++++++++++++++++++++++++++++++++--------------------------
 nvme-print.h |    3 +-
 nvme.c       |    5 ++--
 3 files changed, 45 insertions(+), 34 deletions(-)

--- a/nvme-print.c
+++ b/nvme-print.c
@@ -2373,7 +2373,8 @@ void nvme_show_supported_cap_config_log(
 	}
 }
 
-static unsigned int nvme_show_subsystem_multipath(nvme_subsystem_t s)
+static unsigned int nvme_show_subsystem_multipath(nvme_subsystem_t s,
+						  bool show_ana)
 {
 	nvme_ns_t n;
 	nvme_path_t p;
@@ -2385,13 +2386,17 @@ static unsigned int nvme_show_subsystem_
 
 	nvme_namespace_for_each_path(n, p) {
 		nvme_ctrl_t c = nvme_path_get_ctrl(p);
+		const char *ana_state = "";
+
+		if (show_ana)
+			ana_state = nvme_path_get_ana_state(p);
 
 		printf(" +- %s %s %s %s %s\n",
-		       nvme_ctrl_get_name(c),
-		       nvme_ctrl_get_transport(c),
-		       nvme_ctrl_get_address(c),
-		       nvme_ctrl_get_state(c),
-		       nvme_path_get_ana_state(p));
+			nvme_ctrl_get_name(c),
+			nvme_ctrl_get_transport(c),
+			nvme_ctrl_get_address(c),
+			nvme_ctrl_get_state(c),
+			ana_state);
 		i++;
 	}
 
@@ -2411,7 +2416,7 @@ static void nvme_show_subsystem_ctrls(nv
 	}
 }
 
-static void nvme_show_subsystem(nvme_root_t r)
+static void nvme_show_subsystem(nvme_root_t r, bool show_ana)
 {
 	nvme_host_t h;
 
@@ -2423,39 +2428,42 @@ static void nvme_show_subsystem(nvme_roo
 			       nvme_subsystem_get_nqn(s));
 			printf("\\\n");
 
-			if (!nvme_show_subsystem_multipath(s))
+			if (!nvme_show_subsystem_multipath(s, show_ana))
 				nvme_show_subsystem_ctrls(s);
 		}
 	}
 }
 
 static unsigned int json_print_nvme_subsystem_multipath(nvme_subsystem_t s,
+							bool show_ana,
 						        json_object *paths)
 {
 	nvme_ns_t n;
+	nvme_path_t p;
 	unsigned int i = 0;
 
-	nvme_subsystem_for_each_ns(s, n) {
-		nvme_path_t p;
+	n = nvme_subsystem_first_ns(s);
+	if (!n)
+		return 0;
+
+	nvme_namespace_for_each_path(n, p) {
+		struct json_object *path_attrs;
+		nvme_ctrl_t c = nvme_path_get_ctrl(p);
 
-		nvme_namespace_for_each_path(n, p) {
-			struct json_object *path_attrs;
-			nvme_ctrl_t c = nvme_path_get_ctrl(p);
-
-			path_attrs = json_create_object();
-			json_object_add_value_string(path_attrs, "Name",
-						     nvme_ctrl_get_name(c));
-			json_object_add_value_string(path_attrs, "Transport",
-						     nvme_ctrl_get_transport(c));
-			json_object_add_value_string(path_attrs, "Address",
-						     nvme_ctrl_get_address(c));
-			json_object_add_value_string(path_attrs, "State",
-						     nvme_ctrl_get_state(c));
+		path_attrs = json_create_object();
+		json_object_add_value_string(path_attrs, "Name",
+					     nvme_ctrl_get_name(c));
+		json_object_add_value_string(path_attrs, "Transport",
+					     nvme_ctrl_get_transport(c));
+		json_object_add_value_string(path_attrs, "Address",
+					     nvme_ctrl_get_address(c));
+		json_object_add_value_string(path_attrs, "State",
+					     nvme_ctrl_get_state(c));
+		if (show_ana)
 			json_object_add_value_string(path_attrs, "ANAState",
 						     nvme_path_get_ana_state(p));
-			json_array_add_value_object(paths, path_attrs);
-			i++;
-		}
+		json_array_add_value_object(paths, path_attrs);
+		i++;
 	}
 
 	return i;
@@ -2482,7 +2490,7 @@ static void json_print_nvme_subsystem_ct
 	}
 }
 
-static void json_print_nvme_subsystem_list(nvme_root_t r)
+static void json_print_nvme_subsystem_list(nvme_root_t r, bool show_ana)
 {
 	struct json_object *host_attrs, *subsystem_attrs;
 	struct json_object *subsystems, *paths;
@@ -2510,7 +2518,7 @@ static void json_print_nvme_subsystem_li
 			json_array_add_value_object(subsystems, subsystem_attrs);
 			paths = json_create_array();
 
-			if (!json_print_nvme_subsystem_multipath(s, paths))
+			if (!json_print_nvme_subsystem_multipath(s, show_ana, paths))
 				json_print_nvme_subsystem_ctrls(s, paths);
 
 			json_object_add_value_array(subsystem_attrs, "Paths",
@@ -2524,11 +2532,12 @@ static void json_print_nvme_subsystem_li
 	json_free_object(root);
 }
 
-void nvme_show_subsystem_list(nvme_root_t r, enum nvme_print_flags flags)
+void nvme_show_subsystem_list(nvme_root_t r, bool show_ana,
+			      enum nvme_print_flags flags)
 {
 	if (flags & JSON)
-		return json_print_nvme_subsystem_list(r);
-	nvme_show_subsystem(r);
+		return json_print_nvme_subsystem_list(r, show_ana);
+	nvme_show_subsystem(r, show_ana);
 }
 
 static void nvme_show_registers_cap(struct nvme_bar_cap *cap)
--- a/nvme-print.h
+++ b/nvme-print.h
@@ -87,7 +87,8 @@ void nvme_show_id_ns_descs(void *data, u
 void nvme_show_lba_status(struct nvme_lba_status *list, unsigned long len,
 	enum nvme_print_flags flags);
 void nvme_show_list_items(nvme_root_t t, enum nvme_print_flags flags);
-void nvme_show_subsystem_list(nvme_root_t t, enum nvme_print_flags flags);
+void nvme_show_subsystem_list(nvme_root_t t, bool show_ana,
+			      enum nvme_print_flags flags);
 void nvme_show_id_nvmset(struct nvme_id_nvmset_list *nvmset, unsigned nvmset_id,
 	enum nvme_print_flags flags);
 void nvme_show_primary_ctrl_cap(const struct nvme_primary_ctrl_cap *cap,
--- a/nvme.c
+++ b/nvme.c
@@ -2522,6 +2522,7 @@ static int list_subsys(int argc, char **
 	const char *verbose = "Increase output verbosity";
 	nvme_scan_filter_t filter = NULL;
 	int err;
+	int nsid = NVME_NSID_ALL;
 
 	struct config {
 		char	*output_format;
@@ -2570,7 +2571,7 @@ static int list_subsys(int argc, char **
 	}
 
 	if (devicename) {
-		int subsys_num, nsid;
+		int subsys_num;
 
 		if (sscanf(devicename,"nvme%dn%d",
 			   &subsys_num, &nsid) != 2) {
@@ -2588,7 +2589,7 @@ static int list_subsys(int argc, char **
 		goto ret;
 	}
 
-	nvme_show_subsystem_list(r, flags);
+	nvme_show_subsystem_list(r, nsid != NVME_NSID_ALL, flags);
 
 ret:
 	if (r)
