__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];
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,
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)
}
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,
if (lsp)
cmd.cdw10 |= lsp << 8;
- cmd.cdw11 = numdu;
+ cmd.cdw11 = numdu | (lsi << 16);
cmd.cdw12 = lpo;
cmd.cdw13 = (lpo >> 32);
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,
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)
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);
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);
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,
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 */
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;
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);
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);
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.";
}
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) {