All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] nvme-cli ANA update
@ 2018-07-27 10:26 Hannes Reinecke
  2018-07-27 10:26 ` [PATCH 1/6] nvme-discover: sanitize options Hannes Reinecke
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Hannes Reinecke @ 2018-07-27 10:26 UTC (permalink / raw)


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

-- 
2.13.7

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/6] nvme-discover: sanitize options
  2018-07-27 10:26 [PATCH 0/6] nvme-cli ANA update Hannes Reinecke
@ 2018-07-27 10:26 ` Hannes Reinecke
  2018-07-27 10:26 ` [PATCH 2/6] nvme-discover: Retry discovery log if the generation counter changes Hannes Reinecke
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Hannes Reinecke @ 2018-07-27 10:26 UTC (permalink / raw)


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(-)

diff --git a/Documentation/nvme-discover.txt b/Documentation/nvme-discover.txt
index 4fcf1ca..51d63e4 100644
--- a/Documentation/nvme-discover.txt
+++ b/Documentation/nvme-discover.txt
@@ -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
diff --git a/fabrics.c b/fabrics.c
index 9aee8f8..ca8aaf7 100644
--- a/fabrics.c
+++ b/fabrics.c
@@ -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},
 	};
 
-- 
2.13.7

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/6] nvme-discover: Retry discovery log if the generation counter changes
  2018-07-27 10:26 [PATCH 0/6] nvme-cli ANA update Hannes Reinecke
  2018-07-27 10:26 ` [PATCH 1/6] nvme-discover: sanitize options Hannes Reinecke
@ 2018-07-27 10:26 ` Hannes Reinecke
  2018-07-27 10:26 ` [PATCH 3/6] nvme-cli: Add ANA support Hannes Reinecke
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Hannes Reinecke @ 2018-07-27 10:26 UTC (permalink / raw)


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(-)

diff --git a/fabrics.c b/fabrics.c
index ca8aaf7..b1219a0 100644
--- a/fabrics.c
+++ b/fabrics.c
@@ -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;
 	}
-- 
2.13.7

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/6] nvme-cli: Add ANA support
  2018-07-27 10:26 [PATCH 0/6] nvme-cli ANA update Hannes Reinecke
  2018-07-27 10:26 ` [PATCH 1/6] nvme-discover: sanitize options Hannes Reinecke
  2018-07-27 10:26 ` [PATCH 2/6] nvme-discover: Retry discovery log if the generation counter changes Hannes Reinecke
@ 2018-07-27 10:26 ` Hannes Reinecke
  2018-07-27 10:26 ` [PATCH 4/6] nvme-list-subsys: Add device name argument and print out ANA state Hannes Reinecke
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Hannes Reinecke @ 2018-07-27 10:26 UTC (permalink / raw)


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(-)

diff --git a/linux/nvme.h b/linux/nvme.h
index dc8ea89..55a197b 100644
--- a/linux/nvme.h
+++ b/linux/nvme.h
@@ -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];
diff --git a/nvme-print.c b/nvme-print.c
index daf2929..692c903 100644
--- a/nvme-print.c
+++ b/nvme-print.c
@@ -78,12 +78,14 @@ static void format(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz)
 
 static void show_nvme_id_ctrl_cmic(__u8 cmic)
 {
-	__u8 rsvd = (cmic & 0xF8) >> 3;
+	__u8 rsvd = (cmic & 0xF0) >> 4;
+	__u8 ana = (cmic & 0x8) >> 3;
 	__u8 sriov = (cmic & 0x4) >> 2;
 	__u8 mctl = (cmic & 0x2) >> 1;
 	__u8 mp = cmic & 0x1;
 	if (rsvd)
-		printf("  [7:3] : %#x\tReserved\n", rsvd);
+		printf("  [7:4] : %#x\tReserved\n", rsvd);
+	printf("  [3:3] : %#x\tANA %ssupported\n", ana, ana ? "" : "not ");
 	printf("  [2:2] : %#x\t%s\n", sriov, sriov ? "SR-IOV" : "PCI");
 	printf("  [1:1] : %#x\t%s Controller\n",
 		mctl, mctl ? "Multi" : "Single");
@@ -283,6 +285,36 @@ static void show_nvme_id_ctrl_sanicap(__le32 ctrl_sanicap)
 	printf("\n");
 }
 
