commit 4bad11866a349b7ae5d10869474f7c0fee740845 Author: Wen Xiong Date: Wed Jan 8 12:24:41 2020 -0800 Add additional smart log critical warn decoding Provide a user option to request additional smart log page decoding, and print out detailed critical warning when requested. Signed-off-by: Wendy Xiong [merge up, rename json keys] Signed-off-by: Keith Busch diff --git a/nvme-print.c b/nvme-print.c index 2ba1de1..46d5228 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -585,10 +585,11 @@ static void json_endurance_log(struct nvme_endurance_group_log *endurance_group, json_free_object(root); } -static void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid) +static void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, + enum nvme_print_flags flags) { + int c, human = flags & VERBOSE; struct json_object *root; - int c; char key[21]; unsigned int temperature = ((smart->temperature[1] << 8) | @@ -607,8 +608,22 @@ static void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid) root = json_create_object(); - json_object_add_value_int(root, "critical_warning", - smart->critical_warning); + if (human) { + struct json_object *crt = json_create_object(); + + json_object_add_value_int(crt, "value", smart->critical_warning); + json_object_add_value_int(crt, "available_spare", smart->critical_warning & 0x01); + json_object_add_value_int(crt, "temp_threshold", (smart->critical_warning & 0x02) >> 1); + json_object_add_value_int(crt, "reliability_degraded", (smart->critical_warning & 0x04) >> 2); + json_object_add_value_int(crt, "ro", (smart->critical_warning & 0x08) >> 3); + json_object_add_value_int(crt, "vmbu_failed", (smart->critical_warning & 0x10) >> 4); + json_object_add_value_int(crt, "pmr_ro", (smart->critical_warning & 0x20) >> 5); + + json_object_add_value_object(root, "critical_warning", crt); + } else + json_object_add_value_int(root, "critical_warning", + smart->critical_warning); + json_object_add_value_int(root, "temperature", temperature); json_object_add_value_int(root, "avail_spare", smart->avail_spare); json_object_add_value_int(root, "spare_thresh", smart->spare_thresh); @@ -3400,16 +3415,26 @@ void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, /* convert temperature from Kelvin to Celsius */ int temperature = ((smart->temperature[1] << 8) | smart->temperature[0]) - 273; - int i; + int i, human = flags & VERBOSE; if (flags & BINARY) return d_raw((unsigned char *)smart, sizeof(*smart)); else if (flags & JSON) - return json_smart_log(smart, nsid); + return json_smart_log(smart, nsid, flags); printf("Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid); printf("critical_warning : %#x\n", smart->critical_warning); + + if (human) { + printf(" Available Spare[0] : %d\n", smart->critical_warning & 0x01); + printf(" Temp. Threshold[1] : %d\n", (smart->critical_warning & 0x02) >> 1); + printf(" NVM subsystem Reliability[2] : %d\n", (smart->critical_warning & 0x04) >> 2); + printf(" Read-only[3] : %d\n", (smart->critical_warning & 0x08) >> 3); + printf(" Volatile mem. backup failed[4] : %d\n", (smart->critical_warning & 0x10) >> 4); + printf(" Persistent Mem. RO[5] : %d\n", (smart->critical_warning & 0x20) >> 5); + } + printf("temperature : %d C\n", temperature); printf("available_spare : %u%%\n", diff --git a/nvme.c b/nvme.c index 3b386bc..dd3ab58 100644 --- a/nvme.c +++ b/nvme.c @@ -218,6 +218,7 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug "(default) or binary."; const char *namespace = "(optional) desired namespace"; const char *raw = "output in binary format"; + const char *human_readable = "show info in readable format"; enum nvme_print_flags flags; int err, fd; @@ -225,6 +226,7 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug __u32 namespace_id; int raw_binary; char *output_format; + int human_readable; }; struct config cfg = { @@ -234,9 +236,10 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace), - OPT_FMT("output-format", 'o', &cfg.output_format, output_format), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), OPT_END() }; @@ -249,6 +252,8 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug goto close_fd; if (cfg.raw_binary) flags = BINARY; + if (cfg.human_readable) + flags |= VERBOSE; err = nvme_smart_log(fd, cfg.namespace_id, &smart_log); if (!err)