* [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 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
* [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