+static void show_nvme_id_ctrl_anacap(__u8 anacap)
+{
+	__u8 nz = (anacap & 0x80) >> 7;
+	__u8 grpid_change = (anacap & 0x40) >> 6;
+	__u8 rsvd = (anacap & 0x20) >> 5;
+	__u8 ana_change = (anacap & 0x10) >> 4;
+	__u8 ana_persist_loss = (anacap & 0x08) >> 3;
+	__u8 ana_inaccessible = (anacap & 0x04) >> 2;
+	__u8 ana_nonopt = (anacap & 0x02) >> 1;
+	__u8 ana_opt = (anacap & 0x01);
+
+	printf("  [7:7] : %#x\tNon-zero group ID %sSupported\n",
+	       nz, nz ? "" : "Not ");
+	printf("  [6:6] : %#x\tGroup ID does %schange\n",
+	       grpid_change, grpid_change ? "" : "not ");
+	if (rsvd)
+		printf(" [5:5] : %#x\tReserved\n", rsvd);
+	printf("  [4:4] : %#x\tANA Change state %sSupported\n",
+		ana_change, ana_change ? "" : "Not ");
+	printf("  [3:3] : %#x\tANA Persistent Loss state %sSupported\n",
+		ana_persist_loss, ana_persist_loss ? "" : "Not ");
+	printf("  [2:2] : %#x\tANA Inaccessible state %sSupported\n",
+		ana_inaccessible, ana_inaccessible ? "" : "Not ");
+	printf("  [1:1] : %#x\tANA Non-optimized state %sSupported\n",
+		ana_nonopt, ana_nonopt ? "" : "Not ");
+	printf("  [0:0] : %#x\tANA Optimized state %sSupported\n",
+		ana_opt, ana_opt ? "" : "Not ");
+	printf("\n");
+}
+
 static void show_nvme_id_ctrl_sqes(__u8 sqes)
 {
 	__u8 msqes = (sqes & 0xF0) >> 4;
@@ -646,6 +678,7 @@ void show_nvme_id_ns(struct nvme_id_ns *ns, unsigned int mode)
 	printf("nvmcap  : %.0Lf\n", int128_to_double(ns->nvmcap));
 	printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid));
 	printf("endgid  : %d\n", le16_to_cpu(ns->endgid));
+	printf("anagrpid: %#x\n", le32_to_cpu(ns->anagrpid));
 
 	printf("nguid   : ");
 	for (i = 0; i < 16; i++)
@@ -924,6 +957,12 @@ void __show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*ve
 	printf("hmminds   : %d\n", le32_to_cpu(ctrl->hmminds));
 	printf("hmmaxd    : %d\n", le16_to_cpu(ctrl->hmmaxd));
 	printf("nsetidmax : %d\n", le16_to_cpu(ctrl->nsetidmax));
+	printf("anatt     : %d\n", ctrl->anatt);
+	printf("anacap    : %#x\n", ctrl->anacap);
+	if (human)
+		show_nvme_id_ctrl_anacap(ctrl->anacap);
+	printf("anagrpmax : %u\n", le32_to_cpu(ctrl->anagrpmax));
+	printf("nanagrpid : %u\n", le32_to_cpu(ctrl->nanagrpid));
 	printf("sqes      : %#x\n", ctrl->sqes);
 	if (human)
 		show_nvme_id_ctrl_sqes(ctrl->sqes);
@@ -953,6 +992,7 @@ void __show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*ve
 	printf("sgls      : %x\n", le32_to_cpu(ctrl->sgls));
 	if (human)
 		show_nvme_id_ctrl_sgls(ctrl->sgls);
+	printf("mnan:     : %d\n", le32_to_cpu(ctrl->mnan));
 	printf("subnqn    : %-.*s\n", (int)sizeof(ctrl->subnqn), ctrl->subnqn);
 	printf("ioccsz    : %d\n", le32_to_cpu(ctrl->ioccsz));
 	printf("iorcsz    : %d\n", le32_to_cpu(ctrl->iorcsz));
