Skip to content

Commit 6a73c83

Browse files
sbates130272igaw
authored andcommitted
ocp-nvme: Add a different formatting for JSON output
The current OCP JSON format for the SMART extended log page is not condusive to metric collection via tools like Prometheus. So we add a new output mode that uses all lower case and underscores (instead of spaces). This should help with metric collection. At the same time we clean up some of the field names. We add a new argument (--output-format-version) to allow us to select which output version we want. Documentation updated to reflect this change and mark this as experimental. Fixes #2577. Signed-off-by: Stephen Bates <[email protected]>
1 parent f258dca commit 6a73c83

File tree

6 files changed

+146
-10
lines changed

6 files changed

+146
-10
lines changed

Documentation/nvme-ocp-smart-add-log.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ compliant device
99
SYNOPSIS
1010
--------
1111
[verse]
12-
'nvme ocp smart-add-log' <device> [--output-format=<fmt> | -o <fmt>]
12+
'nvme ocp smart-add-log' <device> [--output-format=<fmt> | -o <fmt>] [--output-format-version=<version>]
1313

1414
DESCRIPTION
1515
-----------
@@ -22,6 +22,10 @@ device (ex: /dev/nvme0) or block device (ex: /dev/nvme0n1).
2222
This will only work on OCP compliant devices supporting this feature.
2323
Results for any other device are undefined.
2424

25+
EXPERIMENTAL. The --output-format-version can be set to 2 to generate field names
26+
for the outputs that are easier to process via scripts. Note this is
27+
experimental and the field names are subject to change.
28+
2529
On success it returns 0, error code otherwise.
2630

2731
OPTIONS
@@ -31,6 +35,10 @@ OPTIONS
3135
Set the reporting format to 'normal' or 'json'. Only one output format
3236
can be used at a time. The default is normal.
3337

38+
--output-format-version=<version>::
39+
Set the field labels in the reporting format to either '1'
40+
(the original) or '2'. The default is 1. Note this is experimental.
41+
3442
EXAMPLES
3543
--------
3644
* Has the program issue a smart-add-log command to retrieve the 0xC0 log page.

plugins/ocp/ocp-print-json.c

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ static void json_fw_activation_history(const struct fw_activation_history *fw_hi
136136
printf("\n");
137137
}
138138

139-
static void json_smart_extended_log(void *data)
139+
static void json_smart_extended_log_v1(void *data)
140140
{
141141
struct json_object *root;
142142
struct json_object *pmuw;
@@ -248,6 +248,129 @@ static void json_smart_extended_log(void *data)
248248
json_free_object(root);
249249
}
250250

