Skip to contentSkip to conversation

nvme-cli ANA update

PATCH New Hannes Reinecke 4 participants 11 messages Jul 27, 2018 – Jul 29, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover nvme-cli ANA update

Hi all,

here's a patchset to implement ANA support in nvme-cli. And also some minor fixes and cleanups.

I did not take Chaitanyas patch, as actually this is based an older patch which I never sent upstream.
Chaitanya, if you disagree I can easily drop this one and use yours instead. (But mine has JSON support :-).
And I also added support the for 'RGO' bit, and set the 'RAE' bit on per default when retrieving the ANA log page; not much point in us clearing the AEN pending bit.

As usual, comments and reviews are welcome.

Hannes Reinecke (6):
nvme-discover: sanitize options
nvme-discover: Retry discovery log if the generation counter changes
nvme-cli: Add ANA support
nvme-list-subsys: Add device name argument and print out ANA state
nvme-cli: Implement ana log page support
fabrics: display controller ID in discovery log output

 Documentation/nvme-ana-log.txt     |  62 +++++++++++++
 Documentation/nvme-discover.txt    |  13 ++-
 Documentation/nvme-list-subsys.txt |   4 +-
 fabrics.c                          |  16 +++-
 linux/nvme.h                       |  33 ++++++-
 nvme-builtin.h                     |   1 +
 nvme-ioctl.c                       |   9 ++
 nvme-ioctl.h                       |   2 +
 nvme-print.c                       | 140 +++++++++++++++++++++++++++-
 nvme-print.h                       |   2 +
 nvme.c                             | 185 +++++++++++++++++++++++++++++++++++--
 nvme.h                             |   1 +
 12 files changed, 448 insertions(+), 20 deletions(-)
 create mode 100644 Documentation/nvme-ana-log.txt
Signature · 1 line
2.13.7
#1 lore raw

PATCH 1/6 nvme-discover: sanitize options

The discovery controller doesn't accept any KATO or number of I/O queue changes, but we do want to change the reconnect delay and the controller loss timeout.

Signed-off-by Hannes Reinecke <hare at suse.com>
---
 Documentation/nvme-discover.txt | 13 ++++++++++++-
 fabrics.c                       |  4 +---
 2 files changed, 13 insertions(+), 4 deletions(-)
Documentation/nvme-discover.txt +12 -1
index 4fcf1ca..51d63e4 100644
@@ -14,7 +14,9 @@ SYNOPSIS
 		[--trsvcid=<trsvcid>      | -s <trsvcid>]
 		[--host-traddr=<traddr>   | -w <traddr>]
 		[--hostnqn=<hostnqn>      | -q <hostnqn>]
