From: Keith Busch Date: Sat, 17 Feb 2018 18:09:01 +0000 (-0700) Subject: Add support for NVMe Sets log page X-Git-Tag: v1.6~81 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=bd1f2f61541d6ecbef1ea17e6c938a62848daa00;p=users%2Fsagi%2Fnvme-cli.git Add support for NVMe Sets log page Implemented from ratified TP4018 Signed-off-by: Keith Busch --- diff --git a/linux/nvme.h b/linux/nvme.h index 127d6367..437b92d3 100644 --- a/linux/nvme.h +++ b/linux/nvme.h @@ -405,6 +405,18 @@ struct nvme_telemetry_log_page_hdr { __u8 telemetry_dataarea[0]; }; +struct nvme_endurance_group_log { + __u32 rsvd0; + __u8 avl_spare_threshold; + __u8 percent_used; + __u8 rsvd6[26]; + __u8 endurance_estimate[16]; + __u8 data_units_read[16]; + __u8 data_units_written[16]; + __u8 media_units_written[16]; + __u8 rsvd96[416]; +}; + struct nvme_smart_log { __u8 critical_warning; __u8 temperature[2]; @@ -813,6 +825,7 @@ enum { NVME_LOG_CMD_EFFECTS = 0x05, NVME_LOG_TELEMETRY_HOST = 0x07, NVME_LOG_TELEMETRY_CTRL = 0x08, + NVME_LOG_ENDURANCE_GROUP = 0x09, NVME_LOG_DISC = 0x70, NVME_LOG_RESERVATION = 0x80, NVME_LOG_SANITIZE = 0x81, diff --git a/nvme-builtin.h b/nvme-builtin.h index f745e33a..75055c33 100644 --- a/nvme-builtin.h +++ b/nvme-builtin.h @@ -25,6 +25,7 @@ COMMAND_LIST( 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) + ENTRY("endurance-log", "Retrieve Endurance Group Log, show it", get_endurance_log) ENTRY("get-feature", "Get feature and show the resulting value", get_feature) ENTRY("set-feature", "Set a feature and show the resulting value", set_feature) ENTRY("set-property", "Set a property and show the resulting value", set_property) diff --git a/nvme-ioctl.c b/nvme-ioctl.c index 770ff8c1..d17d702f 100644 --- a/nvme-ioctl.c +++ b/nvme-ioctl.c @@ -382,7 +382,7 @@ int nvme_identify_ns_descs(int fd, __u32 nsid, void *data) } int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, - __u32 data_len, void *data) + __u16 lsi, __u32 data_len, void *data) { struct nvme_admin_cmd cmd = { .opcode = nvme_admin_get_log_page, @@ -397,7 +397,7 @@ int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, if (lsp) cmd.cdw10 |= lsp << 8; - cmd.cdw11 = numdu; + cmd.cdw11 = numdu | (lsi << 16); cmd.cdw12 = lpo; cmd.cdw13 = (lpo >> 32); @@ -408,7 +408,7 @@ int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, int nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data) { return nvme_get_log13(fd, nsid, log_id, NVME_NO_LOG_LSP, NVME_NO_LOG_LPO, - data_len, data); + 0, data_len, data); } int nvme_get_telemetry_log(int fd, void *lp, int generate_report, @@ -417,15 +417,15 @@ int nvme_get_telemetry_log(int fd, void *lp, int generate_report, if (ctrl_init) return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_CTRL, NVME_NO_LOG_LSP, offset, - log_page_size, lp); + 0, log_page_size, lp); if (generate_report) return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_HOST, NVME_TELEM_LSP_CREATE, offset, - log_page_size, lp); + 0, log_page_size, lp); else return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_HOST, NVME_NO_LOG_LSP, offset, - log_page_size, lp); + 0, log_page_size, lp); } int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log) @@ -438,6 +438,12 @@ 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); } +int nvme_endurance_log(int fd, __u16 group_id, struct nvme_endurance_group_log *endurance_log) +{ + return nvme_get_log13(fd, 0, NVME_LOG_ENDURANCE_GROUP, 0, 0, group_id, + sizeof(*endurance_log), endurance_log); +} + 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); diff --git a/nvme-ioctl.h b/nvme-ioctl.h index 69a303b2..954a9929 100644 --- a/nvme-ioctl.h +++ b/nvme-ioctl.h @@ -79,7 +79,7 @@ int nvme_identify_ns_list(int fd, __u32 nsid, bool all, void *data); int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data); int nvme_identify_ns_descs(int fd, __u32 nsid, void *data); int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, - __u32 data_len, void *data); + __u16 group_id, __u32 data_len, void *data); int nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data); @@ -91,6 +91,8 @@ 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); 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_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 e729a3c9..eeb952fa 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -1157,6 +1157,22 @@ uint64_t int48_to_long(__u8 *data) return result; } +void show_endurance_log(struct nvme_endurance_group_log *endurance_group, + __u16 group_id, const char *devname) +{ + printf("Endurance Group Log for NVME device:%s Group ID:%x\n", devname, group_id); + printf("avl_spare_threshold : %u\n", endurance_group->avl_spare_threshold); + printf("percent_used : %u%%\n", endurance_group->percent_used); + printf("endurance_estimate : %'.0Lf\n", + int128_to_double(endurance_group->endurance_estimate)); + printf("data_units_read : %'.0Lf\n", + int128_to_double(endurance_group->data_units_read)); + printf("data_units_written : %'.0Lf\n", + int128_to_double(endurance_group->data_units_written)); + printf("media_units_written : %'.0Lf\n", + int128_to_double(endurance_group->media_units_written)); +} + void show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname) { /* convert temperature from Kelvin to Celsius */ @@ -2079,6 +2095,30 @@ void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname) json_free_object(root); } +void json_endurance_log(struct nvme_endurance_group_log *endurance_group, + __u16 group_id, const char *devname) +{ + struct json_object *root; + + long double endurance_estimate= int128_to_double(endurance_group->endurance_estimate); + long double data_units_read= int128_to_double(endurance_group->data_units_read); + long double data_units_written= int128_to_double(endurance_group->data_units_written); + long double media_units_written= int128_to_double(endurance_group->media_units_written); + + root = json_create_object(); + + json_object_add_value_int(root, "avl_spare_threshold", endurance_group->avl_spare_threshold); + json_object_add_value_int(root, "percent_used", endurance_group->percent_used); + json_object_add_value_float(root, "endurance_estimate", endurance_estimate); + json_object_add_value_float(root, "data_units_read", data_units_read); + json_object_add_value_float(root, "data_units_written", data_units_written); + json_object_add_value_float(root, "mediate_write_commands", media_units_written); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname) { struct json_object *root; diff --git a/nvme-print.h b/nvme-print.h index 748f6d03..3372b28e 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -26,6 +26,8 @@ void show_error_log(struct nvme_error_log_page *err_log, int entries, const char void show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, 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_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_ctrl_registers(void *bar, unsigned int mode, bool fabrics); void show_nvme_id_ns_descs(void *data); @@ -47,6 +49,8 @@ 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_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); 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 fad7fcc0..d460fb76 100644 --- a/nvme.c +++ b/nvme.c @@ -341,6 +341,57 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct return err; } +static int get_endurance_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + struct nvme_endurance_group_log endurance_log; + + const char *desc = "Retrieves endurance groups log page and prints the log."; + const char *group_id = "The endurance group identifier"; + + int err, fd; + int fmt; + + struct config { + char *output_format; + __u16 group_id; + }; + + struct config cfg = { + .output_format = "normal", + .group_id = 0, + }; + + const struct argconfig_commandline_options command_line_options[] = { + {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format}, + {"group-id", 'g', "NUM", CFG_SHORT, &cfg.group_id, required_argument, group_id}, + }; + + 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) + return fmt; + + err = nvme_endurance_log(fd, cfg.group_id, &endurance_log); + if (!err) { + if (fmt == BINARY) + d_raw((unsigned char *)&endurance_log, sizeof(endurance_log)); + else if (fmt == JSON) + json_endurance_log(&endurance_log, cfg.group_id, devicename); + else + show_endurance_log(&endurance_log, cfg.group_id, devicename); + } else if (err > 0) + fprintf(stderr, "NVMe Status:%s(%x)\n", + nvme_status_to_string(err), err); + else + perror("endurance log"); + + close(fd); + return err; +} + static int get_effects_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve command effects log page and print the table."; @@ -610,7 +661,7 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl } err = nvme_get_log13(fd, cfg.namespace_id, cfg.log_id, - cfg.lsp, cfg.lpo, + cfg.lsp, cfg.lpo, 0, cfg.log_len, log); if (!err) { if (!cfg.raw_binary) {