File 0011-nvme-cli-add-minimal-ana-log-page-support.patch of Package nvme-cli.7759
From 9a0aa45c58dfaab6ae14c3bc5717792bf5c46efa Mon Sep 17 00:00:00 2001
From: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Date: Wed, 1 Aug 2018 20:28:18 -0700
Subject: [PATCH] nvme-cli: add minimal ana-log page support
This patch adds a new command to retrieve the ANA Log page.
We update identify ctrl/ns data structure to support this command.
We also add ana based error codes and different identifiers to the
linux/nvme.h header file in order to support this command.
Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
linux/nvme.h | 55 ++++++++++++++++--
nvme-builtin.h | 1 +
nvme-ioctl.c | 8 +++
nvme-ioctl.h | 1 +
nvme-print.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
nvme-print.h | 2 +
nvme.c | 79 +++++++++++++++++++++++++
7 files changed, 317 insertions(+), 6 deletions(-)
diff --git a/linux/nvme.h b/linux/nvme.h
index 162b1e0..b7a3c31 100644
--- a/linux/nvme.h
+++ b/linux/nvme.h
@@ -239,7 +239,13 @@ struct nvme_id_ctrl {
__le32 sanicap;
__le32 hmminds;
__le16 hmmaxd;
- __u8 rsvd338[174];
+ __le16 nsetidmax;
+ __u8 rsvd340[2];
+ __u8 anatt;
+ __u8 anacap;
+ __le32 anagrpmax;
+ __le32 nanagrpid;
+ __u8 rsvd352[160];
__u8 sqes;
__u8 cqes;
__le16 maxcmd;
@@ -255,7 +261,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;
@@ -309,7 +316,11 @@ struct nvme_id_ns {
__le16 nabspf;
__le16 noiob;
__u8 nvmcap[16];
- __u8 rsvd64[40];
+ __u8 rsvd64[28];
+ __le32 anagrpid;
+ __u8 rsvd96[4];
+ __le16 nvmsetid;
+ __le16 endgid;
__u8 nguid[16];
__u8 eui64[8];
struct nvme_lbaf lbaf[16];
@@ -426,6 +437,32 @@ struct nvme_effects_log {
__u8 resv[2048];
};
+enum nvme_ana_state {
+ NVME_ANA_OPTIMIZED = 0x01,
+ NVME_ANA_NONOPTIMIZED = 0x02,
+ NVME_ANA_INACCESSIBLE = 0x03,
+ NVME_ANA_PERSISTENT_LOSS = 0x04,
+ NVME_ANA_CHANGE = 0x0f,
+};
+
+struct nvme_ana_group_desc {
+ __le32 grpid;
+ __le32 nnsids;
+ __le64 chgcnt;
+ __u8 state;
+ __u8 rsvd17[7];
+ __le32 nsids[];
+};
+
+/* flag for the log specific field of the ANA log */
+#define NVME_ANA_LOG_RGO (1 << 0)
+
+struct nvme_ana_rsp_hdr {
+ __le64 chgcnt;
+ __le16 ngrps;
+ __le16 rsvd10[3];
+};
+
enum {
NVME_SMART_CRIT_SPARE = 1 << 0,
NVME_SMART_CRIT_TEMPERATURE = 1 << 1,
@@ -441,6 +478,7 @@ enum {
NVME_AER_VS = 7,
NVME_AER_NOTICE_NS_CHANGED = 0x0002,
NVME_AER_NOTICE_FW_ACT_STARTING = 0x0102,
+ NVME_AER_NOTICE_ANA = 0x03,
};
struct nvme_lba_range_type {
@@ -768,6 +806,7 @@ enum {
NVME_LOG_SMART = 0x02,
NVME_LOG_FW_SLOT = 0x03,
NVME_LOG_CMD_EFFECTS = 0x05,
+ NVME_LOG_ANA = 0x0c,
NVME_LOG_DISC = 0x70,
NVME_LOG_RESERVATION = 0x80,
NVME_LOG_SANITIZE = 0x81,
@@ -779,6 +818,7 @@ enum {
enum {
NVME_NO_LOG_LSP = 0x0,
NVME_NO_LOG_LPO = 0x0,
+ NVME_LOG_ANA_LSP_RGO = 0x1,
};
/* Sanitize and Sanitize Monitor/Log */
@@ -916,7 +956,7 @@ struct nvme_get_log_page_command {
__u64 rsvd2[2];
union nvme_data_ptr dptr;
__u8 lid;
- __u8 rsvd10;
+ __u8 lsp;
__le16 numdl;
__le16 numdu;
__u16 rsvd11;
@@ -1230,6 +1270,13 @@ enum {
NVME_SC_ACCESS_DENIED = 0x286,
NVME_SC_UNWRITTEN_BLOCK = 0x287,
+ /*
+ * Path-related Errors:
+ */
+ NVME_SC_ANA_PERSISTENT_LOSS = 0x301,
+ NVME_SC_ANA_INACCESSIBLE = 0x302,
+ NVME_SC_ANA_TRANSITION = 0x303,
+
NVME_SC_DNR = 0x4000,
};
diff --git a/nvme-builtin.h b/nvme-builtin.h
index 85f9f0f..4a474ec 100644
--- a/nvme-builtin.h
+++ b/nvme-builtin.h
@@ -22,6 +22,7 @@ COMMAND_LIST(
ENTRY("get-log", "Generic NVMe get log, returns log in raw format", get_log)
ENTRY("fw-log", "Retrieve FW Log, show it", get_fw_log)
ENTRY("smart-log", "Retrieve SMART Log, show it", get_smart_log)
+ ENTRY("ana-log", "Retrieve ANA Log, show it", get_ana_log)
ENTRY("error-log", "Retrieve Error Log, show it", get_error_log)
ENTRY("effects-log", "Retrieve Command Effects Log, show it", get_effects_log)
ENTRY("get-feature", "Get feature and show the resulting value", get_feature)
diff --git a/nvme-ioctl.c b/nvme-ioctl.c
index 780ee50..eea33ca 100644
--- a/nvme-ioctl.c
+++ b/nvme-ioctl.c
@@ -427,6 +427,14 @@ int nvme_smart_log(int fd, __u32 nsid, struct nvme_smart_log *smart_log)
return nvme_get_log(fd, nsid, NVME_LOG_SMART, sizeof(*smart_log), smart_log);
}
+int nvme_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo)
+{
+ __u64 lpo = 0;
+
+ return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_ANA, rgo, lpo, 0,
+ true, ana_log_len, ana_log);
+}
+
int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size)
{
return nvme_get_log(fd, 0, NVME_LOG_DISC, size, log);
diff --git a/nvme-ioctl.h b/nvme-ioctl.h
index 1f804c2..1b0619a 100644
--- a/nvme-ioctl.h
+++ b/nvme-ioctl.h
@@ -87,6 +87,7 @@ int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log);
int nvme_error_log(int fd, __u32 nsid, int entries,
struct nvme_error_log_page *err_log);
int nvme_smart_log(int fd, __u32 nsid, struct nvme_smart_log *smart_log);
+int nvme_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo);
int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size);
int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10,
diff --git a/nvme-print.c b/nvme-print.c
index 04253d2..8510cb3 100644
--- a/nvme-print.c
+++ b/nvme-print.c
@@ -7,6 +7,23 @@
#include "json.h"
#include "nvme-models.h"
+static const char *nvme_ana_state_to_string(enum nvme_ana_state state)
+{
+ switch (state) {
+ case NVME_ANA_OPTIMIZED:
+ return "optimized";
+ case NVME_ANA_NONOPTIMIZED:
+ return "non-optimized";
+ case NVME_ANA_INACCESSIBLE:
+ return "inaccessible";
+ case NVME_ANA_PERSISTENT_LOSS:
+ return "persistent-loss";
+ case NVME_ANA_CHANGE:
+ return "change";
+ }
+ return "invalid state";
+}
+
static long double int128_to_double(__u8 *data)
{
int i;
@@ -77,12 +94,15 @@ 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");
@@ -261,6 +281,37 @@ 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;
@@ -600,6 +651,9 @@ void show_nvme_id_ns(struct nvme_id_ns *ns, unsigned int mode)
printf("nabspf : %d\n", le16_to_cpu(ns->nabspf));
printf("noiob : %d\n", le16_to_cpu(ns->noiob));
printf("nvmcap : %.0Lf\n", int128_to_double(ns->nvmcap));
+ printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid));
+ printf("anagrpid: %d\n", le32_to_cpu(ns->anagrpid));
+ printf("endgid : %d\n", le16_to_cpu(ns->endgid));
printf("nguid : ");
for (i = 0; i < 16; i++)
@@ -876,6 +930,13 @@ void __show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*ve
show_nvme_id_ctrl_sanicap(ctrl->sanicap);
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 : %d\n", ctrl->anacap);
+ if (human)
+ show_nvme_id_ctrl_anacap(ctrl->anacap);
+ printf("anagrpmax : %d\n", ctrl->anagrpmax);
+ printf("nanagrpid : %d\n", le32_to_cpu(ctrl->nanagrpid));
printf("sqes : %#x\n", ctrl->sqes);
if (human)
show_nvme_id_ctrl_sqes(ctrl->sqes);
@@ -903,6 +964,7 @@ void __show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*ve
show_nvme_id_ctrl_nvscc(ctrl->nvscc);
printf("acwu : %d\n", le16_to_cpu(ctrl->acwu));
printf("sgls : %x\n", le32_to_cpu(ctrl->sgls));
+ printf("mnan : %d\n", le32_to_cpu(ctrl->mnan));
if (human)
show_nvme_id_ctrl_sgls(ctrl->sgls);
printf("subnqn : %-.*s\n", (int)sizeof(ctrl->subnqn), ctrl->subnqn);
@@ -1100,6 +1162,44 @@ void show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char
printf("Thermal Management T2 Total Time : %u\n", le32_to_cpu(smart->thm_temp2_total_time));
}
+void show_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname)
+{
+ int offset = sizeof(struct nvme_ana_rsp_hdr);
+ struct nvme_ana_rsp_hdr *hdr = ana_log;
+ struct nvme_ana_group_desc *desc;
+ size_t nsid_buf_size;
+ void *base = ana_log;
+ __u32 nr_nsids;
+ int i;
+ int j;
+
+ printf("Asynchronous Namespace Access Log for NVMe device: %s\n",
+ devname);
+ printf("ANA LOG HEADER :-\n");
+ printf("chgcnt : %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(hdr->chgcnt));
+ printf("ngrps : %u\n", le16_to_cpu(hdr->ngrps));
+ printf("ANA Log Desc :-\n");
+
+ for (i = 0; i < le16_to_cpu(ana_log->ngrps); i++) {
+ desc = base + offset;
+ nr_nsids = le32_to_cpu(desc->nnsids);
+ nsid_buf_size = nr_nsids * sizeof(__le32);
+
+ offset += sizeof(*desc);
+ printf("grpid : %u\n", le32_to_cpu(desc->grpid));
+ printf("nnsids : %u\n", le32_to_cpu(desc->nnsids));
+ printf("chgcnt : %llu\n", le64_to_cpu(desc->chgcnt));
+ printf("state : %s\n",
+ nvme_ana_state_to_string(desc->state));
+ for (j = 0; j < le32_to_cpu(desc->nnsids); j++)
+ printf(" nsid : %u\n",
+ le32_to_cpu(desc->nsids[j]));
+ printf("\n");
+ offset += nsid_buf_size;
+ }
+}
+
char *nvme_feature_to_string(int feature)
{
switch (feature) {
@@ -1216,6 +1316,10 @@ char *nvme_status_to_string(__u32 status)
case NVME_SC_COMPARE_FAILED: return "COMPARE_FAILED";
case NVME_SC_ACCESS_DENIED: return "ACCESS_DENIED";
case NVME_SC_UNWRITTEN_BLOCK: return "UNWRITTEN_BLOCK";
+
+ case NVME_SC_ANA_PERSISTENT_LOSS: return "ANA_PERSISTENT_LOSS";
+ case NVME_SC_ANA_INACCESSIBLE: return "ANA_INACCESSIBLE";
+ case NVME_SC_ANA_TRANSITION: return "ANA_TRANSITION";
default: return "Unknown";
}
}
@@ -1566,6 +1670,9 @@ void json_nvme_id_ns(struct nvme_id_ns *ns, unsigned int mode)
json_object_add_value_int(root, "nabspf", le16_to_cpu(ns->nabspf));
json_object_add_value_int(root, "noiob", le16_to_cpu(ns->noiob));
json_object_add_value_float(root, "nvmcap", nvmcap);
+ json_object_add_value_int(root, "nvmsetid", le16_to_cpu(ns->nvmsetid));
+ json_object_add_value_int(root, "anagrpid", le32_to_cpu(ns->anagrpid));
+ json_object_add_value_int(root, "endgid", le16_to_cpu(ns->endgid));
memset(eui64, 0, sizeof(eui64_buf));
for (i = 0; i < sizeof(ns->eui64); i++)
@@ -1657,6 +1764,13 @@ void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*vs)(
json_object_add_value_int(root, "mntmt", le16_to_cpu(ctrl->mntmt));
json_object_add_value_int(root, "mxtmt", le16_to_cpu(ctrl->mxtmt));
json_object_add_value_int(root, "sanicap", le32_to_cpu(ctrl->sanicap));
+ json_object_add_value_int(root, "hmminds", le32_to_cpu(ctrl->hmminds));
+ json_object_add_value_int(root, "hmmaxd", le16_to_cpu(ctrl->hmmaxd));
+ json_object_add_value_int(root, "nsetidmax", le16_to_cpu(ctrl->nsetidmax));
+ json_object_add_value_int(root, "anatt",ctrl->anatt);
+ json_object_add_value_int(root, "anacap", ctrl->anacap);
+ json_object_add_value_int(root, "anagrpmax", le32_to_cpu(ctrl->anagrpmax));
+ json_object_add_value_int(root, "nanagrpid", le32_to_cpu(ctrl->nanagrpid));
json_object_add_value_int(root, "sqes", ctrl->sqes);
json_object_add_value_int(root, "cqes", ctrl->cqes);
json_object_add_value_int(root, "maxcmd", le16_to_cpu(ctrl->maxcmd));
@@ -1901,6 +2015,65 @@ void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char
json_free_object(root);
}
+void json_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname)
+{
+ int offset = sizeof(struct nvme_ana_rsp_hdr);
+ struct nvme_ana_rsp_hdr *hdr = ana_log;
+ struct nvme_ana_group_desc *ana_desc;
+ struct json_array *desc_list;
+ struct json_array *ns_list;
+ struct json_object *desc;
+ struct json_object *nsid;
+ struct json_object *root;
+ size_t nsid_buf_size;
+ void *base = ana_log;
+ __u32 nr_nsids;
+ int i;
+ int j;
+
+ root = json_create_object();
+ json_object_add_value_string(root,
+ "Asynchronous Namespace Access Log for NVMe device:",
+ devname);
+ json_object_add_value_uint(root, "chgcnt",
+ (uint64_t)le64_to_cpu(hdr->chgcnt));
+ json_object_add_value_uint(root, "ngrps", le16_to_cpu(hdr->ngrps));
+
+ desc_list = json_create_array();
+ for (i = 0; i < le16_to_cpu(ana_log->ngrps); i++) {
+ desc = json_create_object();
+ ana_desc = base + offset;
+ nr_nsids = le32_to_cpu(ana_desc->nnsids);
+ nsid_buf_size = nr_nsids * sizeof(__le32);
+
+ offset += sizeof(*ana_desc);
+ json_object_add_value_uint(desc, "grpid",
+ le32_to_cpu(ana_desc->grpid));
+ json_object_add_value_uint(desc, "nnsids",
+ le32_to_cpu(ana_desc->nnsids));
+ json_object_add_value_uint(desc, "chgcnt",
+ le64_to_cpu(ana_desc->chgcnt));
+ json_object_add_value_string(desc, "state",
+ nvme_ana_state_to_string(ana_desc->state));
+
+ ns_list = json_create_array();
+ for (j = 0; j < le32_to_cpu(ana_desc->nnsids); j++) {
+ nsid = json_create_object();
+ json_object_add_value_uint(nsid, "nsid",
+ le32_to_cpu(ana_desc->nsids[j]));
+ json_array_add_value_object(ns_list, nsid);
+ }
+ json_object_add_value_array(desc, "NSIDS", ns_list);
+ offset += nsid_buf_size;
+ json_array_add_value_object(desc_list, desc);
+ }
+
+ json_object_add_value_array(root, "ANA DESC LIST ", desc_list);
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+}
+
void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n)
{
struct json_object *root;
diff --git a/nvme-print.h b/nvme-print.h
index 926c196..5f1d570 100644
--- a/nvme-print.h
+++ b/nvme-print.h
@@ -24,6 +24,7 @@ void show_nvme_resv_report(struct nvme_reservation_status *status, int bytes, __
void show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges);
void show_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname);
void show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname);
+void show_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname);
void show_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname);
void show_effects_log(struct nvme_effects_log_page *effects);
void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics);
@@ -41,6 +42,7 @@ void json_nvme_id_ns(struct nvme_id_ns *ns, unsigned int flags);
void json_nvme_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11);
void json_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname);
void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname);
+void json_ana_log(struct nvme_ana_rsp_hdr *ana_log, const char *devname);
void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname);
void json_print_list_items(struct list_item *items, unsigned amnt);
void json_nvme_id_ns_descs(void *data);
diff --git a/nvme.c b/nvme.c
index 274871a..8f26aed 100644
--- a/nvme.c
+++ b/nvme.c
@@ -220,6 +220,85 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug
nvme_status_to_string(err), err);
else
perror("smart log");
+
+ return err;
+}
+
+static int get_ana_log(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve ANA log for the given device" \
+ "in either decoded format "\
+ "(default) or binary.";
+ const char *raw = "output in binary format";
+ void *ana_log;
+ int err, fmt, fd;
+ int groups = 0; /* Right now get all the per ANA group NSIDS */
+ size_t ana_log_len;
+ struct nvme_id_ctrl ctrl;
+
+ struct config {
+ int raw_binary;
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ 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},
+ {NULL}
+ };
+
+ fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0);
+ if (fd < 0)
+ return fd;
+
+ fmt = validate_output_format(cfg.output_format);
+ if (fmt < 0) {
+ err = fmt;
+ goto close_fd;
+ }
+
+ if (cfg.raw_binary)
+ fmt = BINARY;
+
+ memset(&ctrl, 0, sizeof (struct nvme_id_ctrl));
+ err = nvme_identify_ctrl(fd, &ctrl);
+ if (err) {
+ fprintf(stderr, "ERROR : nvme_identify_ctrl() failed 0x%x\n",
+ err);
+ goto close_fd;
+ }
+ ana_log_len = sizeof(struct nvme_ana_rsp_hdr) +
+ le32_to_cpu(ctrl.nanagrpid) * sizeof(struct nvme_ana_group_desc);
+ if (!(ctrl.anacap & (1 << 6)))
+ ana_log_len += ctrl.mnan * sizeof(__le32);
+
+ ana_log = malloc(ana_log_len);
+ if (!ana_log) {
+ perror("malloc : ");
+ err = -ENOMEM;
+ goto close_fd;
+ }
+
+ err = nvme_ana_log(fd, ana_log, ana_log_len, groups ? NVME_ANA_LOG_RGO : 0);
+ if (!err) {
+ if (fmt == BINARY)
+ d_raw((unsigned char *)ana_log, ana_log_len);
+ else if (fmt == JSON)
+ json_ana_log(ana_log, devicename);
+ else
+ show_ana_log(ana_log, devicename);
+ } else if (err > 0)
+ fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+ else
+ perror("ana-log");
+ free(ana_log);
+close_fd:
+ close(fd);
return err;
}
--
2.13.7