-		[--raw=<filename>         | -r <filename>]
+		[--raw=<filename>	  | -r <filename>]
+		[--reconnect-delay=<#>	  | -c <#>]
+		[--ctrl-loss-tmo=<#>	  | -l <#>]
 
 DESCRIPTION
 -----------
@@ -99,6 +101,15 @@ OPTIONS
 	and dump it to a raw binary file. By default 'nvme discover' will
 	dump the output to stdout.
 
+-c <#>::
+--reconnect-delay=<#>::
+	Overrides the default delay (in seconds) before reconnect is attempted
+	after a connect loss.
+
+-l <#>::
+--ctrl-loss-tmo=<#>::
+	Overrides the default controller loss timeout period (in seconds).
+
 EXAMPLES
 --------
 * Query the Discover Controller with IP4 address 192.168.1.3 for all
fabrics.c +1 -3
index 9aee8f8..ca8aaf7 100644
@@ -820,12 +820,10 @@ int discover(const char *desc, int argc, char **argv, bool connect)
 		{"host-traddr", 'w', "LIST", CFG_STRING, &cfg.host_traddr, required_argument, "host traddr (e.g. FC WWN's)" },
 		{"hostnqn",     'q', "LIST", CFG_STRING, &cfg.hostnqn,     required_argument, "user-defined hostnqn (if default not used)" },
 		{"hostid",      'I', "LIST", CFG_STRING, &cfg.hostid,      required_argument, "user-defined hostid (if default not used)"},
-		{"queue-size",  'Q', "LIST", CFG_STRING, &cfg.queue_size,  required_argument, "number of io queue elements to use (default 128)" },
-		{"nr-io-queues",'i', "LIST", CFG_STRING, &cfg.nr_io_queues,required_argument, "number of io queues to use (default is core count)" },
 		{"raw",         'r', "LIST", CFG_STRING, &cfg.raw,         required_argument, "raw output file" },
 		{"keep-alive-tmo",  'k', "LIST", CFG_STRING, &cfg.keep_alive_tmo,  required_argument, "keep alive timeout period in seconds" },
+		{"reconnect-delay", 'c', "LIST", CFG_STRING, &cfg.reconnect_delay, required_argument, "reconnect timeout period in seconds" },
 		{"ctrl-loss-tmo",   'l', "LIST", CFG_STRING, &cfg.ctrl_loss_tmo,   required_argument, "controller loss timeout period in seconds" },
-
 		{NULL},
 	};
 
Signature · 1 line
2.13.7
#2 lore raw

PATCH 2/6 nvme-discover: Retry discovery log if the generation counter changes

In reply to Hannes Reinecke

If the generation counter changes we need to validate if the number of records has changed, too.
If so we need to retry retrieving the discovery log to the most recent values. The retry will be terminated after MAX_DISC_RETRIES (currently set to 30) to avoid infinite recursion.

Signed-off-by Hannes Reinecke <hare at suse.com>
---
 fabrics.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
fabrics.c +9 -2
index ca8aaf7..b1219a0 100644
@@ -71,6 +71,7 @@ static struct config {
 #define PATH_NVMF_HOSTID	"/etc/nvme/hostid"
 #define SYS_NVME		"/sys/class/nvme"
 #define MAX_DISC_ARGS		10
+#define MAX_DISC_RETRIES	30
 
 enum {
 	OPT_INSTANCE,
@@ -281,7 +282,7 @@ static int nvmf_get_log_page_discovery(const char *dev_path,
 	struct nvmf_disc_rsp_page_hdr *log;
 	unsigned int log_size = 0;
 	unsigned long genctr;
-	int error, fd;
+	int error, fd, max_retries = MAX_DISC_RETRIES, retries = 0;
 
 	fd = open(dev_path, O_RDWR);
 	if (fd < 0) {
@@ -311,6 +312,7 @@ static int nvmf_get_log_page_discovery(const char *dev_path,
 		goto out_free_log;
 	}
 
+retry_log:
 	/* check numrec limits */
 	*numrec = le64_to_cpu(log->numrec);
 	genctr = le64_to_cpu(log->genctr);
@@ -346,7 +348,12 @@ static int nvmf_get_log_page_discovery(const char *dev_path,
 		goto out_free_log;
 	}
 
-	if (*numrec != le32_to_cpu(log->numrec) || genctr != le64_to_cpu(log->genctr)) {
+	if (genctr != le64_to_cpu(log->genctr) &&
+	    *numrec != le32_to_cpu(log->numrec) &&
+	    ++retries < max_retries)
+		goto retry_log;
+
+	if (*numrec != le32_to_cpu(log->numrec)) {
 		error = DISC_NOT_EQUAL;
 		goto out_free_log;
 	}
Signature · 1 line
2.13.7
#3 lore raw

PATCH 3/6 nvme-cli: Add ANA support

In reply to Hannes Reinecke

Decode additional fields specified in the ANA TP.

Signed-off-by Hannes Reinecke <hare at suse.com>
---
 linux/nvme.h | 14 +++++++++++---
 nvme-print.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 53 insertions(+), 5 deletions(-)
linux/nvme.h +11 -3
index dc8ea89..55a197b 100644
@@ -241,7 +241,12 @@ struct nvme_id_ctrl {
 	__le32			hmminds;
 	__le16			hmmaxd;
 	__le16			nsetidmax;
-	__u8			rsvd340[172];
+	__u8			rsvd340[2];
+	__u8			anatt;
+	__u8			anacap;
+	__le32			anagrpmax;
+	__le32			nanagrpid;
+	__u8			rsvd352[160];
 	__u8			sqes;
 	__u8			cqes;
 	__le16			maxcmd;
@@ -257,7 +262,8 @@ struct nvme_id_ctrl {
 	__le16			acwu;
 	__u8			rsvd534[2];
 	__le32			sgls;
-	__u8			rsvd540[228];
+	__le32			mnan;
+	__u8			rsvd544[224];
 	char			subnqn[256];
 	__u8			rsvd1024[768];
 	__le32			ioccsz;
@@ -317,7 +323,9 @@ struct nvme_id_ns {
 	__le16			nabspf;
 	__le16			noiob;
 	__u8			nvmcap[16];
-	__u8			rsvd64[36];
+	__u8			rsvd64[28];
+	__le32			anagrpid;
+	__u8			rsvd96[4];
 	__le16			nvmsetid;
 	__le16			endgid;
 	__u8			nguid[16];
nvme-print.c +42 -2

78 lines not on this page · raw message

Signature · 1 line
2.13.7
#4 lore raw

PATCH 4/6 nvme-list-subsys: Add device name argument and print out ANA state

In reply to Hannes Reinecke

Update the 'nvme list-subsys' command to accept a device name and print out the ANA state for all paths to that device.

Signed-off-by Hannes Reinecke <hare at suse.com>
---
 Documentation/nvme-list-subsys.txt |   4 +-
 nvme-print.c                       |  10 +++-
 nvme.c                             | 115 +++++++++++++++++++++++++++++++++++--
 nvme.h                             |   1 +
 4 files changed, 121 insertions(+), 9 deletions(-)
Documentation/nvme-list-subsys.txt +3 -1
index c7de7ef..c40b708 100644
@@ -8,12 +8,14 @@ nvme-list-subsys - List all NVMe subsystems
 SYNOPSIS
 --------
 [verse]
-'nvme list-subsys' [-o <fmt> | --output-format=<fmt>]
+'nvme list-subsys' [-o <fmt> | --output-format=<fmt>] <device>
 
 DESCRIPTION
 -----------
 Scan the sysfs tree for NVM Express subsystems and return the controllers
 for those subsystems as well as some pertinent information about them.
+If a device is given, print out only the values for the controllers
+and subsystems leading to the device.
 
 OPTIONS
 -------
nvme-print.c +8 -2
index 692c903..e4c90bf 100644
@@ -2579,9 +2579,11 @@ static void show_nvme_subsystem(struct subsys_list_item *item)
 	printf("\\\n");
 
 	for (i = 0; i < item->nctrls; i++) {
-		printf(" +- %s %s %s\n", item->ctrls[i].name,
+		printf(" +- %s %s %s %s\n", item->ctrls[i].name,
 				item->ctrls[i].transport,
-				item->ctrls[i].address);
+				item->ctrls[i].address,
+				item->ctrls[i].ana_state ?
+					item->ctrls[i].ana_state : "");
 	}
 
 }
@@ -2627,6 +2629,10 @@ void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n)
 					slist[i].ctrls[j].transport);
 			json_object_add_value_string(path_attrs, "Address",
 					slist[i].ctrls[j].address);
+			if (slist[i].ctrls[j].ana_state)
+				json_object_add_value_string(path_attrs,
+						"State",
+						slist[i].ctrls[j].ana_state);
 			json_array_add_value_object(paths, path_attrs);
 		}
 		if (j) {
nvme.c +109 -6

170 lines not on this page · raw message

nvme.h +1 -0
index 5098b0e..26d5b85 100644
@@ -129,6 +129,7 @@ struct ctrl_list_item {
 	char *name;
 	char *address;
 	char *transport;
+	char *ana_state;
 };
 
 struct subsys_list_item {
Signature · 1 line
2.13.7
#5 lore raw

PATCH 5/6 nvme-cli: Implement ana log page support

In reply to Hannes Reinecke
Signed-off-by Hannes Reinecke <hare at suse.com>
---
 Documentation/nvme-ana-log.txt | 62 ++++++++++++++++++++++++++++++
 linux/nvme.h                   | 19 ++++++++++
 nvme-builtin.h                 |  1 +
 nvme-ioctl.c                   |  9 +++++
 nvme-ioctl.h                   |  2 +
 nvme-print.c                   | 86 ++++++++++++++++++++++++++++++++++++++++++
 nvme-print.h                   |  2 +
 nvme.c                         | 70 ++++++++++++++++++++++++++++++++++
 8 files changed, 251 insertions(+)
 create mode 100644 Documentation/nvme-ana-log.txt
Documentation/nvme-ana-log.txt new file +62 -0
new file mode 100644
index 0000000..6ef33e7
@@ -0,0 +1,62 @@
+nvme-ana-log(1)
+===============
+
+NAME
+----
+nvme-ana-log - Send NVME ANA log page request, return result and log
+
+SYNOPSIS
+--------
+[verse]
+'nvme ana-log' <device> [--log-size=<size> | -l <size> ]
+			[--raw-binary | -b ]
+			[--output-format=<fmt> | -o <fmt> ]
+
+DESCRIPTION
+-----------
+Retrieves NVMe Asymmetric Namespace Access (ANA) log page from and
+NVMe device and prints the returned structure.
+
+The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).
+
+On success, the returned ANA log struct may be returned in one of several
+ways depending on the option flags; the structure may be parsed by the
+program and printed in readable format or the raw buffer may be printed to
+stdout for another program to parse.
+
+OPTIONS
+-------
+-l <size>::
+--log-size=<size>::
+	Specify the size of the ANA log buffer.
+
+-b::
+--raw-binary::
+	Print the raw error log buffer to stdout.
+
+-o <format>::
+--output-format=<format>::
+	Set the reporting format to 'normal', 'json', or 'binary'.
+	Only one output formath can be used at a time.
+
+EXAMPLES
+--------
+* Get the ANA log and print it in a humen readable format:
+*
+------------
+# nvme ana-log /dev/nvme0
+------------
++
+
+* Print the raw output to a file:
++
+------------
+# nvme ana-log /dev/nvme0 --raw-binary > ana_log.raw
+------------
++
+It is probably a bad idea to not redirect stdout when using this mode.
+
+NVME
+----
+Part of the nvme-user suite
linux/nvme.h +19 -0
index 55a197b..645e171 100644
@@ -889,6 +889,7 @@ enum {
 	NVME_LOG_TELEMETRY_HOST = 0x07,
 	NVME_LOG_TELEMETRY_CTRL = 0x08,
 	NVME_LOG_ENDURANCE_GROUP = 0x09,
+	NVME_LOG_ANA		= 0x0c,
 	NVME_LOG_DISC		= 0x70,
 	NVME_LOG_RESERVATION	= 0x80,
 	NVME_LOG_SANITIZE	= 0x81,
@@ -901,6 +902,7 @@ enum {
 	NVME_NO_LOG_LSP       = 0x0,
 	NVME_NO_LOG_LPO       = 0x0,
 	NVME_TELEM_LSP_CREATE = 0x1,
+	NVME_ANA_LSP_RGO      = 0x1,
 };
 
 /* Sanitize and Sanitize Monitor/Log */
@@ -1085,6 +1087,23 @@ struct nvme_sanitize_log_page {
 	__le32			est_crypto_erase_time;
 };
 
+/* Asymmetric Namespace Access Log Page */
+struct nvme_ana_group_descriptor {
+	__le32			groupid;
+	__le32			nsid_num;
+	__le64			change_count;
+	__u8			ana_state;
+	__u8			resv1[7];
+	__le32			nsid[0];
+};
+
+struct nvme_ana_log_page {
+	__le64			change_count;
+	__le16			grpid_num;
+	__le16			resv[3];
+	struct nvme_ana_group_descriptor desc[0];
+};
+
 /*
  * Fabrics subcommands.
  */
nvme-builtin.h +1 -0
index 2c26d57..df3eb4f 100644
@@ -28,6 +28,7 @@ COMMAND_LIST(
 	ENTRY("error-log", "Retrieve Error Log, show it", get_error_log)
 	ENTRY("effects-log", "Retrieve Command Effects Log, show it", get_effects_log)
 	ENTRY("endurance-log", "Retrieve Endurance Group Log, show it", get_endurance_log)
+	ENTRY("ana-log", "Retrieve ANA Log, show it", ana_log)
 	ENTRY("get-feature", "Get feature and show the resulting value", get_feature)
 	ENTRY("device-self-test", "Perform the necessary tests to observe the performance", device_self_test)
 	ENTRY("self-test-log", "Retrieve the SELF-TEST Log, show it", self_test_log)
nvme-ioctl.c +9 -0
index 9cf2a33..f88909d 100644
@@ -488,6 +488,15 @@ int nvme_sanitize_log(int fd, struct nvme_sanitize_log_page *sanitize_log)
 	return nvme_get_log(fd, 0, NVME_LOG_SANITIZE, sizeof(*sanitize_log), sanitize_log);
 }
 
+int nvme_ana_log(int fd, bool rgo, struct nvme_ana_log_page *ana_log,
+		 ssize_t ana_log_size)
+{
+	return nvme_get_log13(fd, 0, NVME_LOG_ANA,
+			      rgo ? NVME_ANA_LSP_RGO : NVME_NO_LOG_LSP,
+			      NVME_NO_LOG_LPO, 0, 1,
+			      ana_log_size, ana_log);
+}
+
 int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11,
 		 __u32 cdw12, __u32 data_len, void *data, __u32 *result)
 {
nvme-ioctl.h +2 -0
index b34f5de..9527cc3 100644
@@ -97,6 +97,8 @@ int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size);
 int nvme_sanitize_log(int fd, struct nvme_sanitize_log_page *sanitize_log);
 int nvme_endurance_log(int fd, __u16 group_id,
 		       struct nvme_endurance_group_log *endurance_log);
+int nvme_ana_log(int fd, bool rgo, struct nvme_ana_log_page *ana_log,
+		 ssize_t ana_log_size);
 
 int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10,
 		 __u32 cdw11, __u32 cdw12, __u32 data_len, void *data,
nvme-print.c +86 -0

98 lines not on this page · raw message

nvme-print.h +2 -0
index da287c2..b3d16dc 100644
@@ -31,6 +31,7 @@ void show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, const char *
 void show_endurance_log(struct nvme_endurance_group_log *endurance_group,
 			__u16 group_id, const char *devname);
 void show_sanitize_log(struct nvme_sanitize_log_page *sanitize, unsigned int mode, const char *devname);
+void show_ana_log(struct nvme_ana_log_page *ana, const char *devname);
 void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics);
 void show_single_property(int offset, uint64_t prop, int human);
 void show_nvme_id_ns_descs(void *data);
@@ -56,6 +57,7 @@ void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname);
 void json_changed_ns_list_log(struct nvme_changed_ns_list_log *log, const char *devname);
 void json_endurance_log(struct nvme_endurance_group_log *endurance_group,
 			__u16 group_id, const char *devname);
+void json_ana_log(struct nvme_ana_log_page *ana_log);
 void json_print_list_items(struct list_item *items, unsigned amnt);
 void json_nvme_id_ns_descs(void *data);
 void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n);
nvme.c +70 -0

76 lines not on this page · raw message

Signature · 1 line
2.13.7
#6 lore raw

PATCH 5/6 nvme-cli: Implement ana log page support

Chaitanya already sent a patch for this two days ago..

Quoted 377 lines · Hannes Reinecke
Signed-off-by Hannes Reinecke <hare at suse.com>
---
 Documentation/nvme-ana-log.txt | 62 ++++++++++++++++++++++++++++++
 linux/nvme.h                   | 19 ++++++++++
 nvme-builtin.h                 |  1 +
 nvme-ioctl.c                   |  9 +++++
 nvme-ioctl.h                   |  2 +
 nvme-print.c                   | 86 ++++++++++++++++++++++++++++++++++++++++++
 nvme-print.h                   |  2 +
 nvme.c                         | 70 ++++++++++++++++++++++++++++++++++
 8 files changed, 251 insertions(+)
 create mode 100644 Documentation/nvme-ana-log.txt
Documentation/nvme-ana-log.txt new file +62 -0
new file mode 100644
index 0000000..6ef33e7
@@ -0,0 +1,62 @@
+nvme-ana-log(1)
+===============
+
+NAME
+----
+nvme-ana-log - Send NVME ANA log page request, return result and log
+
+SYNOPSIS
+--------
+[verse]
+'nvme ana-log' <device> [--log-size=<size> | -l <size> ]
+			[--raw-binary | -b ]
+			[--output-format=<fmt> | -o <fmt> ]
+
+DESCRIPTION
+-----------
+Retrieves NVMe Asymmetric Namespace Access (ANA) log page from and
+NVMe device and prints the returned structure.
+
+The <device> parameter is mandatory and may be either the NVMe character
+device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).
+
+On success, the returned ANA log struct may be returned in one of several
+ways depending on the option flags; the structure may be parsed by the
+program and printed in readable format or the raw buffer may be printed to
+stdout for another program to parse.
+
+OPTIONS
+-------
+-l <size>::
+--log-size=<size>::
+	Specify the size of the ANA log buffer.
+
+-b::
+--raw-binary::
+	Print the raw error log buffer to stdout.
+
+-o <format>::
+--output-format=<format>::
+	Set the reporting format to 'normal', 'json', or 'binary'.
+	Only one output formath can be used at a time.
+
+EXAMPLES
+--------
+* Get the ANA log and print it in a humen readable format:
+*
+------------
+# nvme ana-log /dev/nvme0
+------------
++
+
+* Print the raw output to a file:
++
+------------
+# nvme ana-log /dev/nvme0 --raw-binary > ana_log.raw
+------------
++
+It is probably a bad idea to not redirect stdout when using this mode.
+
+NVME
+----
+Part of the nvme-user suite
linux/nvme.h +19 -0
index 55a197b..645e171 100644
@@ -889,6 +889,7 @@ enum {
 	NVME_LOG_TELEMETRY_HOST = 0x07,
 	NVME_LOG_TELEMETRY_CTRL = 0x08,
 	NVME_LOG_ENDURANCE_GROUP = 0x09,
+	NVME_LOG_ANA		= 0x0c,
 	NVME_LOG_DISC		= 0x70,
 	NVME_LOG_RESERVATION	= 0x80,
 	NVME_LOG_SANITIZE	= 0x81,
@@ -901,6 +902,7 @@ enum {
 	NVME_NO_LOG_LSP       = 0x0,
 	NVME_NO_LOG_LPO       = 0x0,
 	NVME_TELEM_LSP_CREATE = 0x1,
+	NVME_ANA_LSP_RGO      = 0x1,
 };
 
 /* Sanitize and Sanitize Monitor/Log */
@@ -1085,6 +1087,23 @@ struct nvme_sanitize_log_page {
 	__le32			est_crypto_erase_time;
 };
 
+/* Asymmetric Namespace Access Log Page */
+struct nvme_ana_group_descriptor {
+	__le32			groupid;
+	__le32			nsid_num;
+	__le64			change_count;
+	__u8			ana_state;
+	__u8			resv1[7];
+	__le32			nsid[0];
+};
+
+struct nvme_ana_log_page {
+	__le64			change_count;
+	__le16			grpid_num;
+	__le16			resv[3];
+	struct nvme_ana_group_descriptor desc[0];
+};
+
 /*
  * Fabrics subcommands.
  */
nvme-builtin.h +1 -0
index 2c26d57..df3eb4f 100644
@@ -28,6 +28,7 @@ COMMAND_LIST(
 	ENTRY("error-log", "Retrieve Error Log, show it", get_error_log)
 	ENTRY("effects-log", "Retrieve Command Effects Log, show it", get_effects_log)
 	ENTRY("endurance-log", "Retrieve Endurance Group Log, show it", get_endurance_log)
+	ENTRY("ana-log", "Retrieve ANA Log, show it", ana_log)
 	ENTRY("get-feature", "Get feature and show the resulting value", get_feature)
 	ENTRY("device-self-test", "Perform the necessary tests to observe the performance", device_self_test)
 	ENTRY("self-test-log", "Retrieve the SELF-TEST Log, show it", self_test_log)
nvme-ioctl.c +9 -0
index 9cf2a33..f88909d 100644
@@ -488,6 +488,15 @@ int nvme_sanitize_log(int fd, struct nvme_sanitize_log_page *sanitize_log)
 	return nvme_get_log(fd, 0, NVME_LOG_SANITIZE, sizeof(*sanitize_log), sanitize_log);
 }
 
+int nvme_ana_log(int fd, bool rgo, struct nvme_ana_log_page *ana_log,
+		 ssize_t ana_log_size)
+{
+	return nvme_get_log13(fd, 0, NVME_LOG_ANA,
+			      rgo ? NVME_ANA_LSP_RGO : NVME_NO_LOG_LSP,
+			      NVME_NO_LOG_LPO, 0, 1,
+			      ana_log_size, ana_log);
+}
+
 int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11,
 		 __u32 cdw12, __u32 data_len, void *data, __u32 *result)
 {
nvme-ioctl.h +2 -0
index b34f5de..9527cc3 100644
@@ -97,6 +97,8 @@ int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size);
 int nvme_sanitize_log(int fd, struct nvme_sanitize_log_page *sanitize_log);
 int nvme_endurance_log(int fd, __u16 group_id,
 		       struct nvme_endurance_group_log *endurance_log);
+int nvme_ana_log(int fd, bool rgo, struct nvme_ana_log_page *ana_log,
+		 ssize_t ana_log_size);
 
 int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10,
 		 __u32 cdw11, __u32 cdw12, __u32 data_len, void *data,
nvme-print.c +86 -0
index e4c90bf..487ea44 100644
@@ -1508,6 +1508,45 @@ void show_sanitize_log(struct nvme_sanitize_log_page *sanitize, unsigned int mod
 	printf("Estimated Time For Crypto Erase               :  %u\n", le32_to_cpu(sanitize->est_crypto_erase_time));
 }
 
+static char *nvme_ana_state_to_string(uint8_t ana_state)
+{
+	switch (ana_state & 0x0f) {
+	case 0x1: return "optimized";
+	case 0x2: return "non-optimized";
+	case 0x3: return "inaccessible";
+	case 0x4: return "persistent-loss";
+	case 0xf: return "change-state";
+	default: return "reserved";
+	}
+}
+
+void show_ana_log(struct nvme_ana_log_page *ana, const char *devname)
+{
+	int grpid_num = le16_to_cpu(ana->grpid_num), i, j;
+	unsigned char *p;
+
+	printf("ANA Log page for device:%s\n", devname);
+	printf("desc_num : %d\n", grpid_num);
+	printf("chgcnt   : %"PRIu64"\n",
+	       (uint64_t)le64_to_cpu(ana->change_count));
+	p = (unsigned char *)&ana->desc[0];
+	for (i = 0; i < grpid_num; i++) {
+		struct nvme_ana_group_descriptor *desc =
+			(struct nvme_ana_group_descriptor *)p;
+		int nsid_num = le32_to_cpu(desc->nsid_num);
+		printf(" desc[%d] :\n", i);
+		printf("  groupid  : %x\n", le32_to_cpu(desc->groupid));
+		printf("  nsid_num : %d\n", nsid_num);
+		printf("  chgcnt   : %"PRId64"\n",
+		       (uint64_t)le64_to_cpu(desc->change_count));
+		printf("  state    : %s\n",
+		       nvme_ana_state_to_string(desc->ana_state));
+		for (j = 0; j < nsid_num; j++)
+			printf("    nsid[%d] : %x\n", j, le32_to_cpu(desc->nsid[j]));
+		p += sizeof(*desc) + nsid_num * 4;
+	}
+}
+
 char *nvme_feature_to_string(int feature)
 {
 	switch (feature) {
@@ -2571,6 +2610,53 @@ void json_sanitize_log(struct nvme_sanitize_log_page *sanitize_log, const char *
 	json_free_object(root);
 }
 
+void json_ana_log(struct nvme_ana_log_page *ana_log)
+{
+	struct json_object *root;
+	struct json_array *ags;
+	unsigned char *p;
+	int grpid_num = le32_to_cpu(ana_log->grpid_num);
+	int i, j;
+
+	root = json_create_object();
+
+	json_object_add_value_int(root, "chgcnt", le64_to_cpu(ana_log->change_count));
+	json_object_add_value_int(root, "desc_num", grpid_num);
+	ags = json_create_array();
+	p = (unsigned char *)&ana_log->desc[0];
+	for (i = 0; i < grpid_num; i++) {
+		struct nvme_ana_group_descriptor *desc =
+			(struct nvme_ana_group_descriptor *)p;
+		struct json_object *ag = json_create_object();
+		struct json_array *nsids;
+		int nsid_num = le32_to_cpu(desc->nsid_num);
+
+		json_object_add_value_int(ag, "groupid", le32_to_cpu(desc->groupid));
+		json_object_add_value_int(ag, "nsid_num", nsid_num);
+		json_object_add_value_int(ag, "chgcnt", le64_to_cpu(desc->change_count));
+		json_object_add_value_string(ag, "state",
+			nvme_ana_state_to_string(desc->ana_state));
+
+		nsids = json_create_array();
+		for (j = 0; j < nsid_num; j++) {
+			struct json_object *nsid = json_create_object();
+
+			json_object_add_value_int(nsid, "nsid", desc->nsid[j]);
+			json_array_add_value_object(nsids, nsid);
+		}
+		if (j)
+			json_object_add_value_array(ag, "nsids", nsids);
+		json_array_add_value_object(ags, ag);
+
+		p += sizeof(*desc) + nsid_num * 4;
+	}
+	if (i)
+		json_object_add_value_array(root, "group_descriptors", ags);
+	json_print_object(root, NULL);
+	printf("\n");
+	json_free_object(root);
+}
+
 static void show_nvme_subsystem(struct subsys_list_item *item)
 {
 	int i;
nvme-print.h +2 -0
index da287c2..b3d16dc 100644
@@ -31,6 +31,7 @@ void show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, const char *
 void show_endurance_log(struct nvme_endurance_group_log *endurance_group,
 			__u16 group_id, const char *devname);
 void show_sanitize_log(struct nvme_sanitize_log_page *sanitize, unsigned int mode, const char *devname);
+void show_ana_log(struct nvme_ana_log_page *ana, const char *devname);
 void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics);
 void show_single_property(int offset, uint64_t prop, int human);
 void show_nvme_id_ns_descs(void *data);
@@ -56,6 +57,7 @@ void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname);
 void json_changed_ns_list_log(struct nvme_changed_ns_list_log *log, const char *devname);
 void json_endurance_log(struct nvme_endurance_group_log *endurance_group,
 			__u16 group_id, const char *devname);
+void json_ana_log(struct nvme_ana_log_page *ana_log);
 void json_print_list_items(struct list_item *items, unsigned amnt);
 void json_nvme_id_ns_descs(void *data);
 void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n);
nvme.c +70 -0
index 74dfb61..e463efc 100644
@@ -824,6 +824,76 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p
 	return ret;
 }
 
+static int ana_log(int argc, char **argv, struct command *command, struct plugin *plugin)
+{
+	const char *desc = "Retrieve ANA log and show it.";
+	const char *raw_binary = "show infos in binary format";
+	const char *log_size = "Size of the ANA log page";
+	const char *rgo = "Retrieve ANA Group Descriptors only";
+	int fd;
+	int ret;
+	int fmt;
+	struct nvme_ana_log_page *ana_log;
+
+	struct config {
+		int   raw_binary;
+		char *output_format;
+		size_t log_size;
+		int rgo;
+	};
+
+	struct config cfg = {
+		.output_format = "normal",
+		.log_size = 4096,
+	};
+
+	const struct argconfig_commandline_options command_line_options[] = {
+		{"output-format", 'o', "FMT", CFG_STRING,   &cfg.output_format, required_argument, output_format},
+		{"raw-binary",    'b', "",    CFG_NONE,     &cfg.raw_binary,    no_argument,       raw_binary},
+		{"log-size",      'l', "NUM", CFG_POSITIVE, &cfg.log_size,    required_argument,  log_size},
+		{"groups-only",   'r', "",    CFG_NONE,     &cfg.rgo,         no_argument,        rgo},
+		{NULL}
+	};
+
+	fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg));
+	if (fd < 0)
+		return fd;
+	ana_log = calloc(cfg.log_size, sizeof(char));
+	if (!ana_log) {
+		fprintf(stderr, "could not allocate buffer for ANA log\n");
+		ret = ENOMEM;
+		goto close_fd;
+	}
+	fmt = validate_output_format(cfg.output_format);
+	if (fmt < 0) {
+		ret = fmt;
+		goto close_fd_and_free;
+	}
+	if (cfg.raw_binary)
+		fmt = BINARY;
+
+	ret = nvme_ana_log(fd, cfg.rgo, ana_log, cfg.log_size);
+	if (!ret) {
+		if (fmt == BINARY)
+			d_raw((unsigned char *)ana_log, cfg.log_size);
+		else if (fmt == JSON)
+			json_ana_log(ana_log);
+		else
+			show_ana_log(ana_log, devicename);
+	}
+	else if (ret > 0)
+		fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+	else
+		perror("ana status log");
+
+close_fd_and_free:
+	free(ana_log);
+ close_fd:
+	close(fd);
+
+	return ret;
+}
+
 static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
 	const char *desc = "Show controller list information for the subsystem the "\
