]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme-cli: add changed log ns support
authorChaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Mon, 11 Jun 2018 02:05:07 +0000 (22:05 -0400)
committerKeith Busch <keith.busch@intel.com>
Mon, 25 Jun 2018 15:52:11 +0000 (09:52 -0600)
Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Signed-off-by: Keith Busch <keith.busch@intel.com>
linux/nvme.h
nvme-builtin.h
nvme-ioctl.c
nvme-ioctl.h
nvme-print.c
nvme-print.h
nvme.c

index 8df72554cb10a1a5f7b89cd6f895a1bbd559f2ec..bab9736f1340599db6b05ca03f5fda212a3f0264 100644 (file)
@@ -495,6 +495,12 @@ struct nvme_fw_slot_info_log {
        __u8                    rsvd64[448];
 };
 
+#define NVME_MAX_CHANGED_NAMESPACES     1024
+
+struct nvme_changed_ns_list_log {
+       __le32                  log[NVME_MAX_CHANGED_NAMESPACES];
+};
+
 enum {
        NVME_CMD_EFFECTS_CSUPP          = 1 << 0,
        NVME_CMD_EFFECTS_LBCC           = 1 << 1,
@@ -869,6 +875,7 @@ enum {
        NVME_LOG_ERROR          = 0x01,
        NVME_LOG_SMART          = 0x02,
        NVME_LOG_FW_SLOT        = 0x03,
+       NVME_LOG_CHANGED_NS     = 0x04,
        NVME_LOG_CMD_EFFECTS    = 0x05,
        NVME_LOG_DEVICE_SELF_TEST = 0x06,
        NVME_LOG_TELEMETRY_HOST = 0x07,
index 86b0fff1932a8741bba20c06ed201abbfe744a61..27a5b35fb4835a59b9206974d61ff0ecae9eb7ba 100644 (file)
@@ -23,6 +23,7 @@ COMMAND_LIST(
        ENTRY("get-log", "Generic NVMe get log, returns log in raw format", get_log)
        ENTRY("telemetry-log", "Retrieve FW Telemetry log write to file", get_telemetry_log)
        ENTRY("fw-log", "Retrieve FW Log, show it", get_fw_log)
+       ENTRY("changed-ns-list-log", "Retrieve Changed Namespace List, show it", get_changed_ns_list_log)
        ENTRY("smart-log", "Retrieve SMART Log, show it", get_smart_log)
        ENTRY("error-log", "Retrieve Error Log, show it", get_error_log)
        ENTRY("effects-log", "Retrieve Command Effects Log, show it", get_effects_log)
index 63ff8fb081f475b7030a5feea1dec5ee5a25e616..f1c7ce6dfb2ce1fc790169c4c9d4200cfe175453 100644 (file)
@@ -445,6 +445,12 @@ int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log)
        return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_FW_SLOT, sizeof(*fw_log), fw_log);
 }
 
+int nvme_changed_ns_list_log(int fd, struct nvme_changed_ns_list_log *changed_ns_list_log)
+{
+       return nvme_get_log(fd, 0, NVME_LOG_CHANGED_NS, sizeof(changed_ns_list_log->log),
+                       changed_ns_list_log->log);
+}
+
 int nvme_error_log(int fd, int entries, struct nvme_error_log_page *err_log)
 {
        return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_ERROR, entries * sizeof(*err_log), err_log);
index 6d4ac9586352ce3427340a4391f2f5f7596b21f5..0b2006221eca093859c4db3791e2305663538e29 100644 (file)
@@ -88,6 +88,8 @@ int nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data);
 int nvme_get_telemetry_log(int fd, void *lp, int generate_report,
                           int ctrl_gen, size_t log_page_size, __u64 offset);
 int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log);
+int nvme_changed_ns_list_log(int fd,
+               struct nvme_changed_ns_list_log *changed_ns_list_log);
 int nvme_error_log(int fd, 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_effects_log(int fd, struct nvme_effects_log_page *effects_log);
index 25a4e03459941dc023cb9ee5b6da301bff9b9473..ddb9625c02f2eb3c76a66b0d44abe0568781a223 100644 (file)
@@ -1103,6 +1103,23 @@ void show_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname)
                                                fw_to_string(fw_log->frs[i]));
 }
 