-- 
2.13.7

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/6] nvme-list-subsys: Add device name argument and print out ANA state
  2018-07-27 10:26 [PATCH 0/6] nvme-cli ANA update Hannes Reinecke
                   ` (2 preceding siblings ...)
  2018-07-27 10:26 ` [PATCH 3/6] nvme-cli: Add ANA support Hannes Reinecke
@ 2018-07-27 10:26 ` Hannes Reinecke
  2018-07-27 10:26 ` [PATCH 5/6] nvme-cli: Implement ana log page support Hannes Reinecke
  2018-07-27 10:26 ` [PATCH 6/6] fabrics: display controller ID in discovery log output Hannes Reinecke
  5 siblings, 0 replies; 11+ messages in thread
From: Hannes Reinecke @ 2018-07-27 10:26 UTC (permalink / raw)


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(-)

diff --git a/Documentation/nvme-list-subsys.txt b/Documentation/nvme-list-subsys.txt
index c7de7ef..c40b708 100644
--- a/Documentation/nvme-list-subsys.txt
+++ b/Documentation/nvme-list-subsys.txt
@@ -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
 -------
diff --git a/nvme-print.c b/nvme-print.c
index 692c903..e4c90bf 100644
--- a/nvme-print.c
+++ b/nvme-print.c
@@ -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) {
diff --git a/nvme.c b/nvme.c
index 4815caa..74dfb61 100644
--- a/nvme.c
+++ b/nvme.c
@@ -1288,6 +1288,73 @@ err_free_addrpath:
 
 	return NULL;
 }
+
+static int scan_ctrl_paths_filter(const struct dirent *d)
+{
+	int id, cntlid, nsid;
+
+	if (d->d_name[0] == '.')
+		return 0;
+
+	if (strstr(d->d_name, "nvme")) {
+		if (sscanf(d->d_name, "nvme%dc%dn%d", &id, &cntlid, &nsid) != 3)
+			return 0;
+		return 1;
+	}
+
+	return 0;
+}
+
+static char *get_nvme_ctrl_path_ana_state(char *path, int nsid)
+{
+	struct dirent **paths;
+	char *ana_state;
+	int i, n;
+
+	ana_state = calloc(1, 16);
+	if (!ana_state)
+		return NULL;
+
+	n = scandir(path, &paths, scan_ctrl_paths_filter, alphasort);
+	if (n <= 0) {
+		fprintf(stderr, "failed to scan controller path(s).\n");
+		free(ana_state);
+		return NULL;
+	}
+	for (i = 0; i < n; i++) {
+		int id, cntlid, ns, fd;
+		ssize_t ret;
+		char ctrl_path[256];
+
+		if (sscanf(paths[i]->d_name, "nvme%dc%dn%d",
+			   &id, &cntlid, &ns) != 3)
+			continue;
+
+		if (ns != nsid)
+			continue;
+
+		sprintf(ctrl_path, "%s/%s/ana_state", path, paths[i]->d_name);
+		fd = open(ctrl_path, O_RDONLY);
+		if (fd < 0) {
+			fprintf(stderr, "Failed to open ANA state %s\n",
+				ctrl_path);
+			return NULL;
+		}
+		ret = read(fd, ana_state, 16);
+		if (ret < 0) {
+			fprintf(stderr, "Failed to read ANA state from %s\n",
+				ctrl_path);
+			free(ana_state);
+			ana_state = NULL;
+		} else if (ana_state[strlen(ana_state) - 1] == '\n')
+			ana_state[strlen(ana_state) - 1] = '\0';
+		close(fd);
+		break;
+	}
+
+	return ana_state;
+}
+
 static int scan_ctrls_filter(const struct dirent *d)
 {
 	int id, nsid;
@@ -1312,7 +1379,7 @@ static void free_ctrl_list_item(struct ctrl_list_item *ctrls)
 }
 
 int get_nvme_subsystem_info(char *name, char *path,
-				struct subsys_list_item *item)
+			    struct subsys_list_item *item, int nsid)
 {
 	char ctrl_path[512];
 	struct dirent **ctrls;
@@ -1360,7 +1427,9 @@ int get_nvme_subsystem_info(char *name, char *path,
 			free_ctrl_list_item(&item->ctrls[ccnt]);
 			continue;
 		}
-
+		if (nsid)
+			item->ctrls[ccnt].ana_state =
+				get_nvme_ctrl_path_ana_state(ctrl_path, nsid);
 		ccnt++;
 	}
 
@@ -1429,9 +1498,10 @@ static int list_subsys(int argc, char **argv, struct command *cmd,
 		       struct plugin *plugin)
 {
 	char path[310];
+	char *subsysnqn = NULL;
 	struct dirent **subsys;
 	struct subsys_list_item *slist;
-	int fmt, n, i, ret = 0, subcnt = 0;
+	int fmt, n = 1, i, ret = 0, subcnt = 0, nsid = 0, id;
 	const char *desc = "Retrieve information for subsystems";
 	struct config {
 		char *output_format;
@@ -1451,13 +1521,42 @@ static int list_subsys(int argc, char **argv, struct command *cmd,
 	if (ret < 0)
 		return ret;
 
+	devicename = NULL;
+	if (optind < argc) {
+		devicename = basename(argv[optind]);
+		if (sscanf(devicename, "nvme%dn%d", &id, &nsid) != 2) {
+			fprintf(stderr, "%s is not a NVMe namespace device\n",
+				argv[optind]);
+			return -EINVAL;
+		}
+		sprintf(path, "/sys/block/%s/device", devicename);
+		subsysnqn = get_nvme_subsnqn(path);
+		if (!subsysnqn) {
+			fprintf(stderr, "Cannot read subsys NQN from %s\n",
+				devicename);
+			return -EINVAL;
+		}
+		optind++;
+	}
+
+	if (ret < 0) {
+		argconfig_print_help(desc, opts);
+		if (subsysnqn)
+			free(subsysnqn);
+		return ret;
+	}
 	fmt = validate_output_format(cfg.output_format);
 
-	if (fmt != JSON && fmt != NORMAL)
+	if (fmt != JSON && fmt != NORMAL) {
+		if (subsysnqn)
+			free(subsysnqn);
 		return -EINVAL;
+	}
 	n = scandir(subsys_dir, &subsys, scan_subsys_filter, alphasort);
 	if (n < 0) {
 		fprintf(stderr, "no NVMe subsystem(s) detected.\n");
+		if (subsysnqn)
+			free(subsysnqn);
 		return n;
 	}
 
@@ -1471,12 +1570,15 @@ static int list_subsys(int argc, char **argv, struct command *cmd,
 		snprintf(path, sizeof(path), "%s%s", subsys_dir,
 			subsys[i]->d_name);
 		ret = get_nvme_subsystem_info(subsys[i]->d_name, path,
-				&slist[subcnt]);
+				&slist[subcnt], nsid);
 		if (ret) {
 			fprintf(stderr,
 				"%s: failed to get subsystem info: %s\n",
 				path, strerror(errno));
 			free_subsys_list_item(&slist[subcnt]);
+		} else if (subsysnqn &&
+			   strncmp(slist[subcnt].subsysnqn, subsysnqn, 255)) {
+			free_subsys_list_item(&slist[subcnt]);
 		} else
 			subcnt++;
 	}
@@ -1492,7 +1594,8 @@ free_subsys:
 	for (i = 0; i < n; i++)
 		free(subsys[i]);
 	free(subsys);
-
+		if (subsysnqn)
+			free(subsysnqn);
 	return ret;
 }
 
diff --git a/nvme.h b/nvme.h
index 5098b0e..26d5b85 100644
--- a/nvme.h
+++ b/nvme.h
@@ -129,6 +129,7 @@ struct ctrl_list_item {
 	char *name;
 	char *address;
 	char *transport;
+	char *ana_state;
 };
 
 struct subsys_list_item {
-- 
2.13.7

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/6] nvme-cli: Implement ana log page support
  2018-07-27 10:26 [PATCH 0/6] nvme-cli ANA update Hannes Reinecke
                   ` (3 preceding siblings ...)
  2018-07-27 10:26 ` [PATCH 4/6] nvme-list-subsys: Add device name argument and print out ANA state Hannes Reinecke
@ 2018-07-27 10:26 ` Hannes Reinecke
  2018-07-27 15:15   ` Christoph Hellwig
  2018-07-27 10:26 ` [PATCH 6/6] fabrics: display controller ID in discovery log output Hannes Reinecke
  5 siblings, 1 reply; 11+ messages in thread
