Bug Summary

File:.build-ci/../plugins/intel/intel-nvme.c
Warning:line 1406, column 10
Potential leak of memory pointed to by 'intel'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name intel-nvme.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/bin/../lib/clang/22 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -I src -I ../src -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu11 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-09-23-073103-589-1 -x c ../plugins/intel/intel-nvme.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2#include <errno(*__errno_location ()).h>
3#include <fcntl.h>
4#include <inttypes.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
8
9#include <libnvme.h>
10
11#include <ccan/endian/endian.h>
12#include <ccan/minmax/minmax.h>
13#include <shared/compiler-attributes-util.h>
14#include <shared/fs-util.h>
15#include <shared/parse-util.h>
16
17#include "cleanup.h"
18#include "global-ctx.h"
19#include "nvme-cmds.h"
20#include "nvme-print.h"
21#include "plugin.h"
22
23struct __packed__attribute__((__packed__)) nvme_additional_smart_log_item {
24 __u8 key;
25 __u8 _kp[2];
26 __u8 norm;
27 __u8 _np;
28 union __packed__attribute__((__packed__)) {
29 __u8 raw[6];
30 struct __packed__attribute__((__packed__)) wear_level {
31 __le16 min;
32 __le16 max;
33 __le16 avg;
34 } wear_level;
35 struct __packed__attribute__((__packed__)) thermal_throttle {
36 __u8 pct;
37 __u32 count;
38 } thermal_throttle;
39 };
40 __u8 _rp;
41};
42
43struct nvme_additional_smart_log {
44 struct nvme_additional_smart_log_item program_fail_cnt;
45 struct nvme_additional_smart_log_item erase_fail_cnt;
46 struct nvme_additional_smart_log_item wear_leveling_cnt;
47 struct nvme_additional_smart_log_item e2e_err_cnt;
48 struct nvme_additional_smart_log_item crc_err_cnt;
49 struct nvme_additional_smart_log_item timed_workload_media_wear;
50 struct nvme_additional_smart_log_item timed_workload_host_reads;
51 struct nvme_additional_smart_log_item timed_workload_timer;
52 struct nvme_additional_smart_log_item thermal_throttle_status;
53 struct nvme_additional_smart_log_item retry_buffer_overflow_cnt;
54 struct nvme_additional_smart_log_item pll_lock_loss_cnt;
55 struct nvme_additional_smart_log_item nand_bytes_written;
56 struct nvme_additional_smart_log_item host_bytes_written;
57 struct nvme_additional_smart_log_item host_ctx_wear_used;
58 struct nvme_additional_smart_log_item perf_stat_indicator;
59 struct nvme_additional_smart_log_item re_alloc_sectr_cnt;
60 struct nvme_additional_smart_log_item soft_ecc_err_rate;
61 struct nvme_additional_smart_log_item unexp_power_loss;
62 struct nvme_additional_smart_log_item media_bytes_read;
63 struct nvme_additional_smart_log_item avail_fw_downgrades;
64};
65
66struct nvme_vu_id_ctrl_field { /* CDR MR5 */
67 __u8 rsvd1[3];
68 __u8 ss;
69 __u8 health[20];
70 __u8 cls;
71 __u8 nlw;
72 __u8 scap;
73 __u8 sstat;
74 __u8 bl[8];
75 __u8 rsvd2[38];
76 __u8 ww[8]; /* little endian */
77 __u8 mic_bl[4];
78 __u8 mic_fw[4];
79};
80
81static void json_intel_id_ctrl(struct nvme_vu_id_ctrl_field *id,
82 char *health, char *bl, char *ww, char *mic_bl, char *mic_fw,
83 struct json_object *root)
84{
85 json_object_add_value_int(root, "ss", id->ss)json_object_object_add(root, "ss", json_object_new_int(id->
ss))
;
86 json_object_add_value_string(root, "health", health);
87 json_object_add_value_int(root, "cls", id->cls)json_object_object_add(root, "cls", json_object_new_int(id->
cls))
;
88 json_object_add_value_int(root, "nlw", id->nlw)json_object_object_add(root, "nlw", json_object_new_int(id->
nlw))
;
89 json_object_add_value_int(root, "scap", id->scap)json_object_object_add(root, "scap", json_object_new_int(id->
scap))
;
90 json_object_add_value_int(root, "sstat", id->sstat)json_object_object_add(root, "sstat", json_object_new_int(id->
sstat))
;
91 json_object_add_value_string(root, "bl", bl);
92 json_object_add_value_string(root, "ww", ww);
93 json_object_add_value_string(root, "mic_bl", mic_bl);
94 json_object_add_value_string(root, "mic_fw", mic_fw);
95}
96
97static void intel_id_ctrl(__u8 *vs, struct json_object *root)
98{
99 struct nvme_vu_id_ctrl_field *id = (struct nvme_vu_id_ctrl_field *)vs;
100
101 char health[21] = { 0 };
102 char bl[9] = { 0 };
103 char ww[19] = { 0 };
104 char mic_bl[5] = { 0 };
105 char mic_fw[5] = { 0 };
106
107 if (id->health[0] == 0)
108 snprintf(health, 21, "%s", "healthy");
109 else
110 snprintf(health, 21, "%s", id->health);
111
112 snprintf(bl, 9, "%s", id->bl);
113 snprintf(ww, 19, "%02X%02X%02X%02X%02X%02X%02X%02X", id->ww[7],
114 id->ww[6], id->ww[5], id->ww[4], id->ww[3], id->ww[2],
115 id->ww[1], id->ww[0]);
116 snprintf(mic_bl, 5, "%s", id->mic_bl);
117 snprintf(mic_fw, 5, "%s", id->mic_fw);
118
119 if (root) {
120 json_intel_id_ctrl(id, health, bl, ww, mic_bl, mic_fw, root);
121 return;
122 }
123
124 printf("ss : %d\n", id->ss);
125 printf("health : %s\n", health);
126 printf("cls : %d\n", id->cls);
127 printf("nlw : %d\n", id->nlw);
128 printf("scap : %d\n", id->scap);
129 printf("sstat : %d\n", id->sstat);
130 printf("bl : %s\n", bl);
131 printf("ww : %s\n", ww);
132 printf("mic_bl : %s\n", mic_bl);
133 printf("mic_fw : %s\n", mic_fw);
134}
135
136static int id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin)
137{
138 return __id_ctrl(argc, argv, acmd, plugin, intel_id_ctrl);
139}
140
141static void
142show_intel_smart_log_jsn(struct nvme_additional_smart_log *smart,
143 unsigned int nsid, const char *devname)
144{
145 struct json_object *root, *entry_stats, *dev_stats, *multi;
146
147 root = json_create_object()json_object_new_object();
148 json_object_add_value_string(root, "Intel Smart log", devname);
149
150 dev_stats = json_create_object()json_object_new_object();
151
152 entry_stats = json_create_object()json_object_new_object();
153 json_object_add_value_int(entry_stats, "normalized", smart->program_fail_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->program_fail_cnt.norm))
;
154 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->program_fail_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->program_fail_cnt.raw)))
;
155 json_object_add_value_object(dev_stats, "program_fail_count", entry_stats)json_object_object_add(dev_stats, "program_fail_count", entry_stats
)
;
156
157 entry_stats = json_create_object()json_object_new_object();
158 json_object_add_value_int(entry_stats, "normalized", smart->erase_fail_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->erase_fail_cnt.norm))
;
159 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->erase_fail_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->erase_fail_cnt.raw)))
;
160 json_object_add_value_object(dev_stats, "erase_fail_count", entry_stats)json_object_object_add(dev_stats, "erase_fail_count", entry_stats
)
;
161
162 entry_stats = json_create_object()json_object_new_object();
163 json_object_add_value_int(entry_stats, "normalized", smart->wear_leveling_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->wear_leveling_cnt.norm))
;
164 multi = json_create_object()json_object_new_object();
165 json_object_add_value_int(multi, "min", le16_to_cpu(smart->wear_leveling_cnt.wear_level.min))json_object_object_add(multi, "min", json_object_new_int(le16_to_cpu
(smart->wear_leveling_cnt.wear_level.min)))
;
166 json_object_add_value_int(multi, "max", le16_to_cpu(smart->wear_leveling_cnt.wear_level.max))json_object_object_add(multi, "max", json_object_new_int(le16_to_cpu
(smart->wear_leveling_cnt.wear_level.max)))
;
167 json_object_add_value_int(multi, "avg", le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg))json_object_object_add(multi, "avg", json_object_new_int(le16_to_cpu
(smart->wear_leveling_cnt.wear_level.avg)))
;
168 json_object_add_value_object(entry_stats, "raw", multi)json_object_object_add(entry_stats, "raw", multi);
169 json_object_add_value_object(dev_stats, "wear_leveling", entry_stats)json_object_object_add(dev_stats, "wear_leveling", entry_stats
)
;
170
171 entry_stats = json_create_object()json_object_new_object();
172 json_object_add_value_int(entry_stats, "normalized", smart->e2e_err_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->e2e_err_cnt.norm))
;
173 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->e2e_err_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->e2e_err_cnt.raw)))
;
174 json_object_add_value_object(dev_stats, "end_to_end_error_detection_count", entry_stats)json_object_object_add(dev_stats, "end_to_end_error_detection_count"
, entry_stats)
;
175
176 entry_stats = json_create_object()json_object_new_object();
177 json_object_add_value_int(entry_stats, "normalized", smart->crc_err_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->crc_err_cnt.norm))
;
178 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->crc_err_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->crc_err_cnt.raw)))
;
179 json_object_add_value_object(dev_stats, "crc_error_count", entry_stats)json_object_object_add(dev_stats, "crc_error_count", entry_stats
)
;
180
181 entry_stats = json_create_object()json_object_new_object();
182 json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_media_wear.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->timed_workload_media_wear.norm))
;
183 json_object_add_value_double(entry_stats, "raw", ((long double)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024)json_object_object_add(entry_stats, "raw", util_json_object_new_double
(((long double)int48_to_long(smart->timed_workload_media_wear
.raw)) / 1024))
;
184 json_object_add_value_object(dev_stats, "timed_workload_media_wear", entry_stats)json_object_object_add(dev_stats, "timed_workload_media_wear"
, entry_stats)
;
185
186 entry_stats = json_create_object()json_object_new_object();
187 json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_host_reads.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->timed_workload_host_reads.norm))
;
188 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->timed_workload_host_reads.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->timed_workload_host_reads.raw)))
;
189 json_object_add_value_object(dev_stats, "timed_workload_host_reads", entry_stats)json_object_object_add(dev_stats, "timed_workload_host_reads"
, entry_stats)
;
190
191 entry_stats = json_create_object()json_object_new_object();
192 json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_timer.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->timed_workload_timer.norm))
;
193 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->timed_workload_timer.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->timed_workload_timer.raw)))
;
194 json_object_add_value_object(dev_stats, "timed_workload_timer", entry_stats)json_object_object_add(dev_stats, "timed_workload_timer", entry_stats
)
;
195
196 entry_stats = json_create_object()json_object_new_object();
197 json_object_add_value_int(entry_stats, "normalized", smart->thermal_throttle_status.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->thermal_throttle_status.norm))
;
198 multi = json_create_object()json_object_new_object();
199 json_object_add_value_int(multi, "pct", smart->thermal_throttle_status.thermal_throttle.pct)json_object_object_add(multi, "pct", json_object_new_int(smart
->thermal_throttle_status.thermal_throttle.pct))
;
200 json_object_add_value_int(multi, "cnt", smart->thermal_throttle_status.thermal_throttle.count)json_object_object_add(multi, "cnt", json_object_new_int(smart
->thermal_throttle_status.thermal_throttle.count))
;
201 json_object_add_value_object(entry_stats, "raw", multi)json_object_object_add(entry_stats, "raw", multi);
202 json_object_add_value_object(dev_stats, "thermal_throttle_status", entry_stats)json_object_object_add(dev_stats, "thermal_throttle_status", entry_stats
)
;
203
204 entry_stats = json_create_object()json_object_new_object();
205 json_object_add_value_int(entry_stats, "normalized", smart->retry_buffer_overflow_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->retry_buffer_overflow_cnt.norm))
;
206 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->retry_buffer_overflow_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->retry_buffer_overflow_cnt.raw)))
;
207 json_object_add_value_object(dev_stats, "retry_buffer_overflow_count", entry_stats)json_object_object_add(dev_stats, "retry_buffer_overflow_count"
, entry_stats)
;
208
209 entry_stats = json_create_object()json_object_new_object();
210 json_object_add_value_int(entry_stats, "normalized", smart->pll_lock_loss_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->pll_lock_loss_cnt.norm))
;
211 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->pll_lock_loss_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->pll_lock_loss_cnt.raw)))
;
212 json_object_add_value_object(dev_stats, "pll_lock_loss_count", entry_stats)json_object_object_add(dev_stats, "pll_lock_loss_count", entry_stats
)
;
213
214 entry_stats = json_create_object()json_object_new_object();
215 json_object_add_value_int(entry_stats, "normalized", smart->nand_bytes_written.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->nand_bytes_written.norm))
;
216 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->nand_bytes_written.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->nand_bytes_written.raw)))
;
217 json_object_add_value_object(dev_stats, "nand_bytes_written", entry_stats)json_object_object_add(dev_stats, "nand_bytes_written", entry_stats
)
;
218
219 entry_stats = json_create_object()json_object_new_object();
220 json_object_add_value_int(entry_stats, "normalized", smart->host_bytes_written.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->host_bytes_written.norm))
;
221 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_bytes_written.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->host_bytes_written.raw)))
;
222 json_object_add_value_object(dev_stats, "host_bytes_written", entry_stats)json_object_object_add(dev_stats, "host_bytes_written", entry_stats
)
;
223
224 entry_stats = json_create_object()json_object_new_object();
225 json_object_add_value_int(entry_stats, "normalized", smart->host_ctx_wear_used.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->host_ctx_wear_used.norm))
;
226 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_ctx_wear_used.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->host_ctx_wear_used.raw)))
;
227 json_object_add_value_object(dev_stats, "host_ctx_wear_used", entry_stats)json_object_object_add(dev_stats, "host_ctx_wear_used", entry_stats
)
;
228
229 entry_stats = json_create_object()json_object_new_object();
230 json_object_add_value_int(entry_stats, "normalized", smart->perf_stat_indicator.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->perf_stat_indicator.norm))
;
231 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->perf_stat_indicator.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->perf_stat_indicator.raw)))
;
232 json_object_add_value_object(dev_stats, "perf_stat_indicator", entry_stats)json_object_object_add(dev_stats, "perf_stat_indicator", entry_stats
)
;
233
234 entry_stats = json_create_object()json_object_new_object();
235 json_object_add_value_int(entry_stats, "normalized", smart->re_alloc_sectr_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->re_alloc_sectr_cnt.norm))
;
236 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->re_alloc_sectr_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->re_alloc_sectr_cnt.raw)))
;
237 json_object_add_value_object(dev_stats, "re_alloc_sectr_cnt", entry_stats)json_object_object_add(dev_stats, "re_alloc_sectr_cnt", entry_stats
)
;
238
239 entry_stats = json_create_object()json_object_new_object();
240 json_object_add_value_int(entry_stats, "normalized", smart->soft_ecc_err_rate.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->soft_ecc_err_rate.norm))
;
241 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->soft_ecc_err_rate.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->soft_ecc_err_rate.raw)))
;
242 json_object_add_value_object(dev_stats, "soft_ecc_err_rate", entry_stats)json_object_object_add(dev_stats, "soft_ecc_err_rate", entry_stats
)
;
243
244 entry_stats = json_create_object()json_object_new_object();
245 json_object_add_value_int(entry_stats, "normalized", smart->unexp_power_loss.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->unexp_power_loss.norm))
;
246 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->unexp_power_loss.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->unexp_power_loss.raw)))
;
247 json_object_add_value_object(dev_stats, "unexp_power_loss", entry_stats)json_object_object_add(dev_stats, "unexp_power_loss", entry_stats
)
;
248
249 entry_stats = json_create_object()json_object_new_object();
250 json_object_add_value_int(entry_stats, "normalized", smart->media_bytes_read.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->media_bytes_read.norm))
;
251 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->media_bytes_read.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->media_bytes_read.raw)))
;
252 json_object_add_value_object(dev_stats, "media_bytes_read", entry_stats)json_object_object_add(dev_stats, "media_bytes_read", entry_stats
)
;
253
254 entry_stats = json_create_object()json_object_new_object();
255 json_object_add_value_int(entry_stats, "normalized", smart->avail_fw_downgrades.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->avail_fw_downgrades.norm))
;
256 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->avail_fw_downgrades.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->avail_fw_downgrades.raw)))
;
257 json_object_add_value_object(dev_stats, "avail_fw_downgrades", entry_stats)json_object_object_add(dev_stats, "avail_fw_downgrades", entry_stats
)
;
258
259 json_object_add_value_object(root, "Device stats", dev_stats)json_object_object_add(root, "Device stats", dev_stats);
260
261 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
262 printf("\n");
263 json_free_object(root)json_object_put(root);
264}
265
266static char *id_to_key(__u8 id)
267{
268 switch (id) {
269 case 0xAB:
270 return "program_fail_count";
271 case 0xAC:
272 return "erase_fail_count";
273 case 0xAD:
274 return "wear_leveling_count";
275 case 0xB8:
276 return "e2e_error_detect_count";
277 case 0xC7:
278 return "crc_error_count";
279 case 0xE2:
280 return "media_wear_percentage";
281 case 0xE3:
282 return "host_reads";
283 case 0xE4:
284 return "timed_work_load";
285 case 0xEA:
286 return "thermal_throttle_status";
287 case 0xF0:
288 return "retry_buff_overflow_count";
289 case 0xF3:
290 return "pll_lock_loss_counter";
291 case 0xF4:
292 return "nand_bytes_written";
293 case 0xF5:
294 return "host_bytes_written";
295 case 0xF6:
296 return "host_context_wear_used";
297 case 0xF7:
298 return "performance_status_indicator";
299 case 0xF8:
300 return "media_bytes_read";
301 case 0xF9:
302 return "available_fw_downgrades";
303 case 0x05:
304 return "re-allocated_sector_count";
305 case 0x0D:
306 return "soft_ecc_error_rate";
307 case 0xAE:
308 return "unexpected_power_loss";
309 default:
310 return "Invalid ID";
311 }
312}
313
314static void print_intel_smart_log_items(struct nvme_additional_smart_log_item *item)
315{
316 if (!item->key)
317 return;
318
319 printf("%#x %-45s %3d %"PRIu64"l" "u""\n",
320 item->key, id_to_key(item->key),
321 item->norm, int48_to_long(item->raw));
322}
323
324static void show_intel_smart_log(struct nvme_additional_smart_log *smart,
325 unsigned int nsid, const char *devname)
326{
327 struct nvme_additional_smart_log_item *iter = &smart->program_fail_cnt;
328 int num_items = sizeof(struct nvme_additional_smart_log) /
329 sizeof(struct nvme_additional_smart_log_item);
330
331 printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
332 devname, nsid);
333 printf("ID KEY Normalized Raw\n");
334
335 for (int i = 0; i < num_items; i++, iter++)
336 print_intel_smart_log_items(iter);
337}
338
339static int get_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
340{
341 const char *desc =
342 "Get Intel vendor specific additional smart log (optionally, for the specified namespace), and show it.";
343 const char *namespace = "(optional) desired namespace";
344 const char *raw = "Dump output in binary format";
345#ifdef CONFIG_JSONC
346 const char *json = "Dump output in json format";
347#endif /* CONFIG_JSONC */
348
349 struct nvme_additional_smart_log smart_log;
350 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
351 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
352 nvme_print_flags_t flags;
353 int err;
354
355 struct config {
356 __u32 namespace_id;
357 bool_Bool raw_binary;
358 bool_Bool json;
359 };
360
361 struct config cfg = {
362 .namespace_id = NVME_NSID_ALL,
363 };
364
365 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG
, &cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0)
, CFG_FLAG, &cfg.json, 0, json, 0, }, {"", 0, ((void*)0),
CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options", 0, ((void
*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &nvme_args.
verbose, 0, "Increase output verbosity", 0, }, {"quiet", 0, (
(void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
366 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG
, &cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0)
, CFG_FLAG, &cfg.json, 0, json, 0, }, {"", 0, ((void*)0),
CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options", 0, ((void
*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &nvme_args.
verbose, 0, "Increase output verbosity", 0, }, {"quiet", 0, (
(void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
367 OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG
, &cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0)
, CFG_FLAG, &cfg.json, 0, json, 0, }, {"", 0, ((void*)0),
CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options", 0, ((void
*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &nvme_args.
verbose, 0, "Increase output verbosity", 0, }, {"quiet", 0, (
(void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
368 OPT_FLAG_JSON("json", 'j', &cfg.json, json))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG
, &cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0)
, CFG_FLAG, &cfg.json, 0, json, 0, }, {"", 0, ((void*)0),
CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options", 0, ((void
*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &nvme_args.
verbose, 0, "Increase output verbosity", 0, }, {"quiet", 0, (
(void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
369
370 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
371 if (err)
372 return err;
373
374 err = validate_output_format(nvme_args.output_format, &flags);
375 if (err < 0) {
376 nvme_show_error("Invalid output format")nvme_show_message(1, "Invalid output format");
377 return err;
378 }
379
380 err = nvme_get_log_simple(hdl, 0xca, &smart_log, sizeof(smart_log));
381 if (!err) {
382 if (flags & JSON || cfg.json)
383 show_intel_smart_log_jsn(&smart_log, cfg.namespace_id,
384 libnvme_transport_handle_get_name(hdl));
385 else if (!cfg.raw_binary)
386 show_intel_smart_log(&smart_log, cfg.namespace_id,
387 libnvme_transport_handle_get_name(hdl));
388 else
389 d_raw((unsigned char *)&smart_log, sizeof(smart_log));
390 } else if (err > 0) {
391 nvme_show_status(err);
392 }
393 return err;
394}
395
396static int get_market_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
397{
398 const char *desc = "Get Intel Marketing Name log and show it.";
399 const char *raw = "dump output in binary format";
400 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
401 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
402 char log[512];
403 int err;
404
405 struct config {
406 bool_Bool raw_binary;
407 };
408
409 struct config cfg = {
410 };
411
412 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, raw, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress informational output", 0, }, {"output-format",
'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
413 OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, raw, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress informational output", 0, }, {"output-format",
'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
414
415 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
416 if (err)
417 return err;
418
419 err = nvme_get_log_simple(hdl, 0xdd, log, sizeof(log));
420 if (!err) {
421 if (!cfg.raw_binary)
422 printf("Intel Marketing Name Log:\n%s\n", log);
423 else
424 d_raw((unsigned char *)&log, sizeof(log));
425 } else if (err > 0)
426 nvme_show_status(err);
427 return err;
428}
429
430struct intel_temp_stats {
431 __le64 curr;
432 __le64 last_overtemp;
433 __le64 life_overtemp;
434 __le64 highest_temp;
435 __le64 lowest_temp;
436 __u8 rsvd[40];
437 __le64 max_operating_temp;
438 __le64 min_operating_temp;
439 __le64 est_offset;
440};
441
442static void show_temp_stats(struct intel_temp_stats *stats)
443{
444 printf(" Intel Temperature Statistics\n");
445 printf("--------------------------------\n");
446 printf("Current temperature : %"PRIu64"l" "u""\n", le64_to_cpu(stats->curr));
447 printf("Last critical overtemp flag : %"PRIu64"l" "u""\n", le64_to_cpu(stats->last_overtemp));
448 printf("Life critical overtemp flag : %"PRIu64"l" "u""\n", le64_to_cpu(stats->life_overtemp));
449 printf("Highest temperature : %"PRIu64"l" "u""\n", le64_to_cpu(stats->highest_temp));
450 printf("Lowest temperature : %"PRIu64"l" "u""\n", le64_to_cpu(stats->lowest_temp));
451 printf("Max operating temperature : %"PRIu64"l" "u""\n", le64_to_cpu(stats->max_operating_temp));
452 printf("Min operating temperature : %"PRIu64"l" "u""\n", le64_to_cpu(stats->min_operating_temp));
453 printf("Estimated offset : %"PRIu64"l" "u""\n", le64_to_cpu(stats->est_offset));
454}
455
456static int get_temp_stats_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
457{
458 struct intel_temp_stats stats;
459 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
460 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
461 int err;
462
463 const char *desc = "Get Temperature Statistics log and show it.";
464 const char *raw = "dump output in binary format";
465 struct config {
466 bool_Bool raw_binary;
467 };
468
469 struct config cfg = {
470 };
471
472 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, raw, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress informational output", 0, }, {"output-format",
'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
473 OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, raw, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress informational output", 0, }, {"output-format",
'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
474
475 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
476 if (err)
477 return err;
478
479 err = nvme_get_log_simple(hdl, 0xc5, &stats, sizeof(stats));
480 if (!err) {
481 if (!cfg.raw_binary)
482 show_temp_stats(&stats);
483 else
484 d_raw((unsigned char *)&stats, sizeof(stats));
485 } else if (err > 0)
486 nvme_show_status(err);
487 return err;
488}
489
490struct intel_lat_stats {
491 __u16 maj;
492 __u16 min;
493 __u32 data[1216];
494};
495
496struct __packed__attribute__((__packed__)) optane_lat_stats {
497 __u16 maj;
498 __u16 min;
499 __u64 data[9];
500};
501
502#define MEDIA_MAJOR_IDX0 0
503#define MEDIA_MINOR_IDX1 1
504#define MEDIA_MAX_LEN2 2
505#define OPTANE_V1000_BUCKET_LEN8 8
506#define OPTANE_V1000_BUCKET_LEN8 8
507#define NAND_LAT_STATS_LEN4868 4868
508
509
510static struct intel_lat_stats stats;
511static struct optane_lat_stats v1000_stats;
512
513struct v1000_thresholds {
514 __u32 read[OPTANE_V1000_BUCKET_LEN8];
515 __u32 write[OPTANE_V1000_BUCKET_LEN8];
516};
517
518static struct v1000_thresholds v1000_bucket;
519static __u16 media_version[MEDIA_MAX_LEN2] = {0};
520
521enum FormatUnit {
522 US,
523 MS,
524 S
525};
526
527/*
528 * COL_WIDTH controls width of columns in human-readable output.
529 * BUFSIZE is for local temp char[]
530 * US_IN_S and US_IN_MS are for unit conversions when printing.
531 */
532#define COL_WIDTH12 12
533#define BUFSIZE10 10
534#define US_IN_S1000000 1000000
535#define US_IN_MS1000 1000
536
537static enum FormatUnit get_seconds_magnitude(__u32 microseconds)
538{
539 if (microseconds > US_IN_S1000000)
540 return S;
541 else if (microseconds > US_IN_MS1000)
542 return MS;
543 else
544 return US;
545}
546
547static float convert_seconds(__u32 microseconds)
548{
549 float divisor = 1.0;
550
551 if (microseconds > US_IN_S1000000)
552 divisor = US_IN_S1000000;
553 else if (microseconds > US_IN_MS1000)
554 divisor = US_IN_MS1000;
555 return microseconds / divisor;
556}
557
558/*
559 * For control over whether a string will format to +/-INF or
560 * print out ####.##US normally.
561 */
562enum inf_bound_type {
563 NEGINF,
564 POSINF,
565 NOINF
566};
567
568/*
569 * Edge buckets may have range [#s, inf) or (-inf, #US] in some
570 * latency statistics formats.
571 * Passing in NEGINF to POSINF to bound_type overrides the string to
572 * either of "-INF" or "+INF", respectively.
573 */
574static void set_unit_string(char *buffer, __u32 microseconds,
575 enum FormatUnit unit,
576 enum inf_bound_type bound_type)
577{
578 char *string;
579
580 if (bound_type != NOINF) {
581 snprintf(buffer, BUFSIZE10, "%s", bound_type ? "+INF" : "-INF");
582 return;
583 }
584
585 switch (unit) {
586 case US:
587 string = "us";
588 break;
589 case MS:
590 string = "ms";
591 break;
592 case S:
593 string = "s";
594 break;
595 default:
596 string = "_s";
597 break;
598 }
599
600 snprintf(buffer, BUFSIZE10, "%4.2f%s", convert_seconds(microseconds),
601 string);
602}
603
604static void init_buffer(char *buffer, size_t size)
605{
606 size_t i;
607
608 for (i = 0; i < size; i++)
609 buffer[i] = i + '0';
610}
611
612static void show_lat_stats_bucket(struct intel_lat_stats *stats,
613 __u32 lower_us, enum inf_bound_type start_type,
614 __u32 upper_us, enum inf_bound_type end_type, int i)
615{
616 enum FormatUnit fu = S;
617 char buffer[BUFSIZE10];
618
619 init_buffer(buffer, BUFSIZE10);
620 printf("%-*d", COL_WIDTH12, i);
621
622 fu = get_seconds_magnitude(lower_us);
623 set_unit_string(buffer, lower_us, fu, start_type);
624 printf("%-*s", COL_WIDTH12, buffer);
625
626 fu = get_seconds_magnitude(upper_us);
627 set_unit_string(buffer, upper_us, fu, end_type);
628 printf("%-*s", COL_WIDTH12, buffer);
629
630 printf("%-*d\n", COL_WIDTH12, stats->data[i]);
631}
632
633static void show_optane_lat_stats_bucket(struct optane_lat_stats *stats,
634 __u32 lower_us, enum inf_bound_type start_type,
635 __u32 upper_us, enum inf_bound_type end_type, int i)
636{
637 enum FormatUnit fu = S;
638 char buffer[BUFSIZE10];
639
640 init_buffer(buffer, BUFSIZE10);
641 printf("%-*d", COL_WIDTH12, i);
642
643 fu = get_seconds_magnitude(lower_us);
644 set_unit_string(buffer, lower_us, fu, start_type);
645 printf("%-*s", COL_WIDTH12, buffer);
646
647 fu = get_seconds_magnitude(upper_us);
648 set_unit_string(buffer, upper_us, fu, end_type);
649 printf("%-*s", COL_WIDTH12, buffer);
650
651 printf("%-*lu\n", COL_WIDTH12, (unsigned long)stats->data[i]);
652}
653
654
655static void show_lat_stats_linear(struct intel_lat_stats *stats,
656 __u32 start_offset, __u32 end_offset, __u32 bytes_per,
657 __u32 us_step, bool_Bool nonzero_print)
658{
659 for (int i = (start_offset / bytes_per) - 1;
660 i < end_offset / bytes_per; i++) {
661 if (nonzero_print && stats->data[i] == 0)
662 continue;
663 show_lat_stats_bucket(stats, us_step * i, NOINF,
664 us_step * (i + 1), NOINF, i);
665 }
666}
667
668/*
669 * For 4.0-4.5 revision.
670 */
671#define LATENCY_STATS_V4_BASE_BITS6 6
672#define LATENCY_STATS_V4_BASE_VAL(1 << 6) (1 << LATENCY_STATS_V4_BASE_BITS6)
673
674static int lat_stats_log_scale(int i)
675{
676 // if (i < 128)
677 if (i < (LATENCY_STATS_V4_BASE_VAL(1 << 6) << 1))
678 return i;
679
680 int error_bits = (i >> LATENCY_STATS_V4_BASE_BITS6) - 1;
681 int base = 1 << (error_bits + LATENCY_STATS_V4_BASE_BITS6);
682 int k = i % LATENCY_STATS_V4_BASE_VAL(1 << 6);
683
684 return base + ((k + 0.5) * (1 << error_bits));
685}
686
687/*
688 * Creates a subroot in the following manner:
689 * {
690 * "latstats" : {
691 * "type" : "write" or "read",
692 * "values" : {
693 */
694static void lat_stats_make_json_root(
695 struct json_object *root, struct json_object *bucket_list,
696 int write)
697{
698 struct json_object *subroot = json_create_object()json_object_new_object();
699
700 json_object_add_value_object(root, "latstats", subroot)json_object_object_add(root, "latstats", subroot);
701 json_object_add_value_string(subroot, "type", write ? "write" : "read");
702 json_object_add_value_object(subroot, "values", bucket_list)json_object_object_add(subroot, "values", bucket_list);
703}
704
705/*
706 * Creates a bucket under the "values" json_object. Format is:
707 * "values" : {
708 * "bucket" : {
709 * "id" : #,
710 * "start" : string,
711 * "end" : string,
712 * "value" : 0,
713 * },
714 */
715static void json_add_bucket(struct intel_lat_stats *stats,
716 struct json_object *bucket_list, __u32 id,
717 __u32 lower_us, enum inf_bound_type start_type,
718 __u32 upper_us, enum inf_bound_type end_type, __u32 val)
719{
720 char buffer[BUFSIZE10];
721 struct json_object *bucket = json_create_object()json_object_new_object();
722
723 init_buffer(buffer, BUFSIZE10);
724
725 json_object_array_add(bucket_list, bucket);
726 json_object_add_value_int(bucket, "id", id)json_object_object_add(bucket, "id", json_object_new_int(id));
727
728 set_unit_string(buffer, lower_us,
729 get_seconds_magnitude(lower_us), start_type);
730 json_object_add_value_string(bucket, "start", buffer);
731
732 set_unit_string(buffer, upper_us,
733 get_seconds_magnitude(upper_us), end_type);
734 json_object_add_value_string(bucket, "end", buffer);
735
736 json_object_add_value_int(bucket, "value", val)json_object_object_add(bucket, "value", json_object_new_int(val
))
;
737}
738
739static void json_add_bucket_optane(struct json_object *bucket_list, __u32 id,
740 __u32 lower_us, enum inf_bound_type start_type,
741 __u32 upper_us, enum inf_bound_type end_type, __u32 val)
742{
743 char buffer[BUFSIZE10];
744 struct json_object *bucket = json_create_object()json_object_new_object();
745
746 init_buffer(buffer, BUFSIZE10);
747
748 json_object_array_add(bucket_list, bucket);
749 json_object_add_value_int(bucket, "id", id)json_object_object_add(bucket, "id", json_object_new_int(id));
750
751 set_unit_string(buffer, lower_us,
752 get_seconds_magnitude(lower_us), start_type);
753 json_object_add_value_string(bucket, "start", buffer);
754
755 set_unit_string(buffer, upper_us,
756 get_seconds_magnitude(upper_us), end_type);
757 json_object_add_value_string(bucket, "end", buffer);
758
759 json_object_add_value_uint(bucket, "value", val)json_object_object_add(bucket, "value", json_object_new_uint64
(val))
;
760
761}
762
763static void json_lat_stats_linear(struct intel_lat_stats *stats,
764 struct json_object *bucket_list, __u32 start_offset,
765 __u32 end_offset, __u32 bytes_per,
766 __u32 us_step, bool_Bool nonzero_print)
767{
768 for (int i = (start_offset / bytes_per) - 1;
769 i < end_offset / bytes_per; i++) {
770 if (nonzero_print && stats->data[i] == 0)
771 continue;
772
773 json_add_bucket(stats, bucket_list,
774 i, us_step * i, NOINF, us_step * (i + 1),
775 NOINF, stats->data[i]);
776 }
777}
778
779static void json_lat_stats_3_0(struct intel_lat_stats *stats, int write)
780{
781 struct json_object *root = json_create_object()json_object_new_object();
782 struct json_object *bucket_list = json_object_new_array();
783
784 lat_stats_make_json_root(root, bucket_list, write);
785
786 json_lat_stats_linear(stats, bucket_list, 4, 131, 4, 32, false0);
787 json_lat_stats_linear(stats, bucket_list, 132, 255, 4, 1024, false0);
788 json_lat_stats_linear(stats, bucket_list, 256, 379, 4, 32768, false0);
789 json_lat_stats_linear(stats, bucket_list, 380, 383, 4, 32, true1);
790 json_lat_stats_linear(stats, bucket_list, 384, 387, 4, 32, true1);
791 json_lat_stats_linear(stats, bucket_list, 388, 391, 4, 32, true1);
792
793 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
794 printf("\n");
795 json_free_object(root)json_object_put(root);
796}
797
798static void json_lat_stats_4_0(struct intel_lat_stats *stats, int write)
799{
800 struct json_object *root = json_create_object()json_object_new_object();
801 struct json_object *bucket_list = json_object_new_array();
802
803 lat_stats_make_json_root(root, bucket_list, write);
804
805 __u32 lower_us = 0;
806 __u32 upper_us = 1;
807 bool_Bool end = false0;
808 int max = 1216;
809
810 for (int i = 0; i < max; i++) {
811 lower_us = lat_stats_log_scale(i);
812 if (i >= max - 1)
813 end = true1;
814 else
815 upper_us = lat_stats_log_scale(i + 1);
816
817 json_add_bucket(stats, bucket_list, i,
818 lower_us, NOINF, upper_us,
819 end ? POSINF : NOINF, stats->data[i]);
820 }
821 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
822 printf("\n");
823 json_free_object(root)json_object_put(root);
824}
825
826static void show_lat_stats_3_0(struct intel_lat_stats *stats)
827{
828 show_lat_stats_linear(stats, 4, 131, 4, 32, false0);
829 show_lat_stats_linear(stats, 132, 255, 4, 1024, false0);
830 show_lat_stats_linear(stats, 256, 379, 4, 32768, false0);
831 show_lat_stats_linear(stats, 380, 383, 4, 32, true1);
832 show_lat_stats_linear(stats, 384, 387, 4, 32, true1);
833 show_lat_stats_linear(stats, 388, 391, 4, 32, true1);
834}
835
836static void show_lat_stats_4_0(struct intel_lat_stats *stats)
837{
838 int lower_us = 0;
839 int upper_us = 1;
840 bool_Bool end = false0;
841 int max = 1216;
842
843 for (int i = 0; i < max; i++) {
844 lower_us = lat_stats_log_scale(i);
845 if (i >= max - 1)
846 end = true1;
847 else
848 upper_us = lat_stats_log_scale(i + 1);
849
850 show_lat_stats_bucket(stats, lower_us, NOINF,
851 upper_us, end ? POSINF : NOINF, i);
852 }
853}
854
855static void json_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
856{
857 int i;
858 struct json_object *root = json_create_object()json_object_new_object();
859 struct json_object *bucket_list = json_object_new_array();
860
861 lat_stats_make_json_root(root, bucket_list, write);
862
863 if (write) {
864 for (i = 0; i < OPTANE_V1000_BUCKET_LEN8 - 1; i++)
865 json_add_bucket_optane(bucket_list, i,
866 v1000_bucket.write[i], NOINF,
867 v1000_bucket.write[i + 1] - 1,
868 NOINF,
869 stats->data[i]);
870
871 json_add_bucket_optane(bucket_list,
872 OPTANE_V1000_BUCKET_LEN8 - 1,
873 v1000_bucket.write[i],
874 NOINF,
875 v1000_bucket.write[i],
876 POSINF, stats->data[i]);
877 } else {
878 for (i = 0; i < OPTANE_V1000_BUCKET_LEN8 - 1; i++)
879 json_add_bucket_optane(bucket_list, i,
880 v1000_bucket.read[i], NOINF,
881 v1000_bucket.read[i + 1] - 1,
882 NOINF,
883 stats->data[i]);
884
885 json_add_bucket_optane(bucket_list,
886 OPTANE_V1000_BUCKET_LEN8 - 1,
887 v1000_bucket.read[i],
888 NOINF,
889 v1000_bucket.read[i],
890 POSINF, stats->data[i]);
891 }
892
893 struct json_object *subroot = json_create_object()json_object_new_object();
894
895 json_object_add_value_object(root, "Average latency since last reset", subroot)json_object_object_add(root, "Average latency since last reset"
, subroot)
;
896
897 json_object_add_value_uint(subroot, "value in us", stats->data[8])json_object_object_add(subroot, "value in us", json_object_new_uint64
(stats->data[8]))
;
898
899 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
900 printf("\n");
901 json_free_object(root)json_object_put(root);
902
903}
904
905static void show_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
906{
907 int i;
908
909 if (write) {
910 for (i = 0; i < OPTANE_V1000_BUCKET_LEN8 - 1; i++)
911 show_optane_lat_stats_bucket(stats,
912 v1000_bucket.write[i],
913 NOINF,
914 v1000_bucket.write[i + 1] - 1,
915 NOINF, i);
916
917 show_optane_lat_stats_bucket(stats, v1000_bucket.write[i],
918 NOINF, v1000_bucket.write[i],
919 POSINF, i);
920 } else {
921 for (i = 0; i < OPTANE_V1000_BUCKET_LEN8 - 1; i++)
922 show_optane_lat_stats_bucket(stats,
923 v1000_bucket.read[i],
924 NOINF,
925 v1000_bucket.read[i + 1] - 1,
926 NOINF, i);
927
928 show_optane_lat_stats_bucket(stats, v1000_bucket.read[i],
929 NOINF, v1000_bucket.read[i],
930 POSINF, i);
931 }
932
933 printf("Average latency since last reset: %lu us\n", (unsigned long)stats->data[8]);
934
935}
936
937static void json_lat_stats(int write)
938{
939 switch (media_version[MEDIA_MAJOR_IDX0]) {
940 case 3:
941 json_lat_stats_3_0(&stats, write);
942 break;
943 case 4:
944 switch (media_version[MEDIA_MINOR_IDX1]) {
945 case 0:
946 case 1:
947 case 2:
948 case 3:
949 case 4:
950 case 5:
951 json_lat_stats_4_0(&stats, write);
952 break;
953 default:
954 nvme_show_error("Unsupported minor revision (%u.%u)",nvme_show_message(1, "Unsupported minor revision (%u.%u)", stats
.maj, stats.min)
955 stats.maj, stats.min)nvme_show_message(1, "Unsupported minor revision (%u.%u)", stats
.maj, stats.min)
;
956 break;
957 }
958 break;
959 case 1000:
960 switch (media_version[MEDIA_MINOR_IDX1]) {
961 case 0:
962 json_lat_stats_v1000_0(&v1000_stats, write);
963 break;
964 default:
965 nvme_show_error("Unsupported minor revision (%u.%u)",nvme_show_message(1, "Unsupported minor revision (%u.%u)", stats
.maj, stats.min)
966 stats.maj, stats.min)nvme_show_message(1, "Unsupported minor revision (%u.%u)", stats
.maj, stats.min)
;
967 break;
968 }
969 break;
970 default:
971 nvme_show_error("Unsupported revision (%u.%u)",nvme_show_message(1, "Unsupported revision (%u.%u)", stats.maj
, stats.min)
972 stats.maj, stats.min)nvme_show_message(1, "Unsupported revision (%u.%u)", stats.maj
, stats.min)
;
973 break;
974 }
975 printf("\n");
976}
977
978static void
979print_dash_separator(int count)
980{
981 for (int i = 0; i < count; i++)
982 putchar('-');
983 putchar('\n');
984}
985
986static void show_lat_stats(int write)
987{
988 static const int separator_length = 50;
989
990 printf("Intel IO %s Command Latency Statistics\n",
991 write ? "Write" : "Read");
992 printf("Major Revision : %u\nMinor Revision : %u\n",
993 media_version[MEDIA_MAJOR_IDX0], media_version[MEDIA_MINOR_IDX1]);
994 print_dash_separator(separator_length);
995 printf("%-12s%-12s%-12s%-20s\n", "Bucket", "Start", "End", "Value");
996 print_dash_separator(separator_length);
997
998 switch (media_version[MEDIA_MAJOR_IDX0]) {
999 case 3:
1000 show_lat_stats_3_0(&stats);
1001 break;
1002 case 4:
1003 switch (media_version[MEDIA_MINOR_IDX1]) {
1004 case 0:
1005 case 1:
1006 case 2:
1007 case 3:
1008 case 4:
1009 case 5:
1010 case 6:
1011 show_lat_stats_4_0(&stats);
1012 break;
1013 default:
1014 nvme_show_error("Unsupported minor revision (%u.%u)",nvme_show_message(1, "Unsupported minor revision (%u.%u)", stats
.maj, stats.min)
1015 stats.maj, stats.min)nvme_show_message(1, "Unsupported minor revision (%u.%u)", stats
.maj, stats.min)
;
1016 break;
1017 }
1018 break;
1019 case 1000:
1020 switch (media_version[MEDIA_MINOR_IDX1]) {
1021 case 0:
1022 show_lat_stats_v1000_0(&v1000_stats, write);
1023 break;
1024 default:
1025 nvme_show_error("Unsupported minor revision (%u.%u)",nvme_show_message(1, "Unsupported minor revision (%u.%u)", stats
.maj, stats.min)
1026 stats.maj, stats.min)nvme_show_message(1, "Unsupported minor revision (%u.%u)", stats
.maj, stats.min)
;
1027 break;
1028 }
1029 break;
1030 default:
1031 nvme_show_error("Unsupported revision (%u.%u)",nvme_show_message(1, "Unsupported revision (%u.%u)", stats.maj
, stats.min)
1032 stats.maj, stats.min)nvme_show_message(1, "Unsupported revision (%u.%u)", stats.maj
, stats.min)
;
1033 break;
1034 }
1035}
1036
1037static int get_lat_stats_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1038{
1039 __u8 data[NAND_LAT_STATS_LEN4868];
1040 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1041 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1042 nvme_print_flags_t flags;
1043 int err;
1044
1045 const char *desc = "Get Intel Latency Statistics log and show it.";
1046 const char *raw = "Dump output in binary format";
1047#ifdef CONFIG_JSONC
1048 const char *json = "Dump output in json format";
1049#endif /* CONFIG_JSONC */
1050 const char *write = "Get write statistics (read default)";
1051
1052 struct config {
1053 bool_Bool raw_binary;
1054 bool_Bool json;
1055 bool_Bool write;
1056 };
1057
1058 struct config cfg = {
1059 };
1060
1061 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &
cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0), CFG_FLAG
, &cfg.json, 0, json, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress informational output", 0, }, {"output-format",
'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1062 OPT_FLAG("write", 'w', &cfg.write, write),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &
cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0), CFG_FLAG
, &cfg.json, 0, json, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress informational output", 0, }, {"output-format",
'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1063 OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &
cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0), CFG_FLAG
, &cfg.json, 0, json, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress informational output", 0, }, {"output-format",
'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1064 OPT_FLAG_JSON("json", 'j', &cfg.json, json))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &
cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0), CFG_FLAG
, &cfg.json, 0, json, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"quiet", 0, ((void*)0), CFG_FLAG, &nvme_args.quiet
, 0, "suppress informational output", 0, }, {"output-format",
'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
1065
1066 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1067 if (err)
1068 return err;
1069
1070 err = validate_output_format(nvme_args.output_format, &flags);
1071 if (err < 0) {
1072 nvme_show_error("Invalid output format")nvme_show_message(1, "Invalid output format");
1073 return err;
1074 }
1075
1076 /* For optate, latency stats are deleted every time their LID is pulled.
1077 * Therefore, we query the longest lat_stats log page first.
1078 */
1079 err = nvme_get_log_simple(hdl, cfg.write ? 0xc2 : 0xc1,
1080 &data, sizeof(data));
1081
1082 media_version[0] = (data[1] << 8) | data[0];
1083 media_version[1] = (data[3] << 8) | data[2];
1084
1085 if (err)
1086 return err;
1087
1088 if (media_version[0] == 1000) {
1089 __u32 thresholds[OPTANE_V1000_BUCKET_LEN8] = {0};
1090 __u64 result;
1091
1092 err = nvme_get_features(hdl, 0, 0xf7,
1093 0, cfg.write ? 0x1 : 0x0,
1094 0, thresholds, sizeof(thresholds),
1095 &result);
1096 if (err) {
1097 nvme_show_error("Querying thresholds failed. ")nvme_show_message(1, "Querying thresholds failed. ");
1098 nvme_show_status(err);
1099 return err;
1100 }
1101
1102 /* Update bucket thresholds to be printed */
1103 if (cfg.write) {
1104 for (int i = 0; i < OPTANE_V1000_BUCKET_LEN8; i++)
1105 v1000_bucket.write[i] = thresholds[i];
1106 } else {
1107 for (int i = 0; i < OPTANE_V1000_BUCKET_LEN8; i++)
1108 v1000_bucket.read[i] = thresholds[i];
1109
1110 }
1111
1112 /* Move counter values to optate stats struct which has a
1113 * smaller size
1114 */
1115 memcpy(&v1000_stats, (struct optane_lat_stats *)data,
1116 sizeof(struct optane_lat_stats));
1117 } else {
1118 memcpy(&stats, (struct intel_lat_stats *)data,
1119 sizeof(struct intel_lat_stats));
1120 }
1121
1122 if (flags & JSON || cfg.json)
1123 json_lat_stats(cfg.write);
1124 else if (!cfg.raw_binary)
1125 show_lat_stats(cfg.write);
1126 else {
1127 if (media_version[0] == 1000)
1128 d_raw((unsigned char *)&v1000_stats,
1129 sizeof(v1000_stats));
1130 else
1131 d_raw((unsigned char *)&stats,
1132 sizeof(stats));
1133 }
1134
1135 return 0;
1136}
1137
1138struct intel_assert_dump {
1139 __u32 coreoffset;
1140 __u32 assertsize;
1141 __u8 assertdumptype;
1142 __u8 assertvalid;
1143 __u8 reserved[2];
1144};
1145
1146struct intel_event_dump {
1147 __u32 numeventdumps;
1148 __u32 coresize;
1149 __u32 coreoffset;
1150 __u32 eventidoffset[16];
1151 __u8 eventIdValidity[16];
1152};
1153
1154struct intel_vu_version {
1155 __u16 major;
1156 __u16 minor;
1157};
1158
1159struct intel_event_header {
1160 __u32 eventidsize;
1161 struct intel_event_dump edumps[0];
1162};
1163
1164struct intel_vu_log {
1165 struct intel_vu_version ver;
1166 __u32 header;
1167 __u32 size;
1168 __u32 numcores;
1169 __u8 reserved[4080];
1170};
1171
1172struct intel_vu_nlog {
1173 struct intel_vu_version ver;
1174 __u32 logselect;
1175 __u32 totalnlogs;
1176 __u32 nlognum;
1177 __u32 nlogname;
1178 __u32 nlogbytesize;
1179 __u32 nlogprimarybuffsize;
1180 __u32 tickspersecond;
1181 __u32 corecount;
1182 __u32 nlogpausestatus;
1183 __u32 selectoffsetref;
1184 __u32 selectnlogpause;
1185 __u32 selectaddedoffset;
1186 __u32 nlogbufnum;
1187 __u32 nlogbufnummax;
1188 __u32 coreselected;
1189 __u32 reserved[3];
1190};
1191
1192struct intel_cd_log {
1193 union {
1194 struct {
1195 __u32 selectLog : 3;
1196 __u32 selectCore : 2;
1197 __u32 selectNlog : 8;
1198 __u8 selectOffsetRef : 1;
1199 __u32 selectNlogPause : 2;
1200 __u32 reserved2 : 16;
1201 } fields;
1202 __u32 entireDword;
1203 } u;
1204};
1205
1206static void print_intel_nlog(struct intel_vu_nlog *intel_nlog)
1207{
1208 printf("Version Major %u\n"
1209 "Version Minor %u\n"
1210 "Log_select %u\n"
1211 "totalnlogs %u\n"
1212 "nlognum %u\n"
1213 "nlogname %u\n"
1214 "nlogbytesze %u\n"
1215 "nlogprimarybuffsize %u\n"
1216 "tickspersecond %u\n"
1217 "corecount %u\n"
1218 "nlogpausestatus %u\n"
1219 "selectoffsetref %u\n"
1220 "selectnlogpause %u\n"
1221 "selectaddedoffset %u\n"
1222 "nlogbufnum %u\n"
1223 "nlogbufnummax %u\n"
1224 "coreselected %u\n",
1225 intel_nlog->ver.major, intel_nlog->ver.minor,
1226 intel_nlog->logselect, intel_nlog->totalnlogs, intel_nlog->nlognum,
1227 intel_nlog->nlogname, intel_nlog->nlogbytesize,
1228 intel_nlog->nlogprimarybuffsize, intel_nlog->tickspersecond,
1229 intel_nlog->corecount, intel_nlog->nlogpausestatus,
1230 intel_nlog->selectoffsetref, intel_nlog->selectnlogpause,
1231 intel_nlog->selectaddedoffset, intel_nlog->nlogbufnum,
1232 intel_nlog->nlogbufnummax, intel_nlog->coreselected);
1233}
1234
1235static int read_entire_cmd(struct libnvme_passthru_cmd *cmd, int total_size,
1236 const size_t max_tfer, int out_fd,
1237 struct libnvme_transport_handle *hdl, __u8 *buf)
1238{
1239 int err = 0;
1240 size_t dword_tfer = 0;
1241
1242 dword_tfer = min(max_tfer, total_size)({ typeof(max_tfer) _a = (max_tfer); typeof(total_size) _b = (
total_size); do { } while (0); _a < _b ? _a : _b; })
;
1243 while (total_size > 0) {
1244 err = libnvme_exec_admin_passthru(hdl, cmd);
1245 if (err) {
1246 nvme_show_error(nvme_show_message(1, "failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n"
, cmd->data_len, cmd->cdw13, cmd->cdw12, cmd->cdw10
, err, total_size)
1247 "failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n",nvme_show_message(1, "failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n"
, cmd->data_len, cmd->cdw13, cmd->cdw12, cmd->cdw10
, err, total_size)
1248 cmd->data_len, cmd->cdw13, cmd->cdw12,nvme_show_message(1, "failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n"
, cmd->data_len, cmd->cdw13, cmd->cdw12, cmd->cdw10
, err, total_size)
1249 cmd->cdw10, err, total_size)nvme_show_message(1, "failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n"
, cmd->data_len, cmd->cdw13, cmd->cdw12, cmd->cdw10
, err, total_size)
;
1250 goto out;
1251 }
1252
1253 if (out_fd > 0) {
1254 err = write(out_fd, buf, cmd->data_len);
1255 if (err < 0) {
1256 nvme_show_perror("write failure");
1257 goto out;
1258 }
1259 err = 0;
1260 }
1261 total_size -= dword_tfer;
1262 cmd->cdw13 += dword_tfer;
1263 cmd->cdw10 = dword_tfer = min(max_tfer, total_size)({ typeof(max_tfer) _a = (max_tfer); typeof(total_size) _b = (
total_size); do { } while (0); _a < _b ? _a : _b; })
;
1264 cmd->data_len = (min(max_tfer, total_size)({ typeof(max_tfer) _a = (max_tfer); typeof(total_size) _b = (
total_size); do { } while (0); _a < _b ? _a : _b; })
) * 4;
1265 }
1266
1267 out:
1268 return err;
1269}
1270
1271static int write_header(__u8 *buf, int fd, size_t amnt)
1272{
1273 if (write(fd, buf, amnt) < 0)
1274 return 1;
1275 return 0;
1276}
1277
1278static int read_header(struct libnvme_passthru_cmd *cmd, __u8 *buf,
1279 struct libnvme_transport_handle *hdl, __u32 dw12, int nsid)
1280{
1281 memset(cmd, 0, sizeof(*cmd));
1282 memset(buf, 0, 4096);
1283 cmd->opcode = 0xd2;
1284 cmd->nsid = nsid;
1285 cmd->cdw10 = 0x400;
1286 cmd->cdw12 = dw12;
1287 cmd->data_len = 0x1000;
1288 cmd->addr = (uintptr_t)(void *)buf;
1289 return read_entire_cmd(cmd, 0x400, 0x400, -1, hdl, buf);
1290}
1291
1292static int setup_file(char *f, char *file, struct libnvme_transport_handle *hdl, int type)
1293{
1294 struct nvme_id_ctrl ctrl;
1295 struct libnvme_passthru_cmd cmd;
1296 int err = 0, i = sizeof(ctrl.sn) - 1;
1297
1298 nvme_init_identify_ctrl(&cmd, &ctrl);
1299 err = libnvme_exec_admin_passthru(hdl, &cmd);
1300 if (err)
1301 return err;
1302
1303 /* Remove trailing spaces from the name */
1304 while (i && ctrl.sn[i] == ' ') {
1305 ctrl.sn[i] = '\0';
1306 i--;
1307 }
1308
1309 sprintf(f, "%s_%-.*s.bin", type == 0 ? "Nlog" :
1310 type == 1 ? "EventLog" : "AssertLog",
1311 (int)sizeof(ctrl.sn), ctrl.sn);
1312 return err;
1313}
1314
1315static int get_internal_log_old(__u8 *buf, int output,
1316 struct libnvme_transport_handle *hdl,
1317 struct libnvme_passthru_cmd *cmd)
1318{
1319 struct intel_vu_log *intel;
1320 int err = 0;
1321 const int dwmax = 0x400;
1322 const int dmamax = 0x1000;
1323
1324 intel = (struct intel_vu_log *)buf;
1325
1326 printf("Log major:%d minor:%d header:%d size:%d\n",
1327 intel->ver.major, intel->ver.minor, intel->header, intel->size);
1328
1329 err = write(output, buf, 0x1000);
1330 if (err < 0) {
1331 nvme_show_perror("write failure");
1332 goto out;
1333 }
1334 intel->size -= 0x400;
1335 cmd->opcode = 0xd2;
1336 cmd->cdw10 = min(dwmax, intel->size)({ typeof(dwmax) _a = (dwmax); typeof(intel->size) _b = (intel
->size); do { } while (0); _a < _b ? _a : _b; })
;
1337 cmd->data_len = min(dmamax, intel->size)({ typeof(dmamax) _a = (dmamax); typeof(intel->size) _b = (
intel->size); do { } while (0); _a < _b ? _a : _b; })
;
1338 err = read_entire_cmd(cmd, intel->size, dwmax, output, hdl, buf);
1339 if (err)
1340 goto out;
1341
1342 err = 0;
1343 out:
1344 return err;
1345}
1346
1347static int get_internal_log(int argc, char **argv, struct command *acmd,
1348 struct plugin *plugin)
1349{
1350 __u8 buf[0x2000];
1351 char f[0x100];
1352 int err, output, i, j, count = 0, core_num = 1;
1353 struct libnvme_passthru_cmd cmd;
1354 struct intel_cd_log cdlog;
1355 struct intel_vu_nlog *intel_nlog = (struct intel_vu_nlog *)buf;
1356 struct intel_assert_dump *ad;
1357 struct intel_event_header *ehdr;
1358 __cleanup_free__attribute__((cleanup(shr_freep))) struct intel_vu_log *intel = NULL((void*)0);
1359 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1360 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1361
1362 const char *desc = "Get Intel Firmware Log and save it.";
1363 const char *log = "Log type: 0, 1, or 2 for nlog, event log, and assert log, respectively.";
1364 const char *core = "Select which region log should come from. -1 for all";
1365 const char *nlognum = "Select which nlog to read. -1 for all nlogs";
1366 const char *file = "Output file; defaults to device name provided";
1367 const char *verbose = "To print out verbose nlog info";
1368 const char *namespace_id = "Namespace to get logs from";
1369
1370 struct config {
1371 __u32 namespace_id;
1372 __u32 log;
1373 int core;
1374 int lnum;
1375 char *file;
1376 bool_Bool verbose;
1377 };
1378
1379 struct config cfg = {
1380 .namespace_id = -1,
1381 .file = NULL((void*)0),
1382 .lnum = -1,
1383 .core = -1
1384 };
1385
1386 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"log", 'l', "NUM", CFG_POSITIVE, &cfg.log, 1, log
, 0, }, {"region", 'r', "NUM", CFG_INT, &cfg.core, 1, core
, 0, }, {"nlognum", 'm', "NUM", CFG_INT, &cfg.lnum, 1, nlognum
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"output-file", 'O', "FILE", CFG_STRING
, &cfg.file, 1, file, 0, }, {"verbose-nlog", 'V', ((void*
)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"", 0, ((
void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1387 OPT_UINT("log", 'l', &cfg.log, log),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"log", 'l', "NUM", CFG_POSITIVE, &cfg.log, 1, log
, 0, }, {"region", 'r', "NUM", CFG_INT, &cfg.core, 1, core
, 0, }, {"nlognum", 'm', "NUM", CFG_INT, &cfg.lnum, 1, nlognum
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"output-file", 'O', "FILE", CFG_STRING
, &cfg.file, 1, file, 0, }, {"verbose-nlog", 'V', ((void*
)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"", 0, ((
void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1388 OPT_INT("region", 'r', &cfg.core, core),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"log", 'l', "NUM", CFG_POSITIVE, &cfg.log, 1, log
, 0, }, {"region", 'r', "NUM", CFG_INT, &cfg.core, 1, core
, 0, }, {"nlognum", 'm', "NUM", CFG_INT, &cfg.lnum, 1, nlognum
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"output-file", 'O', "FILE", CFG_STRING
, &cfg.file, 1, file, 0, }, {"verbose-nlog", 'V', ((void*
)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"", 0, ((
void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1389 OPT_INT("nlognum", 'm', &cfg.lnum, nlognum),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"log", 'l', "NUM", CFG_POSITIVE, &cfg.log, 1, log
, 0, }, {"region", 'r', "NUM", CFG_INT, &cfg.core, 1, core
, 0, }, {"nlognum", 'm', "NUM", CFG_INT, &cfg.lnum, 1, nlognum
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"output-file", 'O', "FILE", CFG_STRING
, &cfg.file, 1, file, 0, }, {"verbose-nlog", 'V', ((void*
)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"", 0, ((
void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1390 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"log", 'l', "NUM", CFG_POSITIVE, &cfg.log, 1, log
, 0, }, {"region", 'r', "NUM", CFG_INT, &cfg.core, 1, core
, 0, }, {"nlognum", 'm', "NUM", CFG_INT, &cfg.lnum, 1, nlognum
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"output-file", 'O', "FILE", CFG_STRING
, &cfg.file, 1, file, 0, }, {"verbose-nlog", 'V', ((void*
)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"", 0, ((
void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1391 OPT_FILE("output-file", 'O', &cfg.file, file),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"log", 'l', "NUM", CFG_POSITIVE, &cfg.log, 1, log
, 0, }, {"region", 'r', "NUM", CFG_INT, &cfg.core, 1, core
, 0, }, {"nlognum", 'm', "NUM", CFG_INT, &cfg.lnum, 1, nlognum
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"output-file", 'O', "FILE", CFG_STRING
, &cfg.file, 1, file, 0, }, {"verbose-nlog", 'V', ((void*
)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"", 0, ((
void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1392 OPT_FLAG("verbose-nlog", 'V', &cfg.verbose, verbose))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"log", 'l', "NUM", CFG_POSITIVE, &cfg.log, 1, log
, 0, }, {"region", 'r', "NUM", CFG_INT, &cfg.core, 1, core
, 0, }, {"nlognum", 'm', "NUM", CFG_INT, &cfg.lnum, 1, nlognum
, 0, }, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"output-file", 'O', "FILE", CFG_STRING
, &cfg.file, 1, file, 0, }, {"verbose-nlog", 'V', ((void*
)0), CFG_FLAG, &cfg.verbose, 0, verbose, 0, }, {"", 0, ((
void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
1393
1394 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1395 if (err)
1
Assuming 'err' is 0
2
Taking false branch
1396 return err;
1397
1398 intel = malloc(sizeof(*intel));
3
Memory is allocated
1399 if (!intel)
4
Assuming 'intel' is non-null
5
Taking false branch
1400 return -ENOMEM12;
1401
1402 ad = (struct intel_assert_dump *)intel->reserved;
1403 ehdr = (struct intel_event_header *)intel->reserved;
1404
1405 if (cfg.log > 2 || cfg.core > 4 || cfg.lnum > 255) {
6
Assuming field 'log' is > 2
1406 err = -EINVAL22;
7
Potential leak of memory pointed to by 'intel'
1407 goto out_free;
1408 }
1409
1410 if (!cfg.file) {
1411 err = setup_file(f, cfg.file, hdl, cfg.log);
1412 if (err)
1413 goto out_free;
1414 cfg.file = f;
1415 }
1416
1417 cdlog.u.entireDword = 0;
1418
1419 cdlog.u.fields.selectLog = cfg.log;
1420 cdlog.u.fields.selectCore = cfg.core < 0 ? 0 : cfg.core;
1421 cdlog.u.fields.selectNlog = cfg.lnum < 0 ? 0 : cfg.lnum;
1422
1423 output = shr_open_rawdata(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666)open((cfg.file), (01 | 0100 | 01000), 0666);
1424 if (output < 0) {
1425 err = output;
1426 goto out_free;
1427 }
1428
1429 err = read_header(&cmd, buf, hdl, cdlog.u.entireDword,
1430 cfg.namespace_id);
1431 if (err)
1432 goto out;
1433 memcpy(intel, buf, sizeof(*intel));
1434
1435 /* for 1.1 Fultondales will use old nlog, but current assert/event */
1436 if ((intel->ver.major < 1 && intel->ver.minor < 1) ||
1437 (intel->ver.major <= 1 && intel->ver.minor <= 1 && cfg.log == 0)) {
1438 cmd.addr = (uintptr_t)(void *)buf;
1439 err = get_internal_log_old(buf, output, hdl, &cmd);
1440 goto out;
1441 }
1442
1443 if (cfg.log == 2) {
1444 if (cfg.verbose)
1445 printf("Log major:%d minor:%d header:%d size:%d numcores:%d\n",
1446 intel->ver.major, intel->ver.minor,
1447 intel->header, intel->size, intel->numcores);
1448
1449 err = write_header(buf, output, 0x1000);
1450 if (err) {
1451 nvme_show_perror("write failure");
1452 goto out;
1453 }
1454
1455 count = intel->numcores;
1456 } else if (cfg.log == 0) {
1457 if (cfg.lnum < 0)
1458 count = intel_nlog->totalnlogs;
1459 else
1460 count = 1;
1461 if (cfg.core < 0)
1462 core_num = intel_nlog->corecount;
1463 } else if (cfg.log == 1) {
1464 core_num = intel->numcores;
1465 count = 1;
1466 err = write_header(buf, output, sizeof(*intel));
1467 if (err)
1468 goto out;
1469 }
1470
1471 for (j = (cfg.core < 0 ? 0 : cfg.core);
1472 j < (cfg.core < 0 ? core_num : cfg.core + 1);
1473 j++) {
1474 cdlog.u.fields.selectCore = j;
1475 for (i = 0; i < count; i++) {
1476 if (cfg.log == 2) {
1477 if (!ad[i].assertvalid)
1478 continue;
1479 cmd.cdw13 = ad[i].coreoffset;
1480 cmd.cdw10 = 0x400;
1481 cmd.data_len = min(0x400, ad[i].assertsize)({ typeof(0x400) _a = (0x400); typeof(ad[i].assertsize) _b = (
ad[i].assertsize); do { } while (0); _a < _b ? _a : _b; })
* 4;
1482 err = read_entire_cmd(&cmd, ad[i].assertsize,
1483 0x400, output,
1484 hdl,
1485 buf);
1486 if (err)
1487 goto out;
1488
1489 } else if (cfg.log == 0) {
1490 /* If the user selected to read the entire nlog */
1491 if (count > 1)
1492 cdlog.u.fields.selectNlog = i;
1493
1494 err = read_header(&cmd, buf, hdl,
1495 cdlog.u.entireDword,
1496 cfg.namespace_id);
1497 if (err)
1498 goto out;
1499 err = write_header(buf, output, sizeof(*intel_nlog));
1500 if (err)
1501 goto out;
1502 if (cfg.verbose)
1503 print_intel_nlog(intel_nlog);
1504 cmd.cdw13 = 0x400;
1505 cmd.cdw10 = 0x400;
1506 cmd.data_len = min(0x1000, intel_nlog->nlogbytesize)({ typeof(0x1000) _a = (0x1000); typeof(intel_nlog->nlogbytesize
) _b = (intel_nlog->nlogbytesize); do { } while (0); _a <
_b ? _a : _b; })
;
1507 err = read_entire_cmd(&cmd, intel_nlog->nlogbytesize / 4,
1508 0x400, output,
1509 hdl,
1510 buf);
1511 if (err)
1512 goto out;
1513 } else if (cfg.log == 1) {
1514 cmd.cdw13 = ehdr->edumps[j].coreoffset;
1515 cmd.cdw10 = 0x400;
1516 cmd.data_len = 0x400;
1517 err = read_entire_cmd(&cmd, ehdr->edumps[j].coresize,
1518 0x400, output,
1519 hdl,
1520 buf);
1521 if (err)
1522 goto out;
1523 }
1524 }
1525 }
1526 err = 0;
1527out:
1528 if (err)
1529 nvme_show_err(err, "intel log");
1530 else
1531 nvme_show_verbose_result("Successfully wrote log to %s", cfg.file)nvme_show_verbose_message("Successfully wrote log to %s", cfg
.file)
;
1532 close(output);
1533out_free:
1534 return err;
1535}
1536
1537static int enable_lat_stats_tracking(int argc, char **argv,
1538 struct command *command, struct plugin *plugin)
1539{
1540 const char *desc = (
1541 "Enable/Disable Intel Latency Statistics Tracking.\n"
1542 "No argument prints current status.");
1543 const char *enable_desc = "Enable LST";
1544 const char *disable_desc = "Disable LST";
1545 const __u32 nsid = 0;
1546 const __u8 fid = 0xe2;
1547 const __u8 sel = 0;
1548 const __u32 cdw11 = 0x0;
1549 const __u32 cdw12 = 0x0;
1550 const __u32 data_len = 32;
1551 const __u32 sv = 0;
1552 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1553 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1554 void *buf = NULL((void*)0);
1555 __u64 result;
1556 int err;
1557
1558 struct config {
1559 bool_Bool enable, disable;
1560 };
1561
1562 struct config cfg = {
1563 .enable = false0,
1564 .disable = false0,
1565 };
1566
1567 struct argconfig_commandline_options opts[] = {
1568 {"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument0, enable_desc},
1569 {"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument0, disable_desc},
1570 {NULL((void*)0)}
1571 };
1572
1573 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1574
1575 enum Option {
1576 None = -1,
1577 True = 1,
1578 False = 0,
1579 };
1580
1581 enum Option option = None;
1582
1583 if (cfg.enable && cfg.disable)
1584 nvme_show_error("Cannot enable and disable simultaneously.")nvme_show_message(1, "Cannot enable and disable simultaneously."
)
;
1585 else if (cfg.enable || cfg.disable)
1586 option = cfg.enable;
1587
1588 if (err)
1589 return err;
1590
1591 switch (option) {
1592 case None:
1593 err = nvme_get_features(hdl, nsid, fid, sel, cdw11, 0, buf,
1594 data_len, &result);
1595 if (!err) {
1596 printf(
1597 "Latency Statistics Tracking (FID 0x%X) is currently (%"PRIu64"l" "u"").\n",
1598 fid, (uint64_t)result);
1599 } else {
1600 nvme_show_error("Could not read feature id 0xE2.")nvme_show_message(1, "Could not read feature id 0xE2.");
1601 return err;
1602 }
1603 break;
1604 case True:
1605 case False:
1606 err = nvme_set_features(hdl, nsid, fid, sv, option, cdw12, 0, 0, 0, buf,
1607 data_len, &result);
1608 if (err) {
1609 nvme_show_err(err, "Enable latency tracking");
1610 } else {
1611 nvme_show_verbose_result("Successfully set enable bit for FID (0x%X) to %i.",nvme_show_verbose_message("Successfully set enable bit for FID (0x%X) to %i."
, fid, option)
1612 fid, option)nvme_show_verbose_message("Successfully set enable bit for FID (0x%X) to %i."
, fid, option)
;
1613 }
1614 break;
1615 default:
1616 nvme_show_error("%d not supported.", option)nvme_show_message(1, "%d not supported.", option);
1617 return -EINVAL22;
1618 }
1619 return err;
1620}
1621
1622static int set_lat_stats_thresholds(int argc, char **argv,
1623 struct command *command, struct plugin *plugin)
1624{
1625 const char *desc = "Write Intel Bucket Thresholds for Latency Statistics Tracking";
1626 const char *bucket_thresholds = "Bucket Threshold List, comma separated list: 0, 10, 20 ...";
1627 const char *write = "Set write bucket Thresholds for latency tracking (read default)";
1628
1629 const __u32 nsid = 0;
1630 const __u8 fid = 0xf7;
1631 const __u32 cdw12 = 0x0;
1632 const __u32 sv = 0;
1633 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1634 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1635 __u64 result;
1636 int err, num;
1637
1638 struct config {
1639 bool_Bool write;
1640 char *bucket_thresholds;
1641 };
1642
1643 struct config cfg = {
1644 .write = false0,
1645 .bucket_thresholds = "",
1646 };
1647
1648 NVME_ARGS(opts,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"bucket-thresholds", 't', "LIST", CFG_STRING,
&cfg.bucket_thresholds, 1, bucket_thresholds, 0, }, {"",
0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1649 OPT_FLAG("write", 'w', &cfg.write, write),nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"bucket-thresholds", 't', "LIST", CFG_STRING,
&cfg.bucket_thresholds, 1, bucket_thresholds, 0, }, {"",
0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1650 OPT_LIST("bucket-thresholds", 't', &cfg.bucket_thresholds,nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"bucket-thresholds", 't', "LIST", CFG_STRING,
&cfg.bucket_thresholds, 1, bucket_thresholds, 0, }, {"",
0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
1651 bucket_thresholds))nvme_args.supported_output_formats = (NORMAL | JSON | BINARY)
; struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"bucket-thresholds", 't', "LIST", CFG_STRING,
&cfg.bucket_thresholds, 1, bucket_thresholds, 0, }, {"",
0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Global options"
, 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT, &
nvme_args.verbose, 0, "Increase output verbosity", 0, }, {"quiet"
, 0, ((void*)0), CFG_FLAG, &nvme_args.quiet, 0, "suppress informational output"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary", 0, },
{"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1
, "timeout value, in milliseconds", 0, }, {"dry-run", 0, ((void
*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, {"set-options", 0, "KEY=VALUE", CFG_STRING
, &nvme_args.set_options, 1, "set a libnvme library option (key=value[,key=value,...]);"
, 0, }, { ((void*)0) } }
;
1652
1653 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1654
1655 if (err)
1656 return err;
1657
1658 /* Query maj and minor version first to figure out the amount of
1659 * valid buckets a user is allowed to modify. Read or write doesn't
1660 * matter
1661 */
1662 err = nvme_get_log_simple(hdl, 0xc2,
1663 media_version, sizeof(media_version));
1664 if (err) {
1665 nvme_show_error("Querying media version failed. ")nvme_show_message(1, "Querying media version failed. ");
1666 nvme_show_status(err);
1667 goto close_dev;
1668 }
1669
1670 if (media_version[0] == 1000) {
1671 int thresholds[OPTANE_V1000_BUCKET_LEN8] = {0};
1672
1673 num = shr_parse_csv_int(cfg.bucket_thresholds,
1674 thresholds,
1675 sizeof(thresholds));
1676 if (num == -1) {
1677 nvme_show_error("ERROR: Bucket list is malformed")nvme_show_message(1, "ERROR: Bucket list is malformed");
1678 goto close_dev;
1679
1680 }
1681
1682 err = nvme_set_features(hdl, nsid, fid, sv, cfg.write ? 0x1 : 0x0, cdw12,
1683 0, 0, 0, thresholds, sizeof(thresholds), &result);
1684
1685 if (err)
1686 nvme_show_err(err, "Enable latency tracking");
1687 } else {
1688 nvme_show_error("Unsupported command")nvme_show_message(1, "Unsupported command");
1689 }
1690
1691close_dev:
1692 return err;
1693}
1694
1695static struct command id_ctrl_cmd = {
1696 .name = "id-ctrl",
1697 .help = "Send NVMe Identify Controller",
1698 .fn = id_ctrl,
1699};
1700
1701static struct command get_internal_log_cmd = {
1702 .name = "internal-log",
1703 .help = "Retrieve Intel internal firmware log, save it",
1704 .fn = get_internal_log,
1705};
1706
1707static struct command get_lat_stats_log_cmd = {
1708 .name = "lat-stats",
1709 .help = "Retrieve Intel IO Latency Statistics log, show it",
1710 .fn = get_lat_stats_log,
1711};
1712
1713static struct command set_lat_stats_thresholds_cmd = {
1714 .name = "set-bucket-thresholds",
1715 .help = "Set Latency Stats Bucket Values, save it",
1716 .fn = set_lat_stats_thresholds,
1717};
1718
1719static struct command enable_lat_stats_tracking_cmd = {
1720 .name = "lat-stats-tracking",
1721 .help = "Enable and disable Latency Statistics logging.",
1722 .fn = enable_lat_stats_tracking,
1723};
1724
1725static struct command get_market_log_cmd = {
1726 .name = "market-name",
1727 .help = "Retrieve Intel Marketing Name log, show it",
1728 .fn = get_market_log,
1729};
1730
1731static struct command get_additional_smart_log_cmd = {
1732 .name = "smart-log-add",
1733 .help = "Retrieve Intel SMART Log, show it",
1734 .fn = get_additional_smart_log,
1735};
1736
1737static struct command get_temp_stats_log_cmd = {
1738 .name = "temp-stats",
1739 .help = "Retrieve Intel Temperature Statistics log, show it",
1740 .fn = get_temp_stats_log,
1741};
1742
1743static struct command *commands[] = {
1744 &id_ctrl_cmd,
1745 &get_internal_log_cmd,
1746 &get_lat_stats_log_cmd,
1747 &set_lat_stats_thresholds_cmd,
1748 &enable_lat_stats_tracking_cmd,
1749 &get_market_log_cmd,
1750 &get_additional_smart_log_cmd,
1751 &get_temp_stats_log_cmd,
1752 NULL((void*)0),
1753};
1754
1755static struct plugin plugin = {
1756 .name = "intel",
1757 .desc = "Intel vendor specific extensions",
1758 .version = NVME_VERSION"3.1",
1759};
1760
1761static void __shr_constructor__attribute__((constructor)) register_plugin(void)
1762{
1763 plugin_add_group(&plugin, NULL((void*)0), commands);
1764 register_extension(&plugin);
1765}
1766