Bug Summary

File:.build-ci/../plugins/memblaze/memblaze-nvme.c
Warning:line 885, column 2
Null pointer passed to 4th parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name memblaze-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 pic -pic-level 2 -pic-is-pie -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/lib/llvm-19/lib/clang/19 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -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/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -std=gnu99 -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 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-06-24-175442-590-1 -x c ../plugins/memblaze/memblaze-nvme.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2#include <fcntl.h>
3#include <errno(*__errno_location ()).h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <sys/stat.h>
7#include <unistd.h>
8#include <time.h>
9
10#include <libnvme.h>
11
12#include "common.h"
13#include "nvme-cmds.h"
14#include "nvme-print.h"
15#include "nvme.h"
16#include "plugin.h"
17
18#define CREATE_CMD
19#include "memblaze-nvme.h"
20#include "memblaze-utils.h"
21
22enum {
23 /* feature id */
24 MB_FEAT_POWER_MGMT = 0x02,
25 MB_FEAT_HIGH_LATENCY = 0xE1,
26 /* log id */
27 GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM = 0xC1,
28 GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM = 0xC2,
29 GLP_ID_VU_GET_HIGH_LATENCY_LOG = 0xC3,
30 MB_FEAT_CLEAR_ERRORLOG = 0xF7,
31};
32
33#define LOG_PAGE_SIZE(0x1000) (0x1000)
34#define DO_PRINT_FLAG(1) (1)
35#define NOT_PRINT_FLAG(0) (0)
36#define FID_C1_LOG_FILENAME"log_c1.csv" "log_c1.csv"
37#define FID_C2_LOG_FILENAME"log_c2.csv" "log_c2.csv"
38#define FID_C3_LOG_FILENAME"log_c3.csv" "log_c3.csv"
39
40/*
41 * Return -1 if @fw1 < @fw2
42 * Return 0 if @fw1 == @fw2
43 * Return 1 if @fw1 > @fw2
44 */
45static int compare_fw_version(const char *fw1, const char *fw2)
46{
47 while (*fw1 != '\0') {
48 if (*fw2 == '\0' || *fw1 > *fw2)
49 return 1;
50 if (*fw1 < *fw2)
51 return -1;
52 fw1++;
53 fw2++;
54 }
55
56 if (*fw2 != '\0')
57 return -1;
58
59 return 0;
60}
61
62/**********************************************************
63 * input: firmware version string
64 * output:
65 * 1: new intel format
66 * 0: old memblaze format
67 * *******************************************************/
68#define MEMBLAZE_FORMAT(0) (0)
69#define INTEL_FORMAT(1) (1)
70
71/* 2.13 = papaya */
72#define IS_PAPAYA(str)(!strcmp(str, "2.13")) (!strcmp(str, "2.13"))
73/* 2.83 = raisin */
74#define IS_RAISIN(str)(!strcmp(str, "2.83")) (!strcmp(str, "2.83"))
75/* 2.94 = kumquat */
76#define IS_KUMQUAT(str)(!strcmp(str, "2.94")) (!strcmp(str, "2.94"))
77/* 0.60 = loquat */
78#define IS_LOQUAT(str)(!strcmp(str, "0.60")) (!strcmp(str, "0.60"))
79
80#define STR_VER_SIZE(5) (5)
81
82int getlogpage_format_type(char *model_name)
83{
84 int logpage_format_type = INTEL_FORMAT(1);
85 const char *boundary_model_name1 = "P"; /* MEMBLAZE P7936DT0640M00 */
86 const char *boundary_model_name2 = "P5920"; /* Use INTEL_FORMAT from Raisin P5920. */
87
88 if (!strncmp(model_name, boundary_model_name1, strlen(boundary_model_name1))) {
89 if (strncmp(model_name, boundary_model_name2, strlen(boundary_model_name2)) < 0)
90 logpage_format_type = MEMBLAZE_FORMAT(0);
91 }
92 return logpage_format_type;
93}
94
95static __u32 item_id_2_u32(struct nvme_memblaze_smart_log_item *item)
96{
97 __le32 __id = 0;
98
99 memcpy(&__id, item->id, 3);
100 return le32_to_cpu(__id);
101}
102
103static __u64 raw_2_u64(const __u8 *buf, size_t len)
104{
105 __le64 val = 0;
106
107 memcpy(&val, buf, len);
108 return le64_to_cpu(val);
109}
110
111static void get_memblaze_new_smart_info(struct nvme_p4_smart_log *smart,
112 int index, __u8 *nm_val, __u8 *raw_val)
113{
114 memcpy(nm_val, smart->itemArr[index].nmVal, NM_SIZE2);
115 memcpy(raw_val, smart->itemArr[index].rawVal, RAW_SIZE7);
116}
117
118static void show_memblaze_smart_log_new(struct nvme_memblaze_smart_log *s, unsigned int nsid,
119 const char *devname)
120{
121 struct nvme_p4_smart_log *smart = (struct nvme_p4_smart_log *)s;
122 __u8 *nm = malloc(NM_SIZE2 * sizeof(__u8));
123 __u8 *raw = malloc(RAW_SIZE7 * sizeof(__u8));
124
125 if (!nm) {
126 free(raw);
127 return;
128 }
129 if (!raw) {
130 free(nm);
131 return;
132 }
133
134 printf("%s:%s %s:%x\n", "Additional Smart Log for NVME device", devname, "namespace-id",
135 nsid);
136 printf("%-34s%-11s%s\n", "key", "normalized", "raw");
137
138 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_PROGRAM_FAIL, nm, raw);
139 printf("%-32s: %3d%% %"PRIu64"l" "u""\n", "program_fail_count", *nm, int48_to_long(raw));
140
141 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_ERASE_FAIL, nm, raw);
142 printf("%-32s: %3d%% %"PRIu64"l" "u""\n", "erase_fail_count", *nm, int48_to_long(raw));
143
144 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_WEARLEVELING_COUNT, nm, raw);
145 printf("%-31s : %3d%% %s%u%s%u%s%u\n", "wear_leveling", *nm, "min: ", *(__u16 *)raw,
146 ", max: ", *(__u16 *)(raw+2), ", avg: ", *(__u16 *)(raw+4));
147
148 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_E2E_DECTECTION_COUNT, nm, raw);
149 printf("%-31s: %3d%% %"PRIu64"l" "u""\n", "end_to_end_error_detection_count", *nm,
150 int48_to_long(raw));
151
152 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_PCIE_CRC_ERR_COUNT, nm, raw);
153 printf("%-32s: %3d%% %"PRIu64"l" "u""\n", "crc_error_count", *nm, int48_to_long(raw));
154
155 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR, nm, raw);
156 printf("%-32s: %3d%% %.3f%%\n", "timed_workload_media_wear", *nm,
157 ((float)int48_to_long(raw))/1000);
158
159 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ, nm, raw);
160 printf("%-32s: %3d%% %"PRIu64"l" "u""%%\n", "timed_workload_host_reads", *nm,
161 int48_to_long(raw));
162
163 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_TIMER, nm, raw);
164 printf("%-32s: %3d%% %"PRIu64"l" "u""%s\n", "timed_workload_timer", *nm,
165 int48_to_long(raw), " min");
166
167 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_THERMAL_THROTTLE_STATUS, nm, raw);
168 printf("%-32s: %3d%% %u%%%s%"PRIu64"l" "u""\n", "thermal_throttle_status", *nm, *raw,
169 ", cnt: ", int48_to_long(raw+1));
170
171 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT, nm, raw);
172 printf("%-32s: %3d%% %"PRIu64"l" "u""\n", "retry_buffer_overflow_count", *nm,
173 int48_to_long(raw));
174
175 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT, nm, raw);
176 printf("%-32s: %3d%% %"PRIu64"l" "u""\n", "pll_lock_loss_count", *nm,
177 int48_to_long(raw));
178
179 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TOTAL_WRITE, nm, raw);
180 printf("%-32s: %3d%% %s%"PRIu64"l" "u""\n", "nand_bytes_written", *nm, "sectors: ",
181 int48_to_long(raw));
182
183 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_HOST_WRITE, nm, raw);
184 printf("%-32s: %3d%% %s%"PRIu64"l" "u""\n", "host_bytes_written", *nm, "sectors: ",
185 int48_to_long(raw));
186
187 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT, nm, raw);
188 printf("%-32s: %3d%% %"PRIu64"l" "u""\n", "system_area_life_left", *nm,
189 int48_to_long(raw));
190
191 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TOTAL_READ, nm, raw);
192 printf("%-32s: %3d%% %"PRIu64"l" "u""\n", "total_read", *nm, int48_to_long(raw));
193
194 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TEMPT_SINCE_BORN, nm, raw);
195 printf("%-32s: %3d%% %s%u%s%u%s%u\n", "tempt_since_born", *nm,
196 "max: ", *(__u16 *)raw, ", min: ", *(__u16 *)(raw+2), ", curr: ", *(__u16 *)(raw+4));
197
198 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_POWER_CONSUMPTION, nm, raw);
199 printf("%-32s: %3d%% %s%u%s%u%s%u\n", "power_consumption", *nm,
200 "max: ", *(__u16 *)raw, ", min: ", *(__u16 *)(raw+2), ", curr: ", *(__u16 *)(raw+4));
201
202 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TEMPT_SINCE_BOOTUP, nm, raw);
203 printf("%-32s: %3d%% %s%u%s%u%s%u\n", "tempt_since_bootup", *nm, "max: ",
204 *(__u16 *)raw, ", min: ", *(__u16 *)(raw+2), ", curr: ", *(__u16 *)(raw+4));
205
206 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_READ_FAIL, nm, raw);
207 printf("%-32s: %3d%% %"PRIu64"l" "u""\n", "read_fail_count", *nm, int48_to_long(raw));
208
209 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_THERMAL_THROTTLE_TIME, nm, raw);
210 printf("%-32s: %3d%% %"PRIu64"l" "u""\n", "thermal_throttle_time", *nm, int48_to_long(raw));
211
212 get_memblaze_new_smart_info(smart, RAISIN_SI_VD_FLASH_MEDIA_ERROR, nm, raw);
213 printf("%-32s: %3d%% %"PRIu64"l" "u""\n", "flash_media_error", *nm, int48_to_long(raw));
214
215 free(nm);
216 free(raw);
217}
218
219static void show_memblaze_smart_log_old(struct nvme_memblaze_smart_log *smart,
220 unsigned int nsid, const char *devname, const char *fw_ver)
221{
222 char fw_ver_local[STR_VER_SIZE(5) + 1];
223 struct nvme_memblaze_smart_log_item *item;
224
225 strncpy(fw_ver_local, fw_ver, STR_VER_SIZE(5));
226 *(fw_ver_local + STR_VER_SIZE(5)) = '\0';
227
228 printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid);
229
230 printf("Total write in GB since last factory reset : %"PRIu64"l" "u""\n",
231 int48_to_long(smart->items[TOTAL_WRITE].rawval));
232 printf("Total read in GB since last factory reset : %"PRIu64"l" "u""\n",
233 int48_to_long(smart->items[TOTAL_READ].rawval));
234
235 printf("Thermal throttling status[1:HTP in progress] : %u\n",
236 smart->items[THERMAL_THROTTLE].thermal_throttle.on);
237 printf("Total thermal throttling minutes since power on : %u\n",
238 smart->items[THERMAL_THROTTLE].thermal_throttle.count);
239
240 printf("Maximum temperature in kelvins since last factory reset : %u\n",
241 le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.max));
242 printf("Minimum temperature in kelvins since last factory reset : %u\n",
243 le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.min));
244 if (compare_fw_version(fw_ver, "0.09.0300") != 0) {
245 printf("Maximum temperature in kelvins since power on : %u\n",
246 le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.max));
247 printf("Minimum temperature in kelvins since power on : %u\n",
248 le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.min));
249 }
250 printf("Current temperature in kelvins : %u\n",
251 le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.curr));
252
253 printf("Maximum power in watt since power on : %u\n",
254 le16_to_cpu(smart->items[POWER_CONSUMPTION].power.max));
255 printf("Minimum power in watt since power on : %u\n",
256 le16_to_cpu(smart->items[POWER_CONSUMPTION].power.min));
257 printf("Current power in watt : %u\n",
258 le16_to_cpu(smart->items[POWER_CONSUMPTION].power.curr));
259
260 item = &smart->items[POWER_LOSS_PROTECTION];
261 if (item_id_2_u32(item) == 0xEC)
262 printf("Power loss protection normalized value : %u\n",
263 item->power_loss_protection.curr);
264
265 item = &smart->items[WEARLEVELING_COUNT];
266 if (item_id_2_u32(item) == 0xAD) {
267 printf("Percentage of wearleveling count left : %u\n",
268 le16_to_cpu(item->nmval));
269 printf("Wearleveling count min erase cycle : %u\n",
270 le16_to_cpu(item->wearleveling_count.min));
271 printf("Wearleveling count max erase cycle : %u\n",
272 le16_to_cpu(item->wearleveling_count.max));
273 printf("Wearleveling count avg erase cycle : %u\n",
274 le16_to_cpu(item->wearleveling_count.avg));
275 }
276
277 item = &smart->items[HOST_WRITE];
278 if (item_id_2_u32(item) == 0xF5)
279 printf("Total host write in GiB since device born : %llu\n",
280 (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
281
282 item = &smart->items[THERMAL_THROTTLE_CNT];
283 if (item_id_2_u32(item) == 0xEB)
284 printf("Thermal throttling count since device born : %u\n",
285 item->thermal_throttle_cnt.cnt);
286
287 item = &smart->items[CORRECT_PCIE_PORT0];
288 if (item_id_2_u32(item) == 0xED)
289 printf("PCIE Correctable Error Count of Port0 : %llu\n",
290 (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
291
292 item = &smart->items[CORRECT_PCIE_PORT1];
293 if (item_id_2_u32(item) == 0xEE)
294 printf("PCIE Correctable Error Count of Port1 : %llu\n",
295 (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
296
297 item = &smart->items[REBUILD_FAIL];
298 if (item_id_2_u32(item) == 0xEF)
299 printf("End-to-End Error Detection Count : %llu\n",
300 (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
301
302 item = &smart->items[ERASE_FAIL];
303 if (item_id_2_u32(item) == 0xF0)
304 printf("Erase Fail Count : %llu\n",
305 (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
306
307 item = &smart->items[PROGRAM_FAIL];
308 if (item_id_2_u32(item) == 0xF1)
309 printf("Program Fail Count : %llu\n",
310 (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
311
312 item = &smart->items[READ_FAIL];
313 if (item_id_2_u32(item) == 0xF2)
314 printf("Read Fail Count : %llu\n",
315 (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval)));
316
317 if (IS_PAPAYA(fw_ver_local)(!strcmp(fw_ver_local, "2.13"))) {
318 struct nvme_p4_smart_log *s = (struct nvme_p4_smart_log *)smart;
319 __u8 *nm = malloc(NM_SIZE2 * sizeof(__u8));
320 __u8 *raw = malloc(RAW_SIZE7 * sizeof(__u8));
321
322 if (!nm) {
323 free(raw);
324 return;
325 }
326 if (!raw) {
327 free(nm);
328 return;
329 }
330 get_memblaze_new_smart_info(s, PROGRAM_FAIL, nm, raw);
331 printf("%-32s : %3d%% %"PRIu64"l" "u""\n",
332 "program_fail_count", *nm, int48_to_long(raw));
333
334 get_memblaze_new_smart_info(s, ERASE_FAIL, nm, raw);
335 printf("%-32s : %3d%% %"PRIu64"l" "u""\n",
336 "erase_fail_count", *nm, int48_to_long(raw));
337
338 get_memblaze_new_smart_info(s, WEARLEVELING_COUNT, nm, raw);
339 printf("%-31s : %3d%% %s%u%s%u%s%u\n",
340 "wear_leveling", *nm, "min: ", *(__u16 *)raw, ", max: ", *(__u16 *)(raw+2),
341 ", avg: ", *(__u16 *)(raw+4));
342
343 get_memblaze_new_smart_info(s, TOTAL_WRITE, nm, raw);
344 printf("%-32s : %3d%% %"PRIu64"l" "u""\n",
345 "nand_bytes_written", *nm, 32*int48_to_long(raw));
346
347 get_memblaze_new_smart_info(s, HOST_WRITE, nm, raw);
348 printf("%-32s : %3d%% %"PRIu64"l" "u""\n",
349 "host_bytes_written", *nm, 32*int48_to_long(raw));
350
351 free(nm);
352 free(raw);
353 }
354}
355
356static int show_memblaze_smart_log(struct libnvme_transport_handle *hdl, __u32 nsid,
357 const char *devname, struct nvme_memblaze_smart_log *smart)
358{
359 struct nvme_id_ctrl ctrl;
360 char fw_ver[10];
361 int err = 0;
362
363 err = nvme_identify_ctrl(hdl, &ctrl);
364 if (err)
365 return err;
366
367 snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c",
368 ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3],
369 ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]);
370
371 if (getlogpage_format_type(ctrl.mn)) /* Intel Format & new format */
372 show_memblaze_smart_log_new(smart, nsid, devname);
373 else /* Memblaze Format & old format */
374 show_memblaze_smart_log_old(smart, nsid, devname, fw_ver);
375 return err;
376}
377
378int parse_params(char *str, int number, ...)
379{
380 va_list argp;
381 int *param;
382 char *c;
383 int value;
384
385 va_start(argp, number)__builtin_va_start(argp, number);
386
387 while (number > 0) {
388 c = strtok(str, ",");
389 if (!c) {
390 printf("No enough parameters. abort...\n");
391 va_end(argp)__builtin_va_end(argp);
392 return 1;
393 }
394
395 if (!isalnum((int)*c)((*__ctype_b_loc ())[(int) (((int)*c))] & (unsigned short
int) _ISalnum)
) {
396 printf("%s is not a valid number\n", c);
397 va_end(argp)__builtin_va_end(argp);
398 return 1;
399 }
400 value = atoi(c);
401 param = va_arg(argp, int *)__builtin_va_arg(argp, int *);
402 *param = value;
403
404 if (str) {
405 str = strchr(str, ',');
406 if (str)
407 str++;
408 }
409 number--;
410 }
411 va_end(argp)__builtin_va_end(argp);
412
413 return 0;
414}
415
416static int mb_get_additional_smart_log(int argc, char **argv, struct command *acmd,
417 struct plugin *plugin)
418{
419 struct nvme_memblaze_smart_log smart_log;
420 char *desc =
421 "Get Memblaze vendor specific additional smart log, and show it.";
422 const char *namespace = "(optional) desired namespace";
423 const char *raw = "dump output in binary format";
424 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
425 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
426 struct config {
427 __u32 namespace_id;
428 bool_Bool raw_binary;
429 };
430 int err;
431
432 struct config cfg = {
433 .namespace_id = NVME_NSID_ALL,
434 };
435
436 NVME_ARGS(opts,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, }, {"", 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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
437 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),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, }, {"", 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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
438 OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw))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, }, {"", 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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
439
440 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
441 if (err)
442 return err;
443
444 err = nvme_get_nsid_log(hdl, cfg.namespace_id, false0, 0xca,
445 &smart_log, sizeof(smart_log));
446 if (!err) {
447 if (!cfg.raw_binary)
448 err = show_memblaze_smart_log(hdl, cfg.namespace_id,
449 libnvme_transport_handle_get_name(hdl),
450 &smart_log);
451 else
452 d_raw((unsigned char *)&smart_log, sizeof(smart_log));
453 }
454 if (err > 0)
455 nvme_show_status(err);
456
457 return err;
458}
459
460static char *mb_feature_to_string(int feature)
461{
462 switch (feature) {
463 case MB_FEAT_POWER_MGMT:
464 return "Memblaze power management";
465 case MB_FEAT_HIGH_LATENCY:
466 return "Memblaze high latency log";
467 case MB_FEAT_CLEAR_ERRORLOG:
468 return "Memblaze clear error log";
469 default:
470 return "Unknown";
471 }
472}
473
474static int mb_get_powermanager_status(int argc, char **argv, struct command *acmd,
475 struct plugin *plugin)
476{
477 const char *desc = "Get Memblaze power management ststus\n (value 0 - 25w, 1 - 20w, 2 - 15w)";
478 __u64 result;
479 __u32 feature_id = MB_FEAT_POWER_MGMT;
480 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
481 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
482 int err;
483
484 NVME_ARGS(opts)struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
485
486 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
487 if (err)
488 return err;
489
490 err = nvme_get_features(hdl, 0, feature_id, 0, 0, 0, NULL((void*)0), 0, &result);
491 if (err < 0)
492 perror("get-feature");
493 if (!err)
494 printf("get-feature:0x%02x (%s), %s value: %#016" PRIx64"l" "x" "\n",
495 feature_id, mb_feature_to_string(feature_id),
496 nvme_select_to_string(0), (uint64_t)result);
497 else if (err > 0)
498 nvme_show_status(err);
499 return err;
500}
501
502static int mb_set_powermanager_status(int argc, char **argv, struct command *acmd,
503 struct plugin *plugin)
504{
505 const char *desc = "Set Memblaze power management status\n (value 0 - 25w, 1 - 20w, 2 - 15w)";
506 const char *value = "new value of feature (required)";
507 const char *save = "specifies that the controller shall save the attribute";
508 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
509 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
510 __u64 result;
511 int err;
512
513 struct config {
514 __u32 feature_id;
515 __u32 value;
516 bool_Bool save;
517 };
518
519 struct config cfg = {
520 .feature_id = MB_FEAT_POWER_MGMT,
521 .value = 0,
522 .save = 0,
523 };
524
525 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"value", 'V', "NUM", CFG_POSITIVE, &cfg.value, 1,
value, 0, }, {"save", 's', ((void*)0), CFG_FLAG, &cfg.save
, 0, save, 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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
526 OPT_UINT("value", 'V', &cfg.value, value),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"value", 'V', "NUM", CFG_POSITIVE, &cfg.value, 1,
value, 0, }, {"save", 's', ((void*)0), CFG_FLAG, &cfg.save
, 0, save, 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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
527 OPT_FLAG("save", 's', &cfg.save, save))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"value", 'V', "NUM", CFG_POSITIVE, &cfg.value, 1,
value, 0, }, {"save", 's', ((void*)0), CFG_FLAG, &cfg.save
, 0, save, 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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
528
529 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
530 if (err)
531 return err;
532
533 err = nvme_set_features(hdl, 0, cfg.feature_id, cfg.save, cfg.value, 0, 0, 0,
534 0, NULL((void*)0), 0, &result);
535 if (err < 0)
536 perror("set-feature");
537 if (!err)
538 printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
539 mb_feature_to_string(cfg.feature_id), cfg.value);
540 else if (err > 0)
541 nvme_show_status(err);
542
543 return err;
544}
545
546#define P2MIN(1) (1)
547#define P2MAX(5000) (5000)
548#define MB_FEAT_HIGH_LATENCY_VALUE_SHIFT(15) (15)
549static int mb_set_high_latency_log(int argc, char **argv, struct command *acmd,
550 struct plugin *plugin)
551{
552 const char *desc = "Set Memblaze high latency log\n"
553 " input parameter p1,p2\n"
554 " p1 value: 0 is disable, 1 is enable\n"
555 " p2 value: 1 .. 5000 ms";
556 const char *param = "input parameters";
557 int param1 = 0, param2 = 0;
558 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
559 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
560
561 __u64 result;
562 int err;
563
564 struct config {
565 __u32 feature_id;
566 char *param;
567 __u32 value;
568 };
569
570 struct config cfg = {
571 .feature_id = MB_FEAT_HIGH_LATENCY,
572 .param = "0,0",
573 .value = 0,
574 };
575
576 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"param", 'p', "LIST", CFG_STRING, &cfg.param, 1, param
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
577 OPT_LIST("param", 'p', &cfg.param, param))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"param", 'p', "LIST", CFG_STRING, &cfg.param, 1, param
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
578
579 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
580 if (err)
581 return err;
582
583 if (parse_params(cfg.param, 2, &param1, &param2)) {
584 printf("setfeature: invalid formats %s\n", cfg.param);
585 return -EINVAL22;
586 }
587 if ((param1 == 1) && (param2 < P2MIN(1) || param2 > P2MAX(5000))) {
588 printf("setfeature: invalid high io latency threshold %d\n", param2);
589 return -EINVAL22;
590 }
591 cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT(15)) | param2;
592
593 err = nvme_set_features(hdl, 0, cfg.feature_id, false0, cfg.value, 0, 0, 0,
594 0, NULL((void*)0), 0, &result);
595 if (err < 0)
596 perror("set-feature");
597 if (!err)
598 printf("set-feature:0x%02X (%s), value:%#08x\n", cfg.feature_id,
599 mb_feature_to_string(cfg.feature_id), cfg.value);
600 else if (err > 0)
601 nvme_show_status(err);
602
603 return err;
604}
605
606static int glp_high_latency_show_bar(FILE *fdi, int print)
607{
608 fPRINT_PARAM1("Memblaze High Latency Log\n")do { if (fdi) fprintf(fdi, "Memblaze High Latency Log\n"); if
(print) printf("Memblaze High Latency Log\n"); } while (0)
;
609 fPRINT_PARAM1("---------------------------------------------------------------------------------------------\n")do { if (fdi) fprintf(fdi, "---------------------------------------------------------------------------------------------\n"
); if (print) printf("---------------------------------------------------------------------------------------------\n"
); } while (0)
;
610 fPRINT_PARAM1("Timestamp Type QID CID NSID StartLBA NumLBA Latency\n")do { if (fdi) fprintf(fdi, "Timestamp Type QID CID NSID StartLBA NumLBA Latency\n"
); if (print) printf("Timestamp Type QID CID NSID StartLBA NumLBA Latency\n"
); } while (0)
;
611 fPRINT_PARAM1("---------------------------------------------------------------------------------------------\n")do { if (fdi) fprintf(fdi, "---------------------------------------------------------------------------------------------\n"
); if (print) printf("---------------------------------------------------------------------------------------------\n"
); } while (0)
;
612 return 0;
613}
614
615/*
616 * High latency log page definition
617 * Total 32 bytes
618 */
619struct log_page_high_latency {
620 __u8 port;
621 __u8 revision;
622 __u16 rsvd;
623 __u8 opcode;
624 __u8 sqe;
625 __u16 cid;
626 __u32 nsid;
627 __u32 latency;
628 __u64 sLBA;
629 __u16 numLBA;
630 __u16 timestampH;
631 __u32 timestampL;
632}; /* total 32 bytes */
633
634static int find_deadbeef(char *buf)
635{
636 if (((*(buf + 0) & 0xff) == 0xef) && ((*(buf + 1) & 0xff) == 0xbe) &&
637 ((*(buf + 2) & 0xff) == 0xad) && ((*(buf + 3) & 0xff) == 0xde))
638 return 1;
639 return 0;
640}
641
642#define TIME_STR_SIZE(44) (44)
643static int glp_high_latency(FILE *fdi, char *buf, int buflen, int print)
644{
645 struct log_page_high_latency *logEntry;
646 char string[TIME_STR_SIZE(44)];
647 int i, entrySize;
648 __u64 timestamp;
649 time_t tt = 0;
650 struct tm *t = NULL((void*)0);
651 int millisec = 0;
652
653 if (find_deadbeef(buf))
654 return 0;
655
656 entrySize = sizeof(struct log_page_high_latency);
657 for (i = 0; i < buflen; i += entrySize) {
658 logEntry = (struct log_page_high_latency *)(buf + i);
659
660 if (logEntry->latency == 0 && logEntry->revision == 0)
661 return 1;
662
663 if (!logEntry->timestampH) { /* generate host time string */
664 snprintf(string, sizeof(string), "%d", logEntry->timestampL);
665 } else { /* sort */
666 timestamp = logEntry->timestampH;
667 timestamp = timestamp << 32;
668 timestamp += logEntry->timestampL;
669 tt = timestamp / 1000;
670 millisec = timestamp % 1000;
671 t = gmtime(&tt);
672 snprintf(string, sizeof(string), "%4d%02d%02d--%02d:%02d:%02d.%03d UTC",
673 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour,
674 t->tm_min, t->tm_sec, millisec);
675 }
676
677 if (fdi)
678 fprintf(fdi, "%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n",
679 string, logEntry->opcode, logEntry->sqe,
680 logEntry->cid, logEntry->nsid,
681 (__u32)(logEntry->sLBA >> 32),
682 (__u32)logEntry->sLBA, logEntry->numLBA,
683 logEntry->latency);
684 if (print)
685 printf("%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n",
686 string, logEntry->opcode, logEntry->sqe, logEntry->cid,
687 logEntry->nsid, (__u32)(logEntry->sLBA >> 32), (__u32)logEntry->sLBA,
688 logEntry->numLBA, logEntry->latency);
689 }
690 return 1;
691}
692
693static int mb_high_latency_log_print(int argc, char **argv, struct command *acmd,
694 struct plugin *plugin)
695{
696 const char *desc = "Get Memblaze high latency log";
697 char buf[LOG_PAGE_SIZE(0x1000)];
698 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
699 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
700
701 FILE *fdi = NULL((void*)0);
702 int err;
703
704 NVME_ARGS(opts)struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
705
706 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
707 if (err)
708 return err;
709
710 fdi = fopen(FID_C3_LOG_FILENAME"log_c3.csv", "w+");
711
712 glp_high_latency_show_bar(fdi, DO_PRINT_FLAG(1));
713 err = nvme_get_log_simple(hdl, GLP_ID_VU_GET_HIGH_LATENCY_LOG, &buf, sizeof(buf));
714
715 while (1) {
716 if (!glp_high_latency(fdi, buf, LOG_PAGE_SIZE(0x1000), DO_PRINT_FLAG(1)))
717 break;
718 err = nvme_get_log_simple(hdl, GLP_ID_VU_GET_HIGH_LATENCY_LOG,
719 &buf, sizeof(buf));
720 if (err) {
721 nvme_show_status(err);
722 break;
723 }
724 }
725
726 if (fdi)
727 fclose(fdi);
728 return err;
729}
730
731static int memblaze_fw_commit(struct libnvme_transport_handle *hdl, int select)
732{
733 struct libnvme_passthru_cmd cmd = {
734 .opcode = nvme_admin_fw_commit,
735 .cdw10 = 8,
736 .cdw12 = select,
737 };
738
739 return libnvme_exec_admin_passthru(hdl, &cmd);
740}
741
742static int mb_selective_download(int argc, char **argv, struct command *acmd, struct plugin *plugin)
743{
744 const char *desc =
745 "This performs a selective firmware download, which allows the user to\n"
746 "select which firmware binary to update for 9200 devices. This requires a power cycle once the\n"
747 "update completes. The options available are:\n\n"
748 "OOB - This updates the OOB and main firmware\n"
749 "EEP - This updates the eeprom and main firmware\n"
750 "ALL - This updates the eeprom, OOB, and main firmware";
751 const char *fw = "firmware file (required)";
752 const char *select = "FW Select (e.g., --select=OOB, EEP, ALL)";
753
754 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
755 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
756
757 int selectNo, fw_fd, fw_size, err, offset = 0;
758 struct libnvme_passthru_cmd cmd;
759 int xfer = 4096;
760 struct stat sb;
761 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) void *fw_buf = NULL((void*)0);
762 unsigned char *fw_ptr;
763 int i;
764
765 struct config {
766 char *fw;
767 char *select;
768 };
769
770 struct config cfg = {
771 .fw = "",
772 .select = "\0",
773 };
774
775 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"fw", 'f', "FILE", CFG_STRING, &cfg.fw, 1, fw, 0,
}, {"select", 's', "flag", CFG_STRING, &cfg.select, 1, select
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
776 OPT_STRING("fw", 'f', "FILE", &cfg.fw, fw),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"fw", 'f', "FILE", CFG_STRING, &cfg.fw, 1, fw, 0,
}, {"select", 's', "flag", CFG_STRING, &cfg.select, 1, select
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
777 OPT_STRING("select", 's', "flag", &cfg.select, select))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"fw", 'f', "FILE", CFG_STRING, &cfg.fw, 1, fw, 0,
}, {"select", 's', "flag", CFG_STRING, &cfg.select, 1, select
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
778
779 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
780 if (err)
781 return err;
782
783 if (strlen(cfg.select) != 3) {
784 fprintf(stderrstderr, "Invalid select flag\n");
785 err = EINVAL22;
786 goto out;
787 }
788
789 for (i = 0; i < 3; i++)
790 cfg.select[i] = toupper(cfg.select[i])(__extension__ ({ int __res; if (sizeof (cfg.select[i]) > 1
) { if (__builtin_constant_p (cfg.select[i])) { int __c = (cfg
.select[i]); __res = __c < -128 || __c > 255 ? __c : (*
__ctype_toupper_loc ())[__c]; } else __res = toupper (cfg.select
[i]); } else __res = (*__ctype_toupper_loc ())[(int) (cfg.select
[i])]; __res; }))
;
791
792 if (!strncmp(cfg.select, "OOB", 3)) {
793 selectNo = 18;
794 } else if (!strncmp(cfg.select, "EEP", 3)) {
795 selectNo = 10;
796 } else if (!strncmp(cfg.select, "ALL", 3)) {
797 selectNo = 26;
798 } else {
799 fprintf(stderrstderr, "Invalid select flag\n");
800 err = EINVAL22;
801 goto out;
802 }
803
804 fw_fd = open(cfg.fw, O_RDONLY00);
805 if (fw_fd < 0) {
806 fprintf(stderrstderr, "no firmware file provided\n");
807 err = EINVAL22;
808 goto out;
809 }
810
811 err = fstat(fw_fd, &sb);
812 if (err < 0) {
813 perror("fstat");
814 err = errno(*__errno_location ());
815 goto out_close;
816 }
817
818 fw_size = sb.st_size;
819 if (fw_size & 0x3) {
820 fprintf(stderrstderr, "Invalid size:%d for f/w image\n", fw_size);
821 err = EINVAL22;
822 goto out_close;
823 }
824
825 fw_buf = libnvme_alloc(fw_size);
826 if (!fw_buf) {
827 fprintf(stderrstderr, "No memory for f/w size:%d\n", fw_size);
828 err = ENOMEM12;
829 goto out_close;
830 }
831 fw_ptr = fw_buf;
832
833 if (read(fw_fd, fw_buf, fw_size) != ((ssize_t)(fw_size))) {
834 err = errno(*__errno_location ());
835 goto out_close;
836 }
837
838 while (fw_size > 0) {
839 xfer = min(xfer, fw_size)((xfer) > (fw_size) ? (fw_size) : (xfer));
840
841 err = nvme_init_fw_download(&cmd, fw_ptr, xfer, offset);
842 if (err) {
843 perror("fw-download");
844 goto out_close;
845 }
846 err = libnvme_exec_admin_passthru(hdl, &cmd);
847 if (err < 0) {
848 perror("fw-download");
849 goto out_close;
850 } else if (err != 0) {
851 nvme_show_status(err);
852 goto out_close;
853 }
854 fw_ptr += xfer;
855 fw_size -= xfer;
856 offset += xfer;
857 }
858
859 err = memblaze_fw_commit(hdl, selectNo);
860
861 if (err == 0x10B || err == 0x20B) {
862 err = 0;
863 fprintf(stderrstderr, "Update successful! Please power cycle for changes to take effect\n");
864 }
865
866out_close:
867 close(fw_fd);
868out:
869 return err;
870}
871
872static void ioLatencyHistogramOutput(FILE *fd, int index, int start, int end, char *unit0,
873 char *unit1, unsigned int *pHistogram, int print)
874{
875 int len;
876 char string[64], subString0[12], subString1[12];
877
878 snprintf(subString0, sizeof(subString0), "%d%s", start, unit0);
879 if (end
38.1
'end' is not equal to 2147483647
!= 0x7FFFFFFF)
39
Taking true branch
880 snprintf(subString1, sizeof(subString1), "%d%s", end, unit1);
881 else
882 snprintf(subString1, sizeof(subString1), "%s", "+INF");
883 len = snprintf(string, sizeof(string), "%-11d %-11s %-11s %-11u\n",
884 index, subString0, subString1, pHistogram[index]);
885 fwrite(string, 1, len, fd);
40
Null pointer passed to 4th parameter expecting 'nonnull'
886 if (print)
887 printf("%s", string);
888}
889
890int io_latency_histogram(char *file, char *buf, int print, int logid)
891{
892 FILE *fdi = fopen(file, "w+");
10
Assuming pointer value is null
11
Assuming that 'fopen' fails
12
'fdi' initialized here
893 int i, index;
894 char unit[2][3];
895 unsigned int *revision = (unsigned int *)buf;
896
897 if (logid
12.1
'logid' is equal to GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM
== GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM)
13
Taking true branch
898 fPRINT_PARAM1("Memblaze IO Read Command Latency Histogram\n")do { if (fdi) fprintf(fdi, "Memblaze IO Read Command Latency Histogram\n"
); if (print) printf("Memblaze IO Read Command Latency Histogram\n"
); } while (0)
;
14
Taking false branch
15
Taking true branch
16
Loop condition is false. Exiting loop
899 else if (logid == GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM)
900 fPRINT_PARAM1("Memblaze IO Write Command Latency Histogram\n")do { if (fdi) fprintf(fdi, "Memblaze IO Write Command Latency Histogram\n"
); if (print) printf("Memblaze IO Write Command Latency Histogram\n"
); } while (0)
;
901 fPRINT_PARAM2("Major Revision : %d\n", revision[1])do { if (fdi) fprintf(fdi, "Major Revision : %d\n", revision[
1]); if (print) printf("Major Revision : %d\n", revision[1]);
} while (0)
;
17
Taking false branch
18
Taking true branch
19
Loop condition is false. Exiting loop
902 fPRINT_PARAM2("Minor Revision : %d\n", revision[0])do { if (fdi) fprintf(fdi, "Minor Revision : %d\n", revision[
0]); if (print) printf("Minor Revision : %d\n", revision[0]);
} while (0)
;
20
Taking false branch
21
Taking true branch
22
Loop condition is false. Exiting loop
903 buf += 8;
904
905 if (revision[1] == 1 && revision[0] == 0) {
23
Assuming the condition is true
24
Assuming the condition is true
25
Taking true branch
906 fPRINT_PARAM1("--------------------------------------------------\n")do { if (fdi) fprintf(fdi, "--------------------------------------------------\n"
); if (print) printf("--------------------------------------------------\n"
); } while (0)
;
26
Taking false branch
27
Taking true branch
28
Loop condition is false. Exiting loop
907 fPRINT_PARAM1("Bucket Start End Value\n")do { if (fdi) fprintf(fdi, "Bucket Start End Value\n"
); if (print) printf("Bucket Start End Value\n"
); } while (0)
;
29
Taking false branch
30
Taking true branch
31
Loop condition is false. Exiting loop
908 fPRINT_PARAM1("--------------------------------------------------\n")do { if (fdi) fprintf(fdi, "--------------------------------------------------\n"
); if (print) printf("--------------------------------------------------\n"
); } while (0)
;
32
Taking false branch
33
Taking true branch
34
Loop condition is false. Exiting loop
909 index = 0;
910 strcpy(unit[0], "us");
911 strcpy(unit[1], "us");
912 for (i = 0; i < 32; i++, index++) {
35
Loop condition is true. Entering loop body
913 if (i
35.1
'i' is not equal to 31
== 31) {
36
Taking false branch
914 strcpy(unit[1], "ms");
915 ioLatencyHistogramOutput(fdi, index, i * 32, 1, unit[0], unit[1],
916 (unsigned int *)buf, print);
917 } else {
918 ioLatencyHistogramOutput(fdi, index, i * 32, (i + 1) * 32, unit[0],
37
Passing null pointer value via 1st parameter 'fd'
38
Calling 'ioLatencyHistogramOutput'
919 unit[1], (unsigned int *)buf, print);
920 }
921 }
922
923 strcpy(unit[0], "ms");
924 strcpy(unit[1], "ms");
925 for (i = 1; i < 32; i++, index++)
926 ioLatencyHistogramOutput(fdi, index, i, i + 1, unit[0], unit[1],
927 (unsigned int *)buf, print);
928
929 for (i = 1; i < 32; i++, index++) {
930 if (i == 31) {
931 strcpy(unit[1], "s");
932 ioLatencyHistogramOutput(fdi, index, i * 32, 1, unit[0], unit[1],
933 (unsigned int *)buf, print);
934 } else {
935 ioLatencyHistogramOutput(fdi, index, i * 32, (i + 1) * 32, unit[0],
936 unit[1], (unsigned int *)buf, print);
937 }
938 }
939
940 strcpy(unit[0], "s");
941 strcpy(unit[1], "s");
942 for (i = 1; i < 4; i++, index++)
943 ioLatencyHistogramOutput(fdi, index, i, i + 1, unit[0], unit[1],
944 (unsigned int *)buf, print);
945
946 ioLatencyHistogramOutput(fdi, index, i, 0x7FFFFFFF, unit[0], unit[1],
947 (unsigned int *)buf, print);
948 } else {
949 fPRINT_PARAM1("Unsupported io latency histogram revision\n")do { if (fdi) fprintf(fdi, "Unsupported io latency histogram revision\n"
); if (print) printf("Unsupported io latency histogram revision\n"
); } while (0)
;
950 }
951
952 if (fdi)
953 fclose(fdi);
954 return 1;
955}
956
957static int mb_lat_stats_log_print(int argc, char **argv, struct command *acmd, struct plugin *plugin)
958{
959 char stats[LOG_PAGE_SIZE(0x1000)];
960 char f1[] = FID_C1_LOG_FILENAME"log_c1.csv";
961 char f2[] = FID_C2_LOG_FILENAME"log_c2.csv";
962 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
963 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
964
965 int err;
966
967 const char *desc = "Get Latency Statistics log and show it.";
968 const char *write = "Get write statistics (read default)";
969
970 struct config {
971 bool_Bool write;
972 };
973 struct config cfg = {
974 .write = 0,
975 };
976
977 NVME_ARGS(opts,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, }, {"", 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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
978 OPT_FLAG("write", 'w', &cfg.write, write))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, }, {"", 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, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
979
980 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
981 if (err)
1
Assuming 'err' is 0
2
Taking false branch
982 return err;
983
984 err = nvme_get_log_simple(hdl, cfg.write ? 0xc2 : 0xc1, &stats, sizeof(stats));
3
Assuming field 'write' is false
4
'?' condition is false
985 if (!err)
5
Assuming 'err' is 0
6
Taking true branch
986 io_latency_histogram(cfg.write
6.1
Field 'write' is false
? f2 : f1, stats, DO_PRINT_FLAG(1),
7
'?' condition is false
9
Calling 'io_latency_histogram'
987 cfg.write
7.1
Field 'write' is false
? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM :
8
'?' condition is false
988 GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM);
989 else
990 nvme_show_status(err);
991
992 return err;
993}
994
995static int memblaze_clear_error_log(int argc, char **argv, struct command *acmd,
996 struct plugin *plugin)
997{
998 char *desc = "Clear Memblaze devices error log.";
999 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1000 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1001
1002 int err;
1003
1004 __u64 result;
1005
1006 struct config {
1007 __u32 feature_id;
1008 __u32 value;
1009 int save;
1010 };
1011
1012 struct config cfg = {
1013 .feature_id = 0xf7,
1014 .value = 0x534d0001,
1015 .save = 0,
1016 };
1017
1018 NVME_ARGS(opts)struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
1019
1020 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1021 if (err)
1022 return err;
1023
1024 err = nvme_set_features(hdl, 0, cfg.feature_id, cfg.save, cfg.value, 0, 0, 0,
1025 0, NULL((void*)0), 0, &result);
1026 if (err < 0)
1027 perror("set-feature");
1028 if (!err)
1029 printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
1030 mb_feature_to_string(cfg.feature_id), cfg.value);
1031 else if (err > 0)
1032 nvme_show_status(err);
1033
1034 return err;
1035}
1036
1037static int mb_set_lat_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1038{
1039 const char *desc = (
1040 "Enable/Disable Latency Statistics Tracking.\n"
1041 "No argument prints current status.");
1042 const char *enable_desc = "Enable LST";
1043 const char *disable_desc = "Disable LST";
1044 const __u32 nsid = 0;
1045 const __u8 fid = 0xe2;
1046 const __u8 sel = 0;
1047 const __u32 cdw11 = 0x0;
1048 const __u32 cdw12 = 0x0;
1049 const __u32 data_len = 32;
1050 const __u32 save = 0;
1051 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1052 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1053
1054 void *buf = NULL((void*)0);
1055 __u64 result;
1056 int err;
1057
1058 struct config {
1059 bool_Bool enable, disable;
1060 };
1061
1062 struct config cfg = {
1063 .enable = false0,
1064 .disable = false0,
1065 };
1066
1067 struct argconfig_commandline_options opts[] = {
1068 {"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument0, enable_desc},
1069 {"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument0, disable_desc},
1070 {NULL((void*)0)}
1071 };
1072
1073 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1074
1075 enum Option {
1076 None = -1,
1077 True = 1,
1078 False = 0,
1079 };
1080 enum Option option = None;
1081
1082 if (cfg.enable && cfg.disable)
1083 printf("Cannot enable and disable simultaneously.");
1084 else if (cfg.enable || cfg.disable)
1085 option = cfg.enable;
1086
1087 if (err)
1088 return err;
1089 switch (option) {
1090 case None:
1091 err = nvme_get_features(hdl, nsid, fid, sel, cdw11, 0, buf, data_len,
1092 &result);
1093 if (!err) {
1094 printf("Latency Statistics Tracking (FID 0x%X) is currently (%"PRIu64"l" "u"").\n",
1095 fid, (uint64_t)result);
1096 } else {
1097 printf("Could not read feature id 0xE2.\n");
1098 return err;
1099 }
1100 break;
1101 case True:
1102 case False:
1103 err = nvme_set_features(hdl, nsid, fid, save, option, cdw12, 0, 0,
1104 0, buf, data_len, &result);
1105 if (err > 0) {
1106 nvme_show_status(err);
1107 } else if (err < 0) {
1108 perror("Enable latency tracking");
1109 fprintf(stderrstderr, "Command failed while parsing.\n");
1110 } else {
1111 printf("Successfully set enable bit for FID (0x%X) to %i.\n", 0xe2, option);
1112 }
1113 break;
1114 default:
1115 printf("%d not supported.\n", option);
1116 err = EINVAL22;
1117 }
1118 return err;
1119}
1120
1121// Global definitions
1122
1123static inline int K2C(int k) // KELVINS_2_CELSIUS
1124{
1125 return (k - 273);
1126};
1127
1128// Global ID definitions
1129
1130enum {
1131 // feature ids
1132 FID_LATENCY_FEATURE = 0xd0,
1133
1134 // log ids
1135 LID_SMART_LOG_ADD = 0xca,
1136 LID_LATENCY_STATISTICS = 0xd0,
1137 LID_HIGH_LATENCY_LOG = 0xd1,
1138 LID_PERFORMANCE_STATISTICS = 0xd2,
1139};
1140
1141// smart-log-add
1142
1143struct smart_log_add_item {
1144 uint32_t index;
1145 char *attr;
1146};
1147
1148struct __packed__attribute__((__packed__)) raw_array {
1149 __le16 r0;
1150 __le16 r2;
1151 __le16 r4;
1152};
1153
1154struct __packed__attribute__((__packed__)) raw_array1 {
1155 __le32 r0;
1156 __le16 r4;
1157};
1158
1159struct __packed__attribute__((__packed__)) smart_log_add_item_12 {
1160 uint8_t id;
1161 uint8_t rsvd1[2];
1162 uint8_t norm;
1163 uint8_t rsvd11;
1164 union {
1165 struct raw_array ra;
1166 struct raw_array1 ra1;
1167 uint8_t raw[6];
1168 };
1169 uint8_t rsvd2;
1170};
1171
1172struct __packed__attribute__((__packed__)) smart_log_add_item_10 {
1173 uint8_t id;
1174 uint8_t norm;
1175 union {
1176 struct raw_array ra;
1177 struct raw_array1 ra1;
1178 uint8_t raw[6];
1179 };
1180 uint8_t rsvd8[2];
1181};
1182
1183struct __packed__attribute__((__packed__)) smart_log_add {
1184 union {
1185 union {
1186 struct __packed__attribute__((__packed__)) smart_log_add_v0 {
1187 struct smart_log_add_item_12 program_fail_count;
1188 struct smart_log_add_item_12 erase_fail_count;
1189 struct smart_log_add_item_12 wear_leveling_count;
1190 struct smart_log_add_item_12 end_to_end_error_count;
1191 struct smart_log_add_item_12 crc_error_count;
1192 struct smart_log_add_item_12 timed_workload_media_wear;
1193 struct smart_log_add_item_12 timed_workload_host_reads;
1194 struct smart_log_add_item_12 timed_workload_timer;
1195 struct smart_log_add_item_12 thermal_throttle_status;
1196 struct smart_log_add_item_12 retry_buffer_overflow_counter;
1197 struct smart_log_add_item_12 pll_lock_loss_count;
1198 struct smart_log_add_item_12 nand_bytes_written;
1199 struct smart_log_add_item_12 host_bytes_written;
1200 struct smart_log_add_item_12 system_area_life_remaining;
1201 struct smart_log_add_item_12 nand_bytes_read;
1202 struct smart_log_add_item_12 temperature;
1203 struct smart_log_add_item_12 power_consumption;
1204 struct smart_log_add_item_12 power_on_temperature;
1205 struct smart_log_add_item_12 power_loss_protection;
1206 struct smart_log_add_item_12 read_fail_count;
1207 struct smart_log_add_item_12 thermal_throttle_time;
1208 struct smart_log_add_item_12 flash_error_media_count;
1209 } v0;
1210
1211 struct smart_log_add_item_12 v0_raw[22];
1212 };
1213
1214 union {
1215 struct __packed__attribute__((__packed__)) smart_log_add_v2 {
1216 struct smart_log_add_item_12 program_fail_count;
1217 struct smart_log_add_item_12 erase_fail_count;
1218 struct smart_log_add_item_12 wear_leveling_count;
1219 struct smart_log_add_item_12 end_to_end_error_count;
1220 struct smart_log_add_item_12 crc_error_count;
1221 struct smart_log_add_item_12 timed_workload_media_wear;
1222 struct smart_log_add_item_12 timed_workload_host_reads;
1223 struct smart_log_add_item_12 timed_workload_timer;
1224 struct smart_log_add_item_12 thermal_throttle_status;
1225 struct smart_log_add_item_12 lifetime_write_amplification;
1226 struct smart_log_add_item_12 pll_lock_loss_count;
1227 struct smart_log_add_item_12 nand_bytes_written;
1228 struct smart_log_add_item_12 host_bytes_written;
1229 struct smart_log_add_item_12 system_area_life_remaining;
1230 struct smart_log_add_item_12 firmware_update_count;
1231 struct smart_log_add_item_12 dram_cecc_count;
1232 struct smart_log_add_item_12 dram_uecc_count;
1233 struct smart_log_add_item_12 xor_pass_count;
1234 struct smart_log_add_item_12 xor_fail_count;
1235 struct smart_log_add_item_12 xor_invoked_count;
1236 struct smart_log_add_item_12 inflight_read_io_cmd;
1237 struct smart_log_add_item_12 inflight_write_io_cmd;
1238 struct smart_log_add_item_12 nand_bytes_read;
1239 struct smart_log_add_item_12 temp_since_born;
1240 struct smart_log_add_item_12 power_consumption;
1241 struct smart_log_add_item_12 temp_since_bootup;
1242 struct smart_log_add_item_12 thermal_throttle_time;
1243 struct smart_log_add_item_12 capacitor_capacitance;
1244 struct smart_log_add_item_12 free_xblock_status;
1245 } v2;
1246
1247 struct smart_log_add_item_12 v2_raw[29];
1248 };
1249
1250 union {
1251 struct __packed__attribute__((__packed__)) smart_log_add_v3 {
1252 struct smart_log_add_item_10 program_fail_count;
1253 struct smart_log_add_item_10 erase_fail_count;
1254 struct smart_log_add_item_10 wear_leveling_count;
1255 struct smart_log_add_item_10 ext_e2e_err_count;
1256 struct smart_log_add_item_10 crc_err_count;
1257 struct smart_log_add_item_10 nand_bytes_written;
1258 struct smart_log_add_item_10 host_bytes_written;
1259 struct smart_log_add_item_10 reallocated_sector_count;
1260 struct smart_log_add_item_10 uncorrectable_sector_count;
1261 struct smart_log_add_item_10 nand_uecc_detection;
1262 struct smart_log_add_item_10 nand_xor_correction;
1263 struct smart_log_add_item_10 rsvd11;
1264 struct smart_log_add_item_10 gc_count;
1265 struct smart_log_add_item_10 dram_uecc_detection_count;
1266 struct smart_log_add_item_10 sram_uecc_detection_count;
1267 struct smart_log_add_item_10 internal_raid_recovery_fail_count;
1268 struct smart_log_add_item_10 inflight_cmds;
1269 struct smart_log_add_item_10 internal_e2e_err_count;
1270 struct smart_log_add_item_10 rsvd18;
1271 struct smart_log_add_item_10 die_fail_count;
1272 struct smart_log_add_item_10 wear_leveling_execution_count;
1273 struct smart_log_add_item_10 read_disturb_count;
1274 struct smart_log_add_item_10 data_retention_count;
1275 struct smart_log_add_item_10 capacitor_health;
1276 struct smart_log_add_item_10 dram_cecc_count;
1277 struct smart_log_add_item_10 dram_cecc_address;
1278 struct smart_log_add_item_10 sram_cecc_count;
1279 struct smart_log_add_item_10 sram_cecc_address;
1280 struct smart_log_add_item_10 write_throttle_status;
1281 } v3;
1282
1283 struct smart_log_add_item_10 v3_raw[29];
1284 };
1285
1286 uint8_t raw[512];
1287 };
1288};
1289
1290static void smart_log_add_v0_print(struct smart_log_add_item_12 *item, int item_count)
1291{
1292 static const struct smart_log_add_item items[0xff] = {
1293 [0xab] = {0, "program_fail_count" },
1294 [0xac] = {1, "erase_fail_count" },
1295 [0xad] = {2, "wear_leveling_count" },
1296 [0xb8] = {3, "end_to_end_error_count" },
1297 [0xc7] = {4, "crc_error_count" },
1298 [0xe2] = {5, "timed_workload_media_wear" },
1299 [0xe3] = {6, "timed_workload_host_reads" },
1300 [0xe4] = {7, "timed_workload_timer" },
1301 [0xea] = {8, "thermal_throttle_status" },
1302 [0xf0] = {9, "retry_buffer_overflow_counter"},
1303 [0xf3] = {10, "pll_lock_loss_count" },
1304 [0xf4] = {11, "nand_bytes_written" },
1305 [0xf5] = {12, "host_bytes_written" },
1306 [0xf6] = {13, "system_area_life_remaining" },
1307 [0xfa] = {14, "nand_bytes_read" },
1308 [0xe7] = {15, "temperature" },
1309 [0xe8] = {16, "power_consumption" },
1310 [0xaf] = {17, "power_on_temperature" },
1311 [0xec] = {18, "power_loss_protection" },
1312 [0xf2] = {19, "read_fail_count" },
1313 [0xeb] = {20, "thermal_throttle_time" },
1314 [0xed] = {21, "flash_error_media_count" },
1315 };
1316
1317 for (int i = 0; i < item_count; i++, item++) {
1318 if (item->id == 0)
1319 continue;
1320
1321 printf("%#-12" PRIx8"x" "%-36s%-12d", item->id, items[item->id].attr, item->norm);
1322 switch (item->id) {
1323 case 0xad:
1324 printf("min: %d, max: %d, avg: %d\n",
1325 le16_to_cpu(item->ra.r0),
1326 le16_to_cpu(item->ra.r2),
1327 le16_to_cpu(item->ra.r4));
1328 break;
1329 case 0xe7:
1330 printf("max: %d °C (%d K), min: %d °C (%d K), curr: %d °C (%d K)\n",
1331 K2C(le16_to_cpu(item->ra.r0)),
1332 le16_to_cpu(item->ra.r0),
1333 K2C(le16_to_cpu(item->ra.r2)),
1334 le16_to_cpu(item->ra.r2),
1335 K2C(le16_to_cpu(item->ra.r4)),
1336 le16_to_cpu(item->ra.r4));
1337 break;
1338 case 0xe8:
1339 printf("max: %d, min: %d, curr: %d\n",
1340 le16_to_cpu(item->ra.r0),
1341 le16_to_cpu(item->ra.r2),
1342 le16_to_cpu(item->ra.r4));
1343 break;
1344 case 0xaf:
1345 printf("max: %d °C (%d K), min: %d °C (%d K), curr: %d °C (%d K)\n",
1346 K2C(le16_to_cpu(item->ra.r0)),
1347 le16_to_cpu(item->ra.r0),
1348 K2C(le16_to_cpu(item->ra.r2)),
1349 le16_to_cpu(item->ra.r2),
1350 K2C(le16_to_cpu(item->ra.r4)),
1351 le16_to_cpu(item->ra.r4));
1352 break;
1353 default:
1354 printf("%" PRIu64"l" "u" "\n", int48_to_long(item->raw));
1355 break;
1356 }
1357 }
1358}
1359
1360static void smart_log_add_v2_print(struct smart_log_add_item_12 *item, int item_count)
1361{
1362 static const struct smart_log_add_item items[0xff] = {
1363 [0xab] = {0, "program_fail_count" },
1364 [0xac] = {1, "erase_fail_count" },
1365 [0xad] = {2, "wear_leveling_count" },
1366 [0xb8] = {3, "end_to_end_error_count" },
1367 [0xc7] = {4, "crc_error_count" },
1368 [0xe2] = {5, "timed_workload_media_wear" },
1369 [0xe3] = {6, "timed_workload_host_reads" },
1370 [0xe4] = {7, "timed_workload_timer" },
1371 [0xea] = {8, "thermal_throttle_status" },
1372 [0xf0] = {9, "lifetime_write_amplification"},
1373 [0xf3] = {10, "pll_lock_loss_count" },
1374 [0xf4] = {11, "nand_bytes_written" },
1375 [0xf5] = {12, "host_bytes_written" },
1376 [0xf6] = {13, "system_area_life_remaining" },
1377 [0xf9] = {14, "firmware_update_count" },
1378 [0xfa] = {15, "dram_cecc_count" },
1379 [0xfb] = {16, "dram_uecc_count" },
1380 [0xfc] = {17, "xor_pass_count" },
1381 [0xfd] = {18, "xor_fail_count" },
1382 [0xfe] = {19, "xor_invoked_count" },
1383 [0xe5] = {20, "inflight_read_io_cmd" },
1384 [0xe6] = {21, "inflight_write_io_cmd" },
1385 [0xf8] = {22, "nand_bytes_read" },
1386 [0xe7] = {23, "temp_since_born" },
1387 [0xe8] = {24, "power_consumption" },
1388 [0xaf] = {25, "temp_since_bootup" },
1389 [0xeb] = {26, "thermal_throttle_time" },
1390 [0xec] = {27, "capacitor_capacitance" },
1391 [0xed] = {28, "free_xblock_status" },
1392 };
1393
1394 for (int i = 0; i < item_count; i++, item++) {
1395 if (item->id == 0)
1396 continue;
1397
1398 printf("%#-12" PRIx8"x" "%-36s%-12d", item->id, items[item->id].attr, item->norm);
1399 switch (item->id) {
1400 case 0xad:
1401 printf("min: %d, max: %d, avg: %d\n",
1402 le16_to_cpu(item->ra.r0),
1403 le16_to_cpu(item->ra.r2),
1404 le16_to_cpu(item->ra.r4));
1405 break;
1406 case 0xe7:
1407 printf("max: %d °C (%d K), min: %d °C (%d K), curr: %d °C (%d K)\n",
1408 K2C(le16_to_cpu(item->ra.r0)),
1409 le16_to_cpu(item->ra.r0),
1410 K2C(le16_to_cpu(item->ra.r2)),
1411 le16_to_cpu(item->ra.r2),
1412 K2C(le16_to_cpu(item->ra.r4)),
1413 le16_to_cpu(item->ra.r4));
1414 break;
1415 case 0xe8:
1416 printf("max: %d, min: %d, curr: %d\n",
1417 le16_to_cpu(item->ra.r0),
1418 le16_to_cpu(item->ra.r2),
1419 le16_to_cpu(item->ra.r4));
1420 break;
1421 case 0xaf:
1422 printf("max: %d °C (%d K), min: %d °C (%d K), curr: %d °C (%d K)\n",
1423 K2C(le16_to_cpu(item->ra.r0)),
1424 le16_to_cpu(item->ra.r0),
1425 K2C(le16_to_cpu(item->ra.r2)),
1426 le16_to_cpu(item->ra.r2),
1427 K2C(le16_to_cpu(item->ra.r4)),
1428 le16_to_cpu(item->ra.r4));
1429 break;
1430 case 0xeb:
1431 printf("throttle status: %d, total throttling time: %d\n",
1432 item->raw[0],
1433 le32_to_cpu(*(uint32_t *)&item->raw[1]));
1434 break;
1435 case 0xec:
1436 printf("current: %d, norminal: %d, threshold: %d\n",
1437 le16_to_cpu(item->ra.r0),
1438 le16_to_cpu(item->ra.r2),
1439 le16_to_cpu(item->ra.r4));
1440 break;
1441 default:
1442 printf("%" PRIu64"l" "u" "\n", int48_to_long(item->raw));
1443 break;
1444 }
1445 }
1446}
1447
1448static void smart_log_add_v3_print(struct smart_log_add_item_10 *item, int item_count)
1449{
1450 static const struct smart_log_add_item items[0xff] = {
1451 [0xab] = {0, "program_fail_count" },
1452 [0xac] = {1, "erase_fail_count" },
1453 [0xad] = {2, "wear_leveling_count" },
1454 [0xdf] = {3, "ext_e2e_err_count" },
1455 [0xc7] = {4, "crc_err_count" },
1456 [0xf4] = {5, "nand_bytes_written" },
1457 [0xf5] = {6, "host_bytes_written" },
1458 [0xd0] = {7, "reallocated_sector_count" },
1459 [0xd1] = {8, "uncorrectable_sector_count" },
1460 [0xd2] = {9, "nand_uecc_detection" },
1461 [0xd3] = {10, "nand_xor_correction" },
1462 [0xd4] = {12, "gc_count" }, // 11 is reserved
1463 [0xd5] = {13, "dram_uecc_detection_count" },
1464 [0xd6] = {14, "sram_uecc_detection_count" },
1465 [0xd7] = {15, "internal_raid_recovery_fail_count"},
1466 [0xd8] = {16, "inflight_cmds" },
1467 [0xd9] = {17, "internal_e2e_err_count" },
1468 [0xda] = {19, "die_fail_count" }, // 18 is reserved
1469 [0xdb] = {20, "wear_leveling_execution_count" },
1470 [0xdc] = {21, "read_disturb_count" },
1471 [0xdd] = {22, "data_retention_count" },
1472 [0xde] = {23, "capacitor_health" },
1473 [0xf6] = {24, "dram_cecc_count" },
1474 [0xf7] = {25, "dram_cecc_address" },
1475 [0xf8] = {26, "sram_cecc_count" },
1476 [0xf9] = {27, "sram_cecc_address" },
1477 [0xfa] = {28, "write_throttle_status" },
1478 };
1479
1480 for (int i = 0; i < item_count; i++, item++) {
1481 if (item->id == 0)
1482 continue;
1483
1484 printf("%#-12" PRIx8"x" "%-36s%-12d", item->id, items[item->id].attr, item->norm);
1485 switch (item->id) {
1486 case 0xad:
1487 printf("min: %d, max: %d, avg: %d\n",
1488 le16_to_cpu(item->ra.r0),
1489 le16_to_cpu(item->ra.r2),
1490 le16_to_cpu(item->ra.r4));
1491 break;
1492 case 0xf6:
1493 case 0xf8:
1494 case 0xf9:
1495 printf("%d\n", le32_to_cpu(item->ra1.r0));
1496 break;
1497 case 0xfa:
1498 printf("curr: %d, total: %d\n",
1499 le16_to_cpu(item->ra.r0),
1500 le16_to_cpu(item->ra.r2));
1501 break;
1502 default:
1503 printf("%" PRIu64"l" "u" "\n", int48_to_long(item->raw));
1504 break;
1505 }
1506 }
1507}
1508
1509static void smart_log_add_print(struct smart_log_add *log, const char *devname)
1510{
1511 uint8_t version = log->raw[511];
1512
1513 printf("Version: %u\n", version);
1514 printf("\n");
1515 printf("Additional Smart Log for NVMe device: %s\n", devname);
1516 printf("\n");
1517
1518 printf("%-12s%-36s%-12s%s\n", "Id", "Key", "Normalized", "Raw");
1519
1520 switch (version) {
1521 case 0:
1522 return smart_log_add_v0_print(&log->v0_raw[0],
1523 sizeof(struct smart_log_add_v0) / sizeof(struct smart_log_add_item_12));
1524 case 2:
1525 return smart_log_add_v2_print(&log->v2_raw[0],
1526 sizeof(struct smart_log_add_v2) / sizeof(struct smart_log_add_item_12));
1527 case 3:
1528 return smart_log_add_v3_print(&log->v3_raw[0],
1529 sizeof(struct smart_log_add_v3) / sizeof(struct smart_log_add_item_10));
1530
1531 case 1:
1532 fprintf(stderrstderr, "Version %d: N/A\n", version);
1533 break;
1534 default:
1535 fprintf(stderrstderr, "Version %d: Not supported yet\n", version);
1536 break;
1537 }
1538}
1539
1540static int mb_get_smart_log_add(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1541{
1542 int err = 0;
1543
1544 // Get the configuration
1545
1546 struct config {
1547 bool_Bool raw_binary;
1548 };
1549
1550 struct config cfg = {0};
1551
1552 NVME_ARGS(opts,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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
1553 OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, "dump the whole log buffer in binary format"))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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
1554
1555 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1556 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1557
1558
1559 err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts);
1560 if (err)
1561 return err;
1562
1563 // Get log
1564
1565 struct smart_log_add log = {0};
1566
1567 err = nvme_get_log_simple(hdl, LID_SMART_LOG_ADD, &log, sizeof(struct smart_log_add));
1568 if (!err) {
1569 if (!cfg.raw_binary)
1570 smart_log_add_print(&log, libnvme_transport_handle_get_name(hdl));
1571 else
1572 d_raw((unsigned char *)&log, sizeof(struct smart_log_add));
1573 } else if (err > 0) {
1574 nvme_show_status(err);
1575 } else {
1576 nvme_show_error("%s: %s", acmd->name, libnvme_strerror(errno))nvme_show_message(1, "%s: %s", acmd->name, libnvme_strerror
((*__errno_location ())))
;
1577 }
1578
1579 return err;
1580}
1581
1582// performance-monitor
1583
1584struct latency_stats_bucket {
1585 char *start_threshold;
1586 char *end_threshold;
1587};
1588
1589struct __packed__attribute__((__packed__)) latency_stats {
1590 union {
1591 struct __packed__attribute__((__packed__)) latency_stats_v2_0 {
1592 uint32_t minor_version;
1593 uint32_t major_version;
1594 uint32_t bucket_read_data[32];
1595 uint32_t rsvd[32];
1596 uint32_t bucket_write_data[32];
1597 uint32_t rsvd1[32];
1598 uint32_t bucket_trim_data[32];
1599 uint32_t rsvd2[32];
1600 uint8_t rsvd3[248];
1601 } v2_0;
1602 uint8_t raw[1024];
1603 };
1604};
1605
1606struct __packed__attribute__((__packed__)) high_latency_log {
1607 union {
1608 struct __packed__attribute__((__packed__)) high_latency_log_v1 {
1609 uint32_t version;
1610 struct __packed__attribute__((__packed__)) high_latency_log_entry {
1611 uint64_t timestamp; // ms
1612 uint32_t latency;
1613 uint32_t qid;
1614 uint32_t opcode : 8;
1615 uint32_t fuse : 2;
1616 uint32_t psdt : 2;
1617 uint32_t cid : 16;
1618 uint32_t rsvd : 4;
1619 uint32_t nsid;
1620 uint64_t slba;
1621 uint32_t nlb : 16;
1622 uint32_t dtype : 8;
1623 uint32_t pinfo : 4;
1624 uint32_t fua : 1;
1625 uint32_t lr : 1;
1626 uint32_t rsvd1 : 2;
1627 uint8_t rsvd2[28];
1628 } entries[1024];
1629 } v1;
1630 uint8_t raw[4 + 1024 * 64];
1631 };
1632};
1633
1634struct __packed__attribute__((__packed__)) performance_stats {
1635 union {
1636 struct __packed__attribute__((__packed__)) performance_stats_v1 {
1637 uint8_t version;
1638 uint8_t rsvd[3];
1639 struct __packed__attribute__((__packed__)) performance_stats_timestamp {
1640 uint8_t timestamp[6];
1641 struct __packed__attribute__((__packed__)) performance_stats_entry {
1642 uint16_t read_iops; // K IOPS
1643 uint16_t read_bandwidth; // MiB
1644 uint32_t read_latency; // us
1645 uint32_t read_latency_max; // us
1646 uint16_t write_iops; // K IOPS
1647 uint16_t write_bandwidth; // MiB
1648 uint32_t write_latency; // us
1649 uint32_t write_latency_max; // us
1650 } entries[3600];
1651 } timestamps[24];
1652 } v1;
1653 struct __packed__attribute__((__packed__)) performance_stats_v2 {
1654 uint8_t version;
1655 uint8_t rsvd[3];
1656 struct __packed__attribute__((__packed__)) performance_stats_timestamp_v2 {
1657 uint8_t timestamp[6];
1658 struct __packed__attribute__((__packed__)) performance_stats_entry_v2 {
1659 uint16_t read_iops;
1660 uint16_t read_bandwidth;
1661 uint16_t read_latency_avg;
1662 uint16_t read_latency_max;
1663 uint8_t scale_of_read_iops;
1664 uint8_t scale_of_read_bandwidth;
1665 uint8_t scale_of_read_latency_avg;
1666 uint8_t scale_of_read_latency_max;
1667 uint16_t write_iops;
1668 uint16_t write_bandwidth;
1669 uint16_t write_latency_avg;
1670 uint16_t write_latency_max;
1671 uint8_t scale_of_write_iops;
1672 uint8_t scale_of_write_bandwidth;
1673 uint8_t scale_of_write_latency_avg;
1674 uint8_t scale_of_write_latency_max;
1675 } entries[3600];
1676 } timestamps[24];
1677 } v2;
1678 uint8_t raw[4 + 24 * (6 + 3600 * 24)];
1679 };
1680};
1681
1682static int mb_set_latency_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1683{
1684 int err = 0;
1685
1686 // Get the configuration
1687
1688 struct config {
1689 uint32_t perf_monitor;
1690 uint32_t cmd_mask;
1691 uint32_t read_threshold;
1692 uint32_t write_threshold;
1693 uint32_t de_allocate_trim_threshold;
1694 };
1695
1696 struct config cfg = {0};
1697
1698 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1699 OPT_UINT("sel-perf-log", 's', &cfg.perf_monitor,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1700 "Select features to turn on, default: Disable\n"struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1701 " bit 0: latency statistics\n"struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1702 " bit 1: high latency log\n"struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1703 " bit 2: Performance stat"),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1704 OPT_UINT("set-commands-mask", 'm', &cfg.cmd_mask,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1705 "Set Enable, default: Disable\n"struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1706 " bit 0: Read commands\n"struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1707 " bit 1: high Write commands\n"struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1708 " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1709 OPT_UINT("set-read-threshold", 'r', &cfg.read_threshold,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1710 "set read high latency log threshold, it's a 0-based value and unit is 10ms"),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1711 OPT_UINT("set-write-threshold", 'w', &cfg.write_threshold,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1712 "set write high latency log threshold, it's a 0-based value and unit is 10ms"),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1713 OPT_UINT("set-trim-threshold", 't', &cfg.de_allocate_trim_threshold,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
1714 "set trim high latency log threshold, it's a 0-based value and unit is 10ms"))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"sel-perf-log", 's', "NUM", CFG_POSITIVE, &cfg.perf_monitor
, 1, "Select features to turn on, default: Disable\n" " bit 0: latency statistics\n"
" bit 1: high latency log\n" " bit 2: Performance stat"
, 0, }, {"set-commands-mask", 'm', "NUM", CFG_POSITIVE, &
cfg.cmd_mask, 1, "Set Enable, default: Disable\n" " bit 0: Read commands\n"
" bit 1: high Write commands\n" " bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"
, 0, }, {"set-read-threshold", 'r', "NUM", CFG_POSITIVE, &
cfg.read_threshold, 1, "set read high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-write-threshold", 'w', "NUM", CFG_POSITIVE, &
cfg.write_threshold, 1, "set write high latency log threshold, it's a 0-based value and unit is 10ms"
, 0, }, {"set-trim-threshold", 't', "NUM", CFG_POSITIVE, &
cfg.de_allocate_trim_threshold, 1, "set trim high latency log threshold, it's a 0-based value and unit is 10ms"
, 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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
1715
1716 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1717 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1718
1719
1720 err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts);
1721 if (err)
1722 return err;
1723
1724
1725 // Set feature
1726
1727 __u64 result = 0;
1728
1729 err = nvme_set_features(hdl, 0, FID_LATENCY_FEATURE, 0, 0 | cfg.perf_monitor,
1730 0 | cfg.cmd_mask,
1731 0 | (cfg.read_threshold & 0xff) |
1732 ((cfg.write_threshold & 0xff) << 8) |
1733 ((cfg.de_allocate_trim_threshold & 0xff) << 16),
1734 0, 0, NULL((void*)0), 0, &result);
1735 if (!err)
1736 printf("%s have done successfully. result = %#" PRIx64"l" "x" ".\n",
1737 acmd->name, (uint64_t)result);
1738 else if (err > 0)
1739 nvme_show_status(err);
1740 else
1741 nvme_show_error("%s: %s", acmd->name, libnvme_strerror(errno))nvme_show_message(1, "%s: %s", acmd->name, libnvme_strerror
((*__errno_location ())))
;
1742
1743 return err;
1744}
1745
1746static int mb_get_latency_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1747{
1748 __u64 res = 0;
1749 int err;
1750
1751 // Get the configuration
1752
1753 NVME_ARGS(opts)struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)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, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 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}, { ((void*)0) } }
;
1754
1755 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1756 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1757
1758 err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts);
1759 if (err)
1760 return err;
1761
1762 // Get feature
1763
1764 err = nvme_get_features_simple(hdl, FID_LATENCY_FEATURE,
1765 NVME_GET_FEATURES_SEL_CURRENT, &res);
1766 if (!err) {
1767 uint32_t result = res;
1768 printf("%s have done successfully. result = %#" PRIx32"x" ".\n", acmd->name, result);
1769
1770 printf("latency statistics enable status = %d\n", (result & (0x01 << 0)) >> 0);
1771 printf("high latency enable status = %d\n", (result & (0x01 << 1)) >> 1);
1772 printf("performance stat enable status = %d\n", (result & (0x01 << 2)) >> 2);
1773
1774 printf("Monitor Read command = %d\n", (result & (0x01 << 4)) >> 4);
1775 printf("Monitor Write command = %d\n", (result & (0x01 << 5)) >> 5);
1776 printf("Monitor Trim command = %d\n", (result & (0x01 << 6)) >> 6);
1777
1778 printf("Threshold for Read = %dms\n", (((result & (0xff << 8)) >> 8) + 1) * 10);
1779 printf("Threshold for Write = %dms\n", (((result & (0xff << 16)) >> 16) + 1) * 10);
1780 printf("Threshold for Trim = %dms\n", (((result & (0xff << 24)) >> 24) + 1) * 10);
1781 } else if (err > 0) {
1782 nvme_show_status(err);
1783 } else {
1784 nvme_show_error("%s: %s", acmd->name, libnvme_strerror(errno))nvme_show_message(1, "%s: %s", acmd->name, libnvme_strerror
((*__errno_location ())))
;
1785 }
1786
1787 return err;
1788}
1789
1790static void latency_stats_v2_0_print(struct latency_stats *log, int size)
1791{
1792 static const struct latency_stats_bucket buckets[0xff] = {
1793 [1] = {"0us", "50us" },
1794 [2] = {"50us", "100us"},
1795 [3] = {"100us", "150us"},
1796 [4] = {"150us", "200us"},
1797 [5] = {"200us", "300us"},
1798 [6] = {"300us", "400us"},
1799 [7] = {"400us", "500us"},
1800 [8] = {"500us", "600us"},
1801 [9] = {"600us", "700us"},
1802 [10] = {"700us", "800us"},
1803 [11] = {"800us", "900us"},
1804 [12] = {"900us", "1ms" },
1805 [13] = {"1ms", "5ms" },
1806 [14] = {"5ms", "10ms" },
1807 [15] = {"10ms", "20ms" },
1808 [16] = {"20ms", "50ms" },
1809 [17] = {"50ms", "100ms"},
1810 [18] = {"100ms", "200ms"},
1811 [19] = {"200ms", "300ms"},
1812 [20] = {"300ms", "400ms"},
1813 [21] = {"400ms", "500ms"},
1814 [22] = {"500ms", "600ms"},
1815 [23] = {"600ms", "700ms"},
1816 [24] = {"700ms", "800ms"},
1817 [25] = {"800ms", "900ms"},
1818 [26] = {"900ms", "1s" },
1819 [27] = {"1s", "2s" },
1820 [28] = {"2s", "3s" },
1821 [29] = {"3s", "4s" },
1822 [30] = {"4s", "5s" },
1823 [31] = {"5s", "8s" },
1824 [32] = {"8s", "INF" },
1825 };
1826
1827 printf("Bucket 1-32 IO Read Command Data\n");
1828 printf("-------------------------------------------\n");
1829 printf("%-12s%-12s%-12s%-12s\n", "Bucket", "Start(>=)", "End(<)", "Value");
1830 int bucket_count = sizeof(log->v2_0.bucket_read_data) / sizeof(uint32_t);
1831
1832 for (int i = 0; i < bucket_count; i++) {
1833 printf("%-12u%-12s%-12s%-12u\n", i + 1, buckets[i + 1].start_threshold,
1834 buckets[i + 1].end_threshold, log->v2_0.bucket_read_data[i]);
1835 }
1836 printf("\n");
1837
1838 printf("Bucket 1-32 IO Write Command Data\n");
1839 printf("-------------------------------------------\n");
1840 printf("%-12s%-12s%-12s%-12s\n", "Bucket", "Start(>=)", "End(<)", "Value");
1841 bucket_count = sizeof(log->v2_0.bucket_write_data) / sizeof(uint32_t);
1842
1843 for (int i = 0; i < bucket_count; i++) {
1844 printf("%-12u%-12s%-12s%-12u\n", i + 1, buckets[i + 1].start_threshold,
1845 buckets[i + 1].end_threshold, log->v2_0.bucket_write_data[i]);
1846 }
1847 printf("\n");
1848
1849 printf("Bucket 1-32 IO Trim Command Data\n");
1850 printf("-------------------------------------------\n");
1851 printf("%-12s%-12s%-12s%-12s\n", "Bucket", "Start(>=)", "End(<)", "Value");
1852 bucket_count = sizeof(log->v2_0.bucket_trim_data) / sizeof(uint32_t);
1853
1854 for (int i = 0; i < bucket_count; i++) {
1855 printf("%-12u%-12s%-12s%-12u\n", i + 1, buckets[i + 1].start_threshold,
1856 buckets[i + 1].end_threshold, log->v2_0.bucket_trim_data[i]);
1857 }
1858 printf("\n");
1859}
1860
1861static void latency_stats_print(struct latency_stats *log, const char *devname)
1862{
1863 uint32_t minor_version = *(uint32_t *)&log->raw[0];
1864 uint32_t major_version = *(uint32_t *)&log->raw[4];
1865
1866 printf("Major Version: %u, Minor Version: %u\n", major_version, minor_version);
1867 printf("\n");
1868 printf("Latency Statistics Log for NVMe device: %s\n", devname);
1869 printf("\n");
1870
1871 switch (major_version) {
1872 case 2:
1873 switch (minor_version) {
1874 case 0:
1875 latency_stats_v2_0_print(log, sizeof(struct latency_stats));
1876 break;
1877 default:
1878 fprintf(stderrstderr, "Major Version %u, Minor Version %u: Not supported yet\n",
1879 major_version, minor_version);
1880 break;
1881 }
1882 break;
1883
1884 default:
1885 fprintf(stderrstderr, "Major Version %u: Not supported yet\n", major_version);
1886 break;
1887 }
1888}
1889
1890static int mb_get_latency_stats(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1891{
1892 // Get the configuration
1893
1894 struct config {
1895 bool_Bool raw_binary;
1896 };
1897
1898 struct config cfg = {0};
1899
1900 NVME_ARGS(opts,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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
1901 OPT_FLAG("raw-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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
1902 'b',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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
1903 &cfg.raw_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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
1904 "dump the whole log buffer in binary format"))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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
1905
1906 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1907 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1908
1909 int err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts);
1910
1911 if (err)
1912 return err;
1913
1914 // Get log
1915
1916 struct latency_stats log = {0};
1917
1918 err = nvme_get_log_simple(hdl, LID_LATENCY_STATISTICS, &log, sizeof(struct latency_stats));
1919 if (!err) {
1920 if (!cfg.raw_binary)
1921 latency_stats_print(&log, libnvme_transport_handle_get_name(hdl));
1922 else
1923 d_raw((unsigned char *)&log, sizeof(struct latency_stats));
1924 } else if (err > 0) {
1925 nvme_show_status(err);
1926 } else {
1927 nvme_show_error("%s: %s", acmd->name, libnvme_strerror(errno))nvme_show_message(1, "%s: %s", acmd->name, libnvme_strerror
((*__errno_location ())))
;
1928 }
1929
1930 return err;
1931}
1932
1933static void high_latency_log_v1_print(struct high_latency_log *log, int size)
1934{
1935 printf("%-24s%-12s%-12s%-6s%-6s%-6s%-6s%-12s%-24s%-6s%-6s%-6s%-6s%-6s\n",
1936 "Timestamp", "Latency(us)", "QID", "OpC", "Fuse", "PSDT", "CID", "NSID", "SLBA",
1937 "NLB", "DType", "PInfo", "FUA", "LR");
1938
1939 for (int i = 0; i < 1024; i++) {
1940 if (log->v1.entries[i].timestamp == 0)
1941 break;
1942
1943 // Get the timestamp
1944
1945 time_t timestamp_ms = log->v1.entries[i].timestamp;
1946 time_t timestamp_s = timestamp_ms / 1000;
1947 int time_ms = timestamp_ms % 1000;
1948 char str_time_s[20] = {0};
1949 char str_time_ms[32] = {0};
1950
1951 strftime(str_time_s, sizeof(str_time_s), "%Y-%m-%d %H:%M:%S",
1952 localtime(&timestamp_s));
1953 snprintf(str_time_ms, sizeof(str_time_ms), "%s.%03d", str_time_s, time_ms);
1954 printf("%-24s", str_time_ms);
1955
1956 //
1957 printf("%-12" PRIu32"u", log->v1.entries[i].latency);
1958 printf("%-12" PRIu32"u", log->v1.entries[i].qid);
1959 printf("%#-6" PRIx32"x", log->v1.entries[i].opcode);
1960 printf("%-6" PRIu32"u", log->v1.entries[i].fuse);
1961 printf("%-6" PRIu32"u", log->v1.entries[i].psdt);
1962 printf("%-6" PRIu32"u", log->v1.entries[i].cid);
1963 printf("%-12" PRIu32"u", log->v1.entries[i].nsid);
1964 printf("%-24" PRIu64"l" "u", log->v1.entries[i].slba);
1965 printf("%-6" PRIu32"u", log->v1.entries[i].nlb);
1966 printf("%-6" PRIu32"u", log->v1.entries[i].dtype);
1967 printf("%-6" PRIu32"u", log->v1.entries[i].pinfo);
1968 printf("%-6" PRIu32"u", log->v1.entries[i].fua);
1969 printf("%-6" PRIu32"u", log->v1.entries[i].lr);
1970 printf("\n");
1971 }
1972}
1973
1974static void high_latency_log_print(struct high_latency_log *log, const char *devname)
1975{
1976 uint32_t version = *(uint32_t *)&log->raw[0];
1977
1978 printf("Version: %u\n", version);
1979 printf("\n");
1980 printf("High Latency Log for NVMe device: %s\n", devname);
1981 printf("\n");
1982
1983 switch (version) {
1984 case 1:
1985 high_latency_log_v1_print(log, sizeof(struct high_latency_log));
1986 break;
1987
1988 default:
1989 fprintf(stderrstderr, "Version %u: Not supported yet\n", version);
1990 break;
1991 }
1992}
1993
1994static int mb_get_high_latency_log(int argc, char **argv, struct command *acmd,
1995 struct plugin *plugin)
1996{
1997 // Get the configuration
1998
1999 struct config {
2000 bool_Bool raw_binary;
2001 };
2002
2003 struct config cfg = {0};
2004
2005 NVME_ARGS(opts,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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2006 OPT_FLAG("raw-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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2007 'b',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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2008 &cfg.raw_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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2009 "dump the whole log buffer in binary format"))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, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
2010
2011 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
2012 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
2013
2014 int err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts);
2015 if (err)
2016 return err;
2017
2018 // Get log
2019
2020 struct high_latency_log log = {0};
2021
2022 err = nvme_get_log_simple(hdl, LID_HIGH_LATENCY_LOG,
2023 &log, sizeof(struct high_latency_log));
2024 if (!err) {
2025 if (!cfg.raw_binary)
2026 high_latency_log_print(&log, libnvme_transport_handle_get_name(hdl));
2027 else
2028 d_raw((unsigned char *)&log, sizeof(struct high_latency_log));
2029 } else if (err > 0) {
2030 nvme_show_status(err);
2031 } else {
2032 nvme_show_error("%s: %s", acmd->name, libnvme_strerror(errno))nvme_show_message(1, "%s: %s", acmd->name, libnvme_strerror
((*__errno_location ())))
;
2033 }
2034
2035 return err;
2036}
2037
2038static void performance_stats_v1_print(struct performance_stats *log, int duration)
2039{
2040 for (int i = 0; i < duration; i++) {
2041 // Print timestamp
2042
2043 time_t timestamp_ms = int48_to_long(log->v1.timestamps[i].timestamp);
2044 time_t timestamp_s = timestamp_ms / 1000;
2045 int time_ms = timestamp_ms % 1000;
2046 char time_s[32] = {0};
2047
2048 strftime(time_s, sizeof(time_s), "%Y-%m-%d %H:%M:%S", localtime(&timestamp_s));
2049 printf("Timestamp %2d: %s.%03d\n", i + 1, time_s, time_ms);
2050
2051 // Print entry title
2052
2053 printf("%-8s%-14s%-21s%-22s%-22s%-15s%-22s%-23s%-23s\n", "Entry", "Read-IOs(K)",
2054 "Read-Bandwidth(MiB)", "Avg-Read-Latency(us)", "Max-Read-Latency(us)",
2055 "Write-IOs(K)", "Write-Bandwidth(MiB)", "Avg-Write-Latency(us)",
2056 "Max-Write-Latency(us)");
2057
2058 // Print all entries content
2059
2060 struct performance_stats_entry entry = {0};
2061
2062 for (int j = 0; j < 3600; j++) {
2063 entry.read_iops =
2064 log->v1.timestamps[i].entries[j].read_iops;
2065 entry.read_bandwidth =
2066 log->v1.timestamps[i].entries[j].read_bandwidth;
2067 entry.read_latency =
2068 log->v1.timestamps[i].entries[j].read_latency;
2069 entry.read_latency_max =
2070 log->v1.timestamps[i].entries[j].read_latency_max;
2071 entry.write_iops =
2072 log->v1.timestamps[i].entries[j].write_iops;
2073 entry.write_bandwidth =
2074 log->v1.timestamps[i].entries[j].write_bandwidth;
2075 entry.write_latency =
2076 log->v1.timestamps[i].entries[j].write_latency;
2077 entry.write_latency_max =
2078 log->v1.timestamps[i].entries[j].write_latency_max;
2079
2080 if (entry.read_iops == 0 && entry.write_iops == 0)
2081 continue;
2082
2083 printf("%-8u%-14u%-21u%-22u%-22u%-15u%-22u%-23u%-23u\n",
2084 j + 1,
2085 entry.read_iops,
2086 entry.read_bandwidth,
2087 entry.read_iops == 0 ?
2088 0 : entry.read_latency / (1000 * entry.read_iops),
2089 entry.read_latency_max,
2090 entry.write_iops,
2091 entry.write_bandwidth,
2092 entry.write_iops == 0 ?
2093 0 : entry.write_latency / (1000 * entry.write_iops),
2094 entry.write_latency_max);
2095 usleep(100);
2096 }
2097 printf("\n");
2098 }
2099}
2100
2101static void performance_stats_v2_print(struct performance_stats *log, int duration)
2102{
2103 for (int i = 0; i < duration; i++) {
2104 // Print timestamp
2105
2106 time_t timestamp_ms = int48_to_long(log->v2.timestamps[i].timestamp);
2107 time_t timestamp_s = timestamp_ms / 1000;
2108 int time_ms = timestamp_ms % 1000;
2109 char time_s[32] = {0};
2110
2111 strftime(time_s, sizeof(time_s), "%Y-%m-%d %H:%M:%S", localtime(&timestamp_s));
2112 printf("Timestamp %2d: %s.%03d\n", i + 1, time_s, time_ms);
2113
2114 // Print entry title
2115
2116 printf("%-8s%-23s%-23s%-23s%-23s%-23s%-23s%-23s%-23s\n",
2117 "Entry",
2118 "Read-IOs(IOPS)", "Read-Bandwidth(KiB)",
2119 "Avg-Read-Latency(us)", "Max-Read-Latency(us)",
2120 "Write-IOs(IOPS)", "Write-Bandwidth(KiB)",
2121 "Avg-Write-Latency(us)", "Max-Write-Latency(us)");
2122
2123 // Print all entries content
2124 for (int j = 0; j < 3600; j++) {
2125 uint32_t read_iops =
2126 log->v2.timestamps[i].entries[j].read_iops;
2127 uint32_t read_bandwidth =
2128 log->v2.timestamps[i].entries[j].read_bandwidth;
2129 uint32_t read_latency_avg =
2130 log->v2.timestamps[i].entries[j].read_latency_avg;
2131 uint32_t read_latency_max =
2132 log->v2.timestamps[i].entries[j].read_latency_max;
2133 uint32_t scale_of_read_iops =
2134 log->v2.timestamps[i].entries[j].scale_of_read_iops;
2135 uint32_t scale_of_read_bandwidth =
2136 log->v2.timestamps[i].entries[j].scale_of_read_bandwidth;
2137 uint32_t scale_of_read_latency_avg =
2138 log->v2.timestamps[i].entries[j].scale_of_read_latency_avg;
2139 uint32_t scale_of_read_latency_max =
2140 log->v2.timestamps[i].entries[j].scale_of_read_latency_max;
2141
2142 uint32_t write_iops =
2143 log->v2.timestamps[i].entries[j].write_iops;
2144 uint32_t write_bandwidth =
2145 log->v2.timestamps[i].entries[j].write_bandwidth;
2146 uint32_t write_latency_avg =
2147 log->v2.timestamps[i].entries[j].write_latency_avg;
2148 uint32_t write_latency_max =
2149 log->v2.timestamps[i].entries[j].write_latency_max;
2150 uint32_t scale_of_write_iops =
2151 log->v2.timestamps[i].entries[j].scale_of_write_iops;
2152 uint32_t scale_of_write_bandwidth =
2153 log->v2.timestamps[i].entries[j].scale_of_write_bandwidth;
2154 uint32_t scale_of_write_latency_avg =
2155 log->v2.timestamps[i].entries[j].scale_of_write_latency_avg;
2156 uint32_t scale_of_write_latency_max =
2157 log->v2.timestamps[i].entries[j].scale_of_write_latency_max;
2158
2159 if (read_iops == 0 && write_iops == 0)
2160 continue;
2161
2162 while (scale_of_read_iops < 4 && scale_of_read_iops) {
2163 read_iops *= 10;
2164 scale_of_read_iops--;
2165 }
2166 while (scale_of_read_bandwidth < 3 && scale_of_read_bandwidth) {
2167 read_bandwidth *= 1024;
2168 scale_of_read_bandwidth--;
2169 }
2170 while (scale_of_read_latency_avg < 3 && scale_of_read_latency_avg) {
2171 read_latency_avg *= 1000;
2172 scale_of_read_latency_avg--;
2173 }
2174 while (scale_of_read_latency_max < 3 && scale_of_read_latency_max) {
2175 read_latency_max *= 1000;
2176 scale_of_read_latency_max--;
2177 }
2178
2179 while (scale_of_write_iops < 4 && scale_of_write_iops) {
2180 write_iops *= 10;
2181 scale_of_write_iops--;
2182 }
2183 while (scale_of_write_bandwidth < 3 && scale_of_write_bandwidth) {
2184 write_bandwidth *= 1024;
2185 scale_of_write_bandwidth--;
2186 }
2187 while (scale_of_write_latency_avg < 3 && scale_of_write_latency_avg) {
2188 write_latency_avg *= 1000;
2189 scale_of_write_latency_avg--;
2190 }
2191 while (scale_of_write_latency_max < 3 && scale_of_write_latency_max) {
2192 write_latency_max *= 1000;
2193 scale_of_write_latency_max--;
2194 }
2195
2196 printf("%-8u%-23u%-23u%-23u%-23u%-23u%-23u%-23u%-23u\n",
2197 j + 1,
2198 read_iops,
2199 read_bandwidth,
2200 read_latency_avg,
2201 read_latency_max,
2202 write_iops,
2203 write_bandwidth,
2204 write_latency_avg,
2205 write_latency_max);
2206 usleep(100);
2207 }
2208 printf("\n");
2209 }
2210}
2211
2212static void performance_stats_print(struct performance_stats *log, const char *devname,
2213 int duration)
2214{
2215 uint8_t version = *(uint8_t *)&log->raw[0];
2216
2217 printf("Version: %u\n", version);
2218 printf("\n");
2219 printf("Performance Stat log for NVMe device: %s\n", devname);
2220 printf("\n");
2221
2222 switch (version) {
2223 case 1:
2224 performance_stats_v1_print(log, duration);
2225 break;
2226 case 2:
2227 performance_stats_v2_print(log, duration);
2228 break;
2229 default:
2230 fprintf(stderrstderr, "Version %u: Not supported yet\n", version);
2231 break;
2232 }
2233}
2234
2235static int mb_get_performance_stats(int argc, char **argv, struct command *acmd,
2236 struct plugin *plugin)
2237{
2238 // Get the configuration
2239
2240 struct config {
2241 int duration;
2242 bool_Bool raw_binary;
2243 };
2244
2245 struct config cfg = {.duration = 1, .raw_binary = false0};
2246
2247 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"duration", 'd', "NUM", CFG_POSITIVE, &cfg.duration
, 1, "[1-24] hours: duration of the log to be printed, default is 1 hour"
, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2248 OPT_UINT("duration",struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"duration", 'd', "NUM", CFG_POSITIVE, &cfg.duration
, 1, "[1-24] hours: duration of the log to be printed, default is 1 hour"
, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2249 'd',struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"duration", 'd', "NUM", CFG_POSITIVE, &cfg.duration
, 1, "[1-24] hours: duration of the log to be printed, default is 1 hour"
, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2250 &cfg.duration,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"duration", 'd', "NUM", CFG_POSITIVE, &cfg.duration
, 1, "[1-24] hours: duration of the log to be printed, default is 1 hour"
, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2251 "[1-24] hours: duration of the log to be printed, default is 1 hour"),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"duration", 'd', "NUM", CFG_POSITIVE, &cfg.duration
, 1, "[1-24] hours: duration of the log to be printed, default is 1 hour"
, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2252 OPT_FLAG("raw-binary",struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"duration", 'd', "NUM", CFG_POSITIVE, &cfg.duration
, 1, "[1-24] hours: duration of the log to be printed, default is 1 hour"
, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2253 'b',struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"duration", 'd', "NUM", CFG_POSITIVE, &cfg.duration
, 1, "[1-24] hours: duration of the log to be printed, default is 1 hour"
, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2254 &cfg.raw_binary,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"duration", 'd', "NUM", CFG_POSITIVE, &cfg.duration
, 1, "[1-24] hours: duration of the log to be printed, default is 1 hour"
, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
2255 "dump the whole log buffer in binary format"))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"duration", 'd', "NUM", CFG_POSITIVE, &cfg.duration
, 1, "[1-24] hours: duration of the log to be printed, default is 1 hour"
, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, "dump the whole log buffer in binary format", 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, }, {"output-format"
, 'o', "FMT", CFG_STRING, &nvme_args.output_format, 1, "Output format: normal|json|binary|tabular"
, 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}, { ((void*)0) } }
;
2256
2257 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
2258 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
2259
2260 int err = parse_and_open(&ctx, &hdl, argc, argv, acmd->help, opts);
2261
2262 if (err)
2263 return err;
2264
2265 // Check parameters
2266 if (cfg.duration < 1 || cfg.duration > 24) {
2267 fprintf(stderrstderr, "duration must be between 1 and 24.\n");
2268 exit(1);
2269 }
2270
2271 // Get log
2272
2273 struct performance_stats log = {0};
2274
2275 int log_size = 4 + cfg.duration * sizeof(struct performance_stats_timestamp);
2276 // Get one more timestamp if duration is odd number to avoid non-dw alignment issues
2277 int xfer_size = (cfg.duration % 2) > 0 ?
2278 (4 + (cfg.duration + 1) * sizeof(struct performance_stats_timestamp)) : log_size;
2279
2280 err = nvme_get_log_simple(hdl, LID_PERFORMANCE_STATISTICS, &log, xfer_size);
2281 if (!err) {
2282 if (!cfg.raw_binary)
2283 performance_stats_print(&log, libnvme_transport_handle_get_name(hdl), cfg.duration);
2284 else
2285 d_raw((unsigned char *)&log, log_size);
2286 } else if (err > 0) {
2287 nvme_show_status(err);
2288 } else {
2289 nvme_show_error("%s: %s", acmd->name, libnvme_strerror(errno))nvme_show_message(1, "%s: %s", acmd->name, libnvme_strerror
((*__errno_location ())))
;
2290 }
2291
2292 return err;
2293}