From: Hannes Reinecke @ 2018-07-27 10:26 UTC (permalink / raw)


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

diff --git a/Documentation/nvme-ana-log.txt b/Documentation/nvme-ana-log.txt
new file mode 100644
index 0000000..6ef33e7
--- /dev/null
+++ b/Documentation/nvme-ana-log.txt
@@ -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
diff --git a/linux/nvme.h b/linux/nvme.h
index 55a197b..645e171 100644
--- a/linux/nvme.h
+++ b/linux/nvme.h
@@ -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.
  */
diff --git a/nvme-builtin.h b/nvme-builtin.h
index 2c26d57..df3eb4f 100644
--- a/nvme-builtin.h
+++ b/nvme-builtin.h
@@ -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)
diff --git a/nvme-ioctl.c b/nvme-ioctl.c
index 9cf2a33..f88909d 100644
--- a/nvme-ioctl.c
+++ b/nvme-ioctl.c
@@ -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)
 {
diff --git a/nvme-ioctl.h b/nvme-ioctl.h
index b34f5de..9527cc3 100644
--- a/nvme-ioctl.h
+++ b/nvme-ioctl.h
@@ -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,
diff --git a/nvme-print.c b/nvme-print.c
index e4c90bf..487ea44 100644
--- a/nvme-print.c
+++ b/nvme-print.c
@@ -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;
diff --git a/nvme-print.h b/nvme-print.h
index da287c2..b3d16dc 100644
--- a/nvme-print.h
+++ b/nvme-print.h
@@ -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);
diff --git a/nvme.c b/nvme.c
index 74dfb61..e463efc 100644
--- a/nvme.c
+++ b/nvme.c
@@ -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 "\
-- 
2.13.7

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/6] fabrics: display controller ID in discovery log output
  2018-07-27 10:26 [PATCH 0/6] nvme-cli ANA update Hannes Reinecke
                   ` (4 preceding siblings ...)
  2018-07-27 10:26 ` [PATCH 5/6] nvme-cli: Implement ana log page support Hannes Reinecke
