mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zpcimon: Add JSON output for SMART data details
This uses the same format as: nvme smart-log --output-format=json /dev/nvmeX One complication being that several values in the SMART data use unsigned 128 bit integers. Both GCC and Clang support __uint128_t as a C extension but don't offer printf() support for it. Just like nvme-cli add a custom uint128_t to string function.. Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
2eceedeb11
commit
f1a11a01df
@@ -23,14 +23,116 @@
|
||||
#include "nvmemon.h"
|
||||
#include "zpcimon.h"
|
||||
|
||||
/**
|
||||
* Reads a CPU native 128 bit unsigned integer from the binary buffer @data
|
||||
* containing the value in the 128 bit little endian format used by the
|
||||
* NVMe standard.
|
||||
*
|
||||
* @return the 128 bit value encoded in the data buffer.
|
||||
*/
|
||||
static __uint128_t nvme_le128_to_cpu(const __u8 data[16])
|
||||
{
|
||||
__uint128_t u;
|
||||
int i;
|
||||
|
||||
u = data[0];
|
||||
for (i = 1; i < (int)sizeof(u); i++)
|
||||
u |= (__uint128_t)data[i] << (8 * i);
|
||||
return u;
|
||||
}
|
||||
|
||||
#define MAX_UINT128_DECIMAL_LEN (41) /* length of 2^128-1 in decimal + 0 byte */
|
||||
|
||||
/**
|
||||
* Write the decimal string representation of the passed unsigned 128 bit value @val into
|
||||
* the buffer @buf for output in JSON. The representation does not include
|
||||
* quotes.
|
||||
*/
|
||||
static void nvme_u128_to_json_val(__uint128_t val, char buf[MAX_UINT128_DECIMAL_LEN])
|
||||
{
|
||||
const char *digit_ascii = "0123456789";
|
||||
int pos = MAX_UINT128_DECIMAL_LEN - 1;
|
||||
int mod_ten;
|
||||
int len;
|
||||
|
||||
/* Write digits right to left at the end of res */
|
||||
do {
|
||||
mod_ten = val % 10;
|
||||
val /= 10;
|
||||
buf[pos--] = digit_ascii[mod_ten];
|
||||
} while (val);
|
||||
/* Move digits to the front */
|
||||
len = MAX_UINT128_DECIMAL_LEN - 1 - pos;
|
||||
memmove(buf, &buf[pos + 1], len);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
|
||||
static void nvme_json_print_smart_log(struct zpcimon_ctx *ctx, struct nvme_smart_log *log)
|
||||
{
|
||||
char u128_num_buf[MAX_UINT128_DECIMAL_LEN];
|
||||
unsigned int temperature;
|
||||
|
||||
/* While some fields in struct nvme_smart_log are __leXX
|
||||
* temperature is an array of two u8 of the little endian data
|
||||
* in Kelvin.
|
||||
*/
|
||||
temperature = log->temperature[1] << 8 | log->temperature[0];
|
||||
|
||||
util_fmt_obj_start(FMT_DEFAULT, "smart-log");
|
||||
util_fmt_pair(FMT_DEFAULT, "critical_warning", "%d", log->critical_warning);
|
||||
util_fmt_pair(FMT_DEFAULT, "temperature", "%d", temperature);
|
||||
util_fmt_pair(FMT_DEFAULT, "avail_spare", "%d", log->avail_spare);
|
||||
util_fmt_pair(FMT_DEFAULT, "spare_thresh", "%d", log->spare_thresh);
|
||||
util_fmt_pair(FMT_DEFAULT, "percent_used", "%d", log->percent_used);
|
||||
util_fmt_pair(FMT_DEFAULT, "endurance_grp_critical_warning_summary", "%d",
|
||||
log->endu_grp_crit_warn_sumry);
|
||||
nvme_u128_to_json_val(nvme_le128_to_cpu(log->data_units_read), u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "data_units_read", "%s", u128_num_buf);
|
||||
nvme_u128_to_json_val(nvme_le128_to_cpu(log->data_units_written), u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "data_units_written", "%s", u128_num_buf);
|
||||
nvme_u128_to_json_val(nvme_le128_to_cpu(log->host_reads), u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "host_read_commands", "%s", u128_num_buf);
|
||||
nvme_u128_to_json_val(nvme_le128_to_cpu(log->host_writes), u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "host_write_commands", "%s", u128_num_buf);
|
||||
nvme_u128_to_json_val(nvme_le128_to_cpu(log->ctrl_busy_time), u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "controller_busy_time", "%s", u128_num_buf);
|
||||
nvme_u128_to_json_val(nvme_le128_to_cpu(log->power_cycles), u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "power_cycles", "%s", u128_num_buf);
|
||||
/* 2^128 hours is 2.8*10^24 times the age of the universe ;) */
|
||||
nvme_u128_to_json_val(nvme_le128_to_cpu(log->power_on_hours), u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "power_on_hours", "%s", u128_num_buf);
|
||||
nvme_u128_to_json_val(nvme_le128_to_cpu(log->unsafe_shutdowns), u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "unsafe_shutdowns", "%s", u128_num_buf);
|
||||
nvme_u128_to_json_val(nvme_le128_to_cpu(log->media_errors), u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "media_errors", "%s", u128_num_buf);
|
||||
nvme_u128_to_json_val(nvme_le128_to_cpu(log->num_err_log_entries), u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "num_err_log_entries", "%s", u128_num_buf);
|
||||
util_fmt_pair(FMT_DEFAULT, "warning_temp_time", "%d", le32toh(log->warning_temp_time));
|
||||
util_fmt_pair(FMT_DEFAULT, "critical_comp_time", "%d", le32toh(log->critical_comp_time));
|
||||
util_fmt_pair(FMT_DEFAULT, "temperature_sensor_1", "%d", le16toh(log->temp_sensor[0]));
|
||||
util_fmt_pair(FMT_DEFAULT, "temperature_sensor_2", "%d", le16toh(log->temp_sensor[1]));
|
||||
util_fmt_pair(FMT_DEFAULT, "temperature_sensor_3", "%d", le16toh(log->temp_sensor[2]));
|
||||
util_fmt_pair(FMT_DEFAULT, "thm_temp1_trans_count", "%d",
|
||||
le32toh(log->thm_temp1_trans_count));
|
||||
util_fmt_pair(FMT_DEFAULT, "thm_temp2_trans_count", "%d",
|
||||
le32toh(log->thm_temp2_trans_count));
|
||||
util_fmt_pair(FMT_DEFAULT, "thm_temp1_total_time", "%d",
|
||||
le32toh(log->thm_temp1_total_time));
|
||||
util_fmt_pair(FMT_DEFAULT, "thm_temp2_total_time", "%d",
|
||||
le32toh(log->thm_temp2_total_time));
|
||||
util_fmt_obj_end(); /* smart-log */
|
||||
|
||||
if (ctx->opts.smart_blob)
|
||||
zpcimon_json_base64_pair("smart-log-raw", (uint8_t *)log, sizeof(*log));
|
||||
}
|
||||
|
||||
static void nvme_json_print(struct zpcimon_ctx *ctx, struct zpci_dev *zdev, const char *name,
|
||||
struct nvme_smart_log *log)
|
||||
{
|
||||
zpci_adapter_json_print_start(zdev);
|
||||
util_fmt_obj_start(FMT_DEFAULT, "nvmedev");
|
||||
util_fmt_pair(FMT_QUOTE, "dev", name);
|
||||
if (ctx->opts.smart_blob)
|
||||
zpcimon_json_base64_pair("smart-log-raw", (uint8_t *)log, sizeof(*log));
|
||||
nvme_json_print_smart_log(ctx, log);
|
||||
util_fmt_obj_end();
|
||||
zpci_adapter_json_print_end();
|
||||
fflush(stdout);
|
||||
|
||||
Reference in New Issue
Block a user