+void show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, const char *devname)
+{
+       int i;
+       __u32 nsid;
+
+       if (log->log[0] != cpu_to_le32(0XFFFFFFFF)) {
+               for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) {
+                       nsid = le32_to_cpu(log->log[i]);
+                       if (nsid == 0)
+                               break;
+
+                       printf("[%4u]:%#x\n", i, nsid);
+               }
+       } else
+               printf("more than %d ns changed\n", NVME_MAX_CHANGED_NAMESPACES);
+}
+
 static void show_effects_log_human(__u32 effect)
 {
        const char *set = "+";
@@ -2266,6 +2283,41 @@ void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname)
        json_free_object(root);
 }
 
+void json_changed_ns_list_log(struct nvme_changed_ns_list_log *log, const char *devname)
+{
+       struct json_object *root;
+       struct json_object *nsi;
+       char fmt[32];
+       char str[32];
+       __u32 nsid;
+       int i;
+
+       if (log->log[0] == cpu_to_le32(0XFFFFFFFF))
+               return;
+
+       root = json_create_object();
+       nsi = json_create_object();
+
+       json_object_add_value_string(root, "Changed Namespace List Log", devname);
+
+       for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) {
+               nsid = le32_to_cpu(log->log[i]);
+
+               if (nsid == 0)
+                       break;
+
+               snprintf(fmt, sizeof(fmt), "[%4u]", i + 1);
+               snprintf(str, sizeof(str), "%#x", nsid);
+               json_object_add_value_string(nsi, fmt, str);
+       }
+
+       json_object_add_value_object(root, devname, nsi);
+       json_print_object(root, NULL);
+       printf("\n");
+
+       json_free_object(root);
+}
+
 void json_endurance_log(struct nvme_endurance_group_log *endurance_group,
                        __u16 group_id, const char *devname)
 {
index 7dd5f3430ac2316fa8ae27f4a6f319aabc2b892f..eadd87a87b1019b0bee2e4cdc666f8fb83197b3c 100644 (file)
@@ -27,6 +27,7 @@ void show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char
 void show_self_test_log(struct nvme_self_test_log *self_test, 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, unsigned int flags);
+void show_changed_ns_list_log(struct nvme_changed_ns_list_log *log, const char *devname);
 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);
@@ -51,6 +52,7 @@ void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char
 void json_effects_log(struct nvme_effects_log_page *effects_log, const char *devname);
 void json_sanitize_log(struct nvme_sanitize_log_page *sanitize_log, const char *devname);
 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_print_list_items(struct list_item *items, unsigned amnt);
diff --git a/nvme.c b/nvme.c
index b5afa2c25ff8d9af6576ca6448b506d368448f9b..d456bf19c6b3820ae89660d0f54eb70181315a4a 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -606,6 +606,62 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin
        return err;
 }
 
+static int get_changed_ns_list_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+       struct nvme_changed_ns_list_log changed_ns_list_log;
+       const char *desc = "Retrieve Changed Namespaces log for the given device "\
+                       "in either decoded format "\
+                       "(default) or binary.";
+       const char *raw = "output in binary format";
+       int err, fmt, fd;
+
+       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, &cfg, sizeof(cfg));
+       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;
+
+       err = nvme_changed_ns_list_log(fd, &changed_ns_list_log);
+       if (!err) {
+               if (fmt == BINARY)
+                       d_raw((unsigned char *)changed_ns_list_log.log, sizeof(changed_ns_list_log.log));
+               else if (fmt == JSON)
+                       json_changed_ns_list_log(&changed_ns_list_log, devicename);
+               else
+                       show_changed_ns_list_log(&changed_ns_list_log, devicename);
+       } else if (err > 0)
+               fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+       else
+               perror("changed ns list log");
+
+ close_fd:
+       close(fd);
+
+       return err;
+}
+
 static int get_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
        const char *desc = "Retrieve desired number of bytes "\