@ 2018-07-27 10:26 ` Hannes Reinecke
  5 siblings, 0 replies; 11+ messages in thread
From: Hannes Reinecke @ 2018-07-27 10:26 UTC (permalink / raw)


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(+)

diff --git a/fabrics.c b/fabrics.c
index b1219a0..8601001 100644
--- a/fabrics.c
+++ b/fabrics.c
@@ -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);
-- 
2.13.7

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/6] nvme-cli: Implement ana log page support
  2018-07-27 10:26 ` [PATCH 5/6] nvme-cli: Implement ana log page support Hannes Reinecke
@ 2018-07-27 15:15   ` Christoph Hellwig
  2018-07-28 14:14     ` Hannes Reinecke
  0 siblings, 1 reply; 11+ messages in thread
From: Christoph Hellwig @ 2018-07-27 15:15 UTC (permalink / raw)


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

On Fri, Jul 27, 2018@12:26:31PM +0200, Hannes Reinecke wrote:
> 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
> 
> diff --git a/Documentation/nvme-ana-log.txt b/Documentation/nvme-ana-log.txt
> new file mode 100644
> index 0000000..6ef33e7
> --- /dev/null
> +++ b/Documentation/nvme-ana-log.txt
> @@ -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
> diff --git a/linux/nvme.h b/linux/nvme.h
> index 55a197b..645e171 100644
> --- a/linux/nvme.h
> +++ b/linux/nvme.h
> @@ -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.
>   */
> diff --git a/nvme-builtin.h b/nvme-builtin.h
> index 2c26d57..df3eb4f 100644
> --- a/nvme-builtin.h
> +++ b/nvme-builtin.h
> @@ -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)
> diff --git a/nvme-ioctl.c b/nvme-ioctl.c
> index 9cf2a33..f88909d 100644
> --- a/nvme-ioctl.c
> +++ b/nvme-ioctl.c
> @@ -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)
>  {
> diff --git a/nvme-ioctl.h b/nvme-ioctl.h
> index b34f5de..9527cc3 100644
> --- a/nvme-ioctl.h
> +++ b/nvme-ioctl.h
> @@ -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,
> diff --git a/nvme-print.c b/nvme-print.c
> index e4c90bf..487ea44 100644
> --- a/nvme-print.c
> +++ b/nvme-print.c
> @@ -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;
> diff --git a/nvme-print.h b/nvme-print.h
> index da287c2..b3d16dc 100644
> --- a/nvme-print.h
> +++ b/nvme-print.h
> @@ -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);
> diff --git a/nvme.c b/nvme.c
> index 74dfb61..e463efc 100644
> --- a/nvme.c
> +++ b/nvme.c
> @@ -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 "\
> -- 
> 2.13.7
---end quoted text---

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 5/6] nvme-cli: Implement ana log page support
  2018-07-27 15:15   ` Christoph Hellwig
@ 2018-07-28 14:14     ` Hannes Reinecke
  2018-07-28 14:46       ` Chaitanya Kulkarni
  0 siblings, 1 reply; 11+ messages in thread
From: Hannes Reinecke @ 2018-07-28 14:14 UTC (permalink / raw)


On 07/27/2018 05:15 PM, Christoph Hellwig wrote:
> 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

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 5/6] nvme-cli: Implement ana log page support
  2018-07-28 14:14     ` Hannes Reinecke