251+
static void json_smart_extended_log_v2(void *data)
252+
{
253+
struct json_object *root;
254+
struct json_object *pmuw;
255+
struct json_object *pmur;
256+
uint16_t smart_log_ver = 0;
257+
__u8 *log_data = data;
258+
char guid[40];
259+
260+
root = json_create_object();
261+
pmuw = json_create_object();
262+
pmur = json_create_object();
263+
264+
json_object_add_value_uint64(pmuw, "hi",
265+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF));
266+
json_object_add_value_uint64(pmuw, "lo",
267+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
268+
json_object_add_value_object(root, "physical_media_units_written", pmuw);
269+
json_object_add_value_uint64(pmur, "hi",
270+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF));
271+
json_object_add_value_uint64(pmur, "lo",
272+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
273+
json_object_add_value_object(root, "physical_media_units_read", pmur);
274+
json_object_add_value_uint64(root, "bad_user_nand_blocks_raw",
275+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
276+
json_object_add_value_uint(root, "bad_user_nand_blocks_normalized",
277+
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
278+
json_object_add_value_uint64(root, "bad_system_nand_blocks_raw",
279+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
280+
json_object_add_value_uint(root, "bad_system_nand_blocks_normalized",
281+
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
282+
json_object_add_value_uint64(root, "xor_recovery_count",
283+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
284+
json_object_add_value_uint64(root, "uncorrectable_read_errors",
285+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
286+
json_object_add_value_uint64(root, "soft_ecc_error_count",
287+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
288+
json_object_add_value_uint(root, "end_to_end_detected_errors",
289+
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
290+
json_object_add_value_uint(root, "end_to_end_corrected_errors",
291+
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
292+
json_object_add_value_uint(root, "system_data_percent_used",
293+
(__u8)log_data[SCAO_SDPU]);
294+
json_object_add_value_uint64(root, "refresh_count",
295+
(uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF));
296+
json_object_add_value_uint(root, "max_user_data_erase_count",
297+
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
298+
json_object_add_value_uint(root, "min_user_data_erase_count",
299+
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
300+
json_object_add_value_uint(root, "thermal_throttling_events",
301+
(__u8)log_data[SCAO_NTTE]);
302+
json_object_add_value_uint(root, "current_throttling_status",
303+
(__u8)log_data[SCAO_CTS]);
304+
json_object_add_value_uint64(root, "pcie_correctable_errors",
305+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
306+
json_object_add_value_uint(root, "incomplete_shutdowns",
307+
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
308+
json_object_add_value_uint(root, "percent_free_blocks",
309+
(__u8)log_data[SCAO_PFB]);
310+
json_object_add_value_uint(root, "capacitor_health",
311+
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
312+
json_object_add_value_uint64(root, "unaligned_io",
313+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
314+
json_object_add_value_uint64(root, "security_version_number",
315+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
316+
json_object_add_value_uint64(root, "nuse_namespace_utilization",
317+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
318+
json_object_add_value_uint128(root, "plp_start_count",
319+
le128_to_cpu(&log_data[SCAO_PSC]));
320+
json_object_add_value_uint128(root, "endurance_estimate",
321+
le128_to_cpu(&log_data[SCAO_EEST]));
322+
smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]);
323+
324+
json_object_add_value_uint(root, "log_page_version", smart_log_ver);
325+
326+
memset((void *)guid, 0, 40);
327+
sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"",
328+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
329+
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG]));
330+
json_object_add_value_string(root, "log_page_guid", guid);
331+
332+
switch (smart_log_ver) {
333+
case 0 ... 1:
334+
break;
335+
default:
336+
case 4:
337+
json_object_add_value_uint(root, "nvme_command_set_errata_version",
338+
(__u8)log_data[SCAO_NCSEV]);
339+
json_object_add_value_uint(root, "lowest_permitted_firmware_revision",
340+
le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC]));
341+
fallthrough;
342+
case 2 ... 3:
343+
json_object_add_value_uint(root, "errata_version_field",
344+
(__u8)log_data[SCAO_EVF]);
345+
json_object_add_value_uint(root, "point_version_field",
346+
le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF]));
347+
json_object_add_value_uint(root, "minor_version_field",
348+
le16_to_cpu(*(uint16_t *)&log_data[SCAO_MIVF]));
349+
json_object_add_value_uint(root, "major_version_field",
350+
(__u8)log_data[SCAO_MAVF]);
351+
json_object_add_value_uint(root, "nvme_base_errata_version",
352+
(__u8)log_data[SCAO_NBEV]);
353+
json_object_add_value_uint(root, "pcie_link_retraining_count",
354+
le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
355+
json_object_add_value_uint(root, "power_state_change_count",
356+
le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC]));
357+
}
358+
json_print_object(root, NULL);
359+
printf("\n");
360+
json_free_object(root);
361+
}
362+
363+
static void json_smart_extended_log(void *data, unsigned int version)
364+
{
365+
switch (version) {
366+
default:
367+
case 1:
368+
json_smart_extended_log_v1(data);
369+
break;
370+
case 2:
371+
json_smart_extended_log_v2(data);
372+
}
373+
}
251374
static void json_telemetry_log(struct ocp_telemetry_parse_options *options)
252375
{
253376
print_ocp_telemetry_json(options);

plugins/ocp/ocp-print-stdout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ static void stdout_fw_activation_history(const struct fw_activation_history *fw_
9898
printf("\n");
9999
}
100100

101-
static void stdout_smart_extended_log(void *data)
101+
static void stdout_smart_extended_log(void *data, unsigned int version)
102102
{
103103
uint16_t smart_log_ver = 0;
104104
__u8 *log_data = data;

plugins/ocp/ocp-print.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ void ocp_fw_act_history(const struct fw_activation_history *fw_history, nvme_pri
3636
ocp_print(fw_act_history, flags, fw_history);
3737
}
3838

39-
void ocp_smart_extended_log(void *data, nvme_print_flags_t flags)
39+
void ocp_smart_extended_log(void *data, unsigned int version, nvme_print_flags_t flags)
4040
{
41-
ocp_print(smart_extended_log, flags, data);
41+
ocp_print(smart_extended_log, flags, data, version);
4242
}
4343

4444
void ocp_show_telemetry_log(struct ocp_telemetry_parse_options *options, nvme_print_flags_t flags)

plugins/ocp/ocp-print.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
struct ocp_print_ops {
1111
void (*hwcomp_log)(struct hwcomp_log *log, __u32 id, bool list);
1212
void (*fw_act_history)(const struct fw_activation_history *fw_history);
13-
void (*smart_extended_log)(void *data);
13+
void (*smart_extended_log)(void *data, unsigned int version);
1414
void (*telemetry_log)(struct ocp_telemetry_parse_options *options);
1515
void (*c3_log)(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data);
1616
void (*c5_log)(struct nvme_dev *dev, struct unsupported_requirement_log *log_data);
@@ -36,7 +36,7 @@ static inline struct ocp_print_ops *ocp_get_json_print_ops(nvme_print_flags_t fl
3636

3737
void ocp_show_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list, nvme_print_flags_t flags);
3838
void ocp_fw_act_history(const struct fw_activation_history *fw_history, nvme_print_flags_t flags);
39-
void ocp_smart_extended_log(void *data, nvme_print_flags_t flags);
39+
void ocp_smart_extended_log(void *data, unsigned int version, nvme_print_flags_t flags);
4040
void ocp_show_telemetry_log(struct ocp_telemetry_parse_options *options, nvme_print_flags_t flags);
4141
void ocp_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data,
4242
nvme_print_flags_t flags);

plugins/ocp/ocp-smart-extended-log.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ static __u8 scao_guid[GUID_LEN] = {
2727
0xC9, 0x14, 0xD5, 0xAF
2828
};
2929

30-
static int get_c0_log_page(struct nvme_dev *dev, char *format)
30+
static int get_c0_log_page(struct nvme_dev *dev, char *format,
31+
unsigned int format_version)
3132
{
3233
nvme_print_flags_t fmt;
3334
__u8 *data;
@@ -86,7 +87,7 @@ static int get_c0_log_page(struct nvme_dev *dev, char *format)
8687
}
8788

8889
/* print the data */
89-
ocp_smart_extended_log(data, fmt);
90+
ocp_smart_extended_log(data, format_version, fmt);
9091
} else {
9192
fprintf(stderr, "ERROR : OCP : Unable to read C0 data from buffer\n");
9293
}
@@ -105,22 +106,26 @@ int ocp_smart_add_log(int argc, char **argv, struct command *cmd,
105106

106107
struct config {
107108
char *output_format;
109+
unsigned int output_format_version;
108110
};
109111

110112
struct config cfg = {
111113
.output_format = "normal",
114+
.output_format_version = 1,
112115
};
113116

114117
OPT_ARGS(opts) = {
115118
OPT_FMT("output-format", 'o', &cfg.output_format, "output Format: normal|json"),
119+
OPT_UINT("output-format-version", 0, &cfg.output_format_version, "output Format version: 1|2"),
116120
OPT_END()
117121
};
118122

119123
ret = parse_and_open(&dev, argc, argv, desc, opts);
120124
if (ret)
121125
return ret;
122126

123-
ret = get_c0_log_page(dev, cfg.output_format);
127+
ret = get_c0_log_page(dev, cfg.output_format,
128+
cfg.output_format_version);
124129
if (ret)
125130
fprintf(stderr, "ERROR : OCP : Failure reading the C0 Log Page, ret = %d\n",
126131
ret);

0 commit comments

Comments
 (0)