Signature · 1 line
2.13.7

---end quoted text---

#7 lore raw

PATCH 5/6 nvme-cli: Implement ana log page support

Quoted 2 lines · Christoph Hellwig

Chaitanya already sent a patch for this two days ago..

I sort of hinted at that in the cover letter.
This patch was done quite some time ago, and I was to lazy to rework the patch series.
Plus it actually has json support, which was missing from Chaitanyas patch.

I don't mind with way to go; drop my patch, have my patchset updated to include Chaitanyas, drop Chaitanyas, whatever.
Just say the word.

Cheers,

Hannes

#8 lore raw

PATCH 5/6 nvme-cli: Implement ana log page support

From: Hannes Reinecke <[email protected]>
Sent: Saturday, July 28, 2018 7:14 AM
To: Christoph Hellwig
Cc: Hannes Reinecke; Sagi Grimberg; Chaitanya Kulkarni; linux-nvme at lists.infradead.org; Keith Busch; Johannes Thumshirn
Subject: Re: [PATCH 5/6] nvme-cli: Implement ana log page support
?

Quoted 2 lines · Christoph Hellwig

Chaitanya already sent a patch for this two days ago..

I sort of hinted at that in the cover letter.
This patch was done quite some time ago, and I was to lazy to rework the patch series.
Plus it actually has json support, which was missing from Chaitanyas patch.