@ 2018-07-28 14:46       ` Chaitanya Kulkarni
  2018-07-29  8:56         ` Hannes Reinecke
  0 siblings, 1 reply; 11+ messages in thread
From: Chaitanya Kulkarni @ 2018-07-28 14:46 UTC (permalink / raw)



From: Hannes Reinecke <hare@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
? 
 
On 07/27/2018 05:15 PM, Christoph Hellwig wrote:
> 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

    

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 5/6] nvme-cli: Implement ana log page support
  2018-07-28 14:46       ` Chaitanya Kulkarni
@ 2018-07-29  8:56         ` Hannes Reinecke
  0 siblings, 0 replies; 11+ messages in thread
From: Hannes Reinecke @ 2018-07-29  8:56 UTC (permalink / raw)


On 07/28/2018 04:46 PM, Chaitanya Kulkarni wrote:
> 
> 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
>    
>   
> On 07/27/2018 05:15 PM, Christoph Hellwig wrote:
>> 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?
> 
Ok, will be doing so.

Cheers,

Hannes

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-07-29  8:56 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-27 10:26 [PATCH 0/6] nvme-cli ANA update Hannes Reinecke
2018-07-27 10:26 ` [PATCH 1/6] nvme-discover: sanitize options Hannes Reinecke
2018-07-27 10:26 ` [PATCH 2/6] nvme-discover: Retry discovery log if the generation counter changes Hannes Reinecke
2018-07-27 10:26 ` [PATCH 3/6] nvme-cli: Add ANA support Hannes Reinecke
2018-07-27 10:26 ` [PATCH 4/6] nvme-list-subsys: Add device name argument and print out ANA state Hannes Reinecke
2018-07-27 10:26 ` [PATCH 5/6] nvme-cli: Implement ana log page support Hannes Reinecke
2018-07-27 15:15   ` Christoph Hellwig
2018-07-28 14:14     ` Hannes Reinecke
2018-07-28 14:46       ` Chaitanya Kulkarni
2018-07-29  8:56         ` Hannes Reinecke
2018-07-27 10:26 ` [PATCH 6/6] fabrics: display controller ID in discovery log output Hannes Reinecke

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.