[CK] Yes, it was missing from 1st version, however, please have a look at V2 with JSON support posted on Wed Jul 25.

http://lists.infradead.org/pipermail/linux-nvme/2018-July/019471.html.

Maybe we can integrate your patches on the top of above series?

I don't mind with way to go; drop my patch, have my patchset updated to include Chaitanyas, drop Chaitanyas, whatever.
Just say the word.

Cheers,

Hannes

#9 lore raw

PATCH 5/6 nvme-cli: Implement ana log page support

Quoted 16 lines · Chaitanya Kulkarni

From: Hannes Reinecke <hare at suse.de>
Sent: Saturday, July 28, 2018 7:14 AM
To: Christoph Hellwig
Cc: Hannes Reinecke; Sagi Grimberg; Chaitanya Kulkarni; linux-nvme at lists.infradead.org; Keith Busch; Johannes Thumshirn
Subject: Re: [PATCH 5/6] nvme-cli: Implement ana log page support

Quoted 2 lines · Christoph Hellwig

Chaitanya already sent a patch for this two days ago..

I sort of hinted at that in the cover letter.
This patch was done quite some time ago, and I was to lazy to rework the patch series.
Plus it actually has json support, which was missing from Chaitanyas patch.

Quoted 6 lines

[CK] Yes, it was missing from 1st version, however, please have a look at V2 with JSON support posted on Wed Jul 25.

http://lists.infradead.org/pipermail/linux-nvme/2018-July/019471.html.

Maybe we can integrate your patches on the top of above series?

Ok, will be doing so.

Cheers,

Hannes

#10 lore raw

PATCH 6/6 fabrics: display controller ID in discovery log output

In reply to Hannes Reinecke

To figure out if a subsystem supports the static or dynamic controller model we need to display the controller ID in the discovery log output.

Signed-off-by Hannes Reinecke <hare at suse.com>
---
 fabrics.c | 1 +
 1 file changed, 1 insertion(+)
fabrics.c +1 -0
index b1219a0..8601001 100644
@@ -399,6 +399,7 @@ static void print_discovery_log(struct nvmf_disc_rsp_page_hdr *log, int numrec)
 		printf("subtype: %s\n", subtype_str(e->subtype));
 		printf("treq:    %s\n", treq_str(e->treq));
 		printf("portid:  %d\n", e->portid);
+		printf("cntlid:  %x\n", e->cntlid);
 		printf("trsvcid: %.*s\n",
 		       space_strip_len(NVMF_TRSVCID_SIZE, e->trsvcid),
 		       e->trsvcid);
Signature · 1 line
2.13.7