Bug Summary

File:.build-ci/../plugins/solidigm/solidigm-latency-tracking.c
Warning:line 162, column 32
The result of left shift is undefined because the right operand is negative

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 solidigm-latency-tracking.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/solidigm/solidigm-latency-tracking.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2022-2024 Solidigm.
4 *
5 * Author: leonardo.da.cunha@solidigm.com
6 */
7
8#include <errno(*__errno_location ()).h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
12#include <inttypes.h>
13
14#include <libnvme.h>
15
16#include "common.h"
17#include "nvme-cmds.h"
18#include "nvme-print.h"
19#include "nvme.h"
20#include "plugin.h"
21
22#include "solidigm-util.h"
23
24#define BUCKET_LIST_SIZE_4_0152 152
25#define BUCKET_LIST_SIZE_4_11216 1216
26
27#define BASE_RANGE_BITS_4_03 3
28#define BASE_RANGE_BITS_4_16 6
29
30struct latency_statistics {
31 __u16 version_major;
32 __u16 version_minor;
33 __u32 data[BUCKET_LIST_SIZE_4_11216];
34 __u64 average_latency;
35};
36
37struct config {
38 bool_Bool enable;
39 bool_Bool disable;
40 bool_Bool read;
41 bool_Bool write;
42 unsigned char type;
43};
44
45struct latency_tracker {
46 struct libnvme_transport_handle *hdl;
47 __u8 uuid_index;
48 struct config cfg;
49 nvme_print_flags_t print_flags;
50 struct latency_statistics stats;
51 struct json_object *bucket_list;
52 __u32 bucket_list_size;
53 __u8 base_range_bits;
54 bool_Bool has_average_latency_field;
55};
56
57/* COL_WIDTH controls width of columns in NORMAL output. */
58#define COL_WIDTH12 12
59#define BUCKET_LABEL_MAX_SIZE10 10
60
61#define US_IN_S1000000 1000000
62#define US_IN_MS1000 1000
63
64/*
65 * Edge buckets may have range [#s, inf) in some
66 * latency statistics formats.
67 */
68static void get_time_unit_label(char *label, __u32 microseconds,
69 bool_Bool bonded)
70{
71 char *string = "us";
72 int divisor = 1;
73
74 if (!bonded) {
75 snprintf(label, BUCKET_LABEL_MAX_SIZE10, "%s", "+INF");
76 return;
77 }
78
79 if (microseconds > US_IN_S1000000) {
80 string = "s";
81 divisor = US_IN_S1000000;
82 } else if (microseconds > US_IN_MS1000) {
83 string = "ms";
84 divisor = US_IN_MS1000;
85 }
86
87 snprintf(label, BUCKET_LABEL_MAX_SIZE10, "%4.2f%s", (float) microseconds / divisor,
88 string);
89}
90
91static void latency_tracker_bucket_parse(const struct latency_tracker *lt, int id,
92 __u32 lower_us, __u32 upper_us, bool_Bool upper_bounded)
93{
94 char buffer[BUCKET_LABEL_MAX_SIZE10] = "";
95 __u32 bucket_data = le32_to_cpu(lt->stats.data[id]);
96
97 if (lt->print_flags == NORMAL) {
98 printf("%-*d", COL_WIDTH12, id);
99
100 get_time_unit_label(buffer, lower_us, true1);
101 printf("%-*s", COL_WIDTH12, buffer);
102
103 get_time_unit_label(buffer, upper_us, upper_bounded);
104 printf("%-*s", COL_WIDTH12, buffer);
105
106 printf("%-*d\n", COL_WIDTH12, bucket_data);
107 }
108
109 if (lt->print_flags == JSON) {
110 /*
111 * Creates a bucket under the "values" json_object. Format is:
112 * "values" : {
113 * "bucket" : {
114 * "id" : #,
115 * "start" : string,
116 * "end" : string,
117 * "value" : 0,
118 * },
119 */
120 struct json_object *bucket = json_create_object()json_object_new_object();
121
122 json_object_array_add(lt->bucket_list, bucket);
123 json_object_add_value_int(bucket, "id", id)json_object_object_add(bucket, "id", json_object_new_int(id));
124
125 get_time_unit_label(buffer, lower_us, true1);
126 json_object_add_value_string(bucket, "start", buffer);
127
128 get_time_unit_label(buffer, upper_us, upper_bounded);
129 json_object_add_value_string(bucket, "end", buffer);
130
131 json_object_add_value_int(bucket, "value", bucket_data)json_object_object_add(bucket, "value", json_object_new_int(bucket_data
))
;
132 }
133}
134
135static void latency_tracker_parse_linear(const struct latency_tracker *lt,
136 __u32 start_offset, __u32 end_offset,
137 __u32 bytes_per, __u32 us_step,
138 bool_Bool nonzero_print)
139{
140 for (int i = (start_offset / bytes_per) - 1; i < end_offset / bytes_per; i++) {
141 if (nonzero_print && !lt->stats.data[i])
142 continue;
143 latency_tracker_bucket_parse(lt, i, us_step * i, us_step * (i + 1), true1);
144 }
145}
146
147/*
148 * Calculates bucket time slot. Valid starting on 4.0 revision.
149 */
150
151static int latency_tracker_bucket_pos2us(const struct latency_tracker *lt, int i)
152{
153 __u32 base_val = 1 << lt->base_range_bits;
27
Assuming right operand of bit shift is less than 32
154
155 if (i < (base_val << 1))
28
Assuming the condition is false
29
Taking false branch
156 return i;
157
158 int error_bits = (i >> lt->base_range_bits) - 1;
30
'error_bits' initialized to -1
159 int base = 1 << (error_bits + lt->base_range_bits);
160 int k = i % base_val;
161
162 return base + ((k + 0.5) * (1 << error_bits));
31
The result of left shift is undefined because the right operand is negative
163}
164
165/*
166 * Creates a subroot in the following manner:
167 * {
168 * "latstats" : {
169 * "type" : "write" or "read",
170 * "values" : {
171 */
172static void latency_tracker_populate_json_root(const struct latency_tracker *lt,
173 struct json_object *root)
174{
175 struct json_object *subroot = json_create_object()json_object_new_object();
176
177 json_object_add_value_object(root, "latstats", subroot)json_object_object_add(root, "latstats", subroot);
178 json_object_add_value_string(subroot, "type", lt->cfg.write ? "write" : "read");
179 if (lt->has_average_latency_field)
180 json_object_add_value_uint64(subroot, "average_latency",json_object_object_add(subroot, "average_latency", json_object_new_uint64
(le64_to_cpu(lt->stats.average_latency)))
181 le64_to_cpu(lt->stats.average_latency))json_object_object_add(subroot, "average_latency", json_object_new_uint64
(le64_to_cpu(lt->stats.average_latency)))
;
182 json_object_add_value_object(subroot, "values", lt->bucket_list)json_object_object_add(subroot, "values", lt->bucket_list);
183}
184
185static void latency_tracker_parse_3_0(const struct latency_tracker *lt)
186{
187 latency_tracker_parse_linear(lt, 4, 131, 4, 32, false0);
188 latency_tracker_parse_linear(lt, 132, 255, 4, 1024, false0);
189 latency_tracker_parse_linear(lt, 256, 379, 4, 32768, false0);
190 latency_tracker_parse_linear(lt, 380, 383, 4, 32, true1);
191 latency_tracker_parse_linear(lt, 384, 387, 4, 32, true1);
192 latency_tracker_parse_linear(lt, 388, 391, 4, 32, true1);
193}
194
195static void latency_tracker_parse_4_0(const struct latency_tracker *lt)
196{
197 for (unsigned int i = 0; i < lt->bucket_list_size; i++) {
24
Assuming 'i' is < field 'bucket_list_size'
25
Loop condition is true. Entering loop body
198 int lower_us = latency_tracker_bucket_pos2us(lt, i);
26
Calling 'latency_tracker_bucket_pos2us'
199 int upper_us = latency_tracker_bucket_pos2us(lt, i + 1);
200
201 latency_tracker_bucket_parse(lt, i, lower_us, upper_us,
202 i < (lt->bucket_list_size - 1));
203 }
204}
205
206static void print_dash_separator(void)
207{
208 printf("--------------------------------------------------\n");
209}
210
211static void latency_tracker_pre_parse(struct latency_tracker *lt)
212{
213 if (lt->print_flags == NORMAL) {
214 printf("Solidigm IO %s Command Latency Tracking Statistics type %d\n",
215 lt->cfg.write ? "Write" : "Read", lt->cfg.type);
216 printf("UUID-idx: %d\n", lt->uuid_index);
217 printf("Major Revision: %u\nMinor Revision: %u\n",
218 le16_to_cpu(lt->stats.version_major), le16_to_cpu(lt->stats.version_minor));
219 if (lt->has_average_latency_field)
220 printf("Average Latency: %" PRIu64"l" "u" "\n", le64_to_cpu(lt->stats.average_latency));
221 print_dash_separator();
222 printf("%-12s%-12s%-12s%-20s\n", "Bucket", "Start", "End", "Value");
223 print_dash_separator();
224 }
225 if (lt->print_flags == JSON)
226 lt->bucket_list = json_object_new_array();
227}
228
229static void latency_tracker_post_parse(struct latency_tracker *lt)
230{
231 if (lt->print_flags == JSON) {
232 struct json_object *root = json_create_object()json_object_new_object();
233
234 latency_tracker_populate_json_root(lt, root);
235 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
236 json_free_object(root)json_object_put(root);
237 printf("\n");
238 }
239}
240
241static void latency_tracker_parse(struct latency_tracker *lt)
242{
243 __u16 version_major = le16_to_cpu(lt->stats.version_major);
244 __u16 version_minor = le16_to_cpu(lt->stats.version_minor);
245
246 switch (version_major) {
18
Control jumps to 'case 4:' at line 251
247 case 3:
248 latency_tracker_pre_parse(lt);
249 latency_tracker_parse_3_0(lt);
250 break;
251 case 4:
252 if (version_minor >= 8)
19
Assuming 'version_minor' is < 8
20
Taking false branch
253 lt->has_average_latency_field = true1;
254 latency_tracker_pre_parse(lt);
255 if (!version_minor) {
21
Assuming 'version_minor' is not equal to 0
22
Taking false branch
256 lt->base_range_bits = BASE_RANGE_BITS_4_03;
257 lt->bucket_list_size = BUCKET_LIST_SIZE_4_0152;
258 }
259 latency_tracker_parse_4_0(lt);
23
Calling 'latency_tracker_parse_4_0'
260 break;
261 default:
262 printf("Unsupported revision (%u.%u)\n",
263 version_major, version_minor);
264 break;
265 }
266
267 latency_tracker_post_parse(lt);
268}
269
270#define LATENCY_TRACKING_FID0xe2 0xe2
271#define LATENCY_TRACKING_FID_DATA_LEN32 32
272
273static int latency_tracking_is_enable(struct latency_tracker *lt, __u64 *enabled)
274{
275 return nvme_get_features(lt->hdl, 0, LATENCY_TRACKING_FID0xe2, 0, 0,
276 lt->uuid_index, NULL((void*)0),
277 LATENCY_TRACKING_FID_DATA_LEN32, enabled);
278}
279
280static int latency_tracking_enable(struct latency_tracker *lt)
281{
282 __u64 result;
283 int err;
284
285 if (!(lt->cfg.enable || lt->cfg.disable))
286 return 0;
287
288 if (lt->cfg.enable && lt->cfg.disable) {
289 fprintf(stderrstderr, "Cannot enable and disable simultaneously.\n");
290 return -EINVAL22;
291 }
292
293 err = nvme_set_features(lt->hdl, 0, LATENCY_TRACKING_FID0xe2, 0,
294 lt->cfg.enable, 0, 0, lt->uuid_index, 0, NULL((void*)0),
295 LATENCY_TRACKING_FID_DATA_LEN32, &result);
296 if (err > 0) {
297 nvme_show_status(err);
298 } else if (err < 0) {
299 perror("Enable latency tracking");
300 fprintf(stderrstderr, "Command failed while parsing.\n");
301 } else {
302 if (lt->print_flags == NORMAL) {
303 printf("Successfully set enable bit for UUID-idx:%d FID:0x%X, to %i.\n",
304 lt->uuid_index, LATENCY_TRACKING_FID0xe2, lt->cfg.enable);
305 }
306 }
307 return err;
308}
309
310#define READ_LOG_ID0xc1 0xc1
311#define WRITE_LOG_ID0xc2 0xc2
312
313static int latency_tracker_get_log(struct latency_tracker *lt)
314{
315 struct libnvme_passthru_cmd cmd;
316 int err;
317
318 if (lt->cfg.read && lt->cfg.write) {
9
Assuming field 'read' is false
319 fprintf(stderrstderr, "Cannot capture read and write logs simultaneously.\n");
320 return -EINVAL22;
321 }
322
323 if (!(lt->cfg.read
9.1
Field 'read' is false
|| lt->cfg.write)
)
10
Assuming the condition is false
11
Taking false branch
324 return 0;
325
326 nvme_init_get_log(&cmd, NVME_NSID_ALL,
327 lt->cfg.write
11.1
Field 'write' is true
? WRITE_LOG_ID0xc2 : READ_LOG_ID0xc1,
12
'?' condition is true
328 NVME_CSI_NVM, &lt->stats, sizeof(lt->stats));
329 cmd.cdw10 |= NVME_FIELD_ENCODE(lt->cfg.type,(((__u32)(lt->cfg.type) & (NVME_LOG_CDW10_LSP_MASK)) <<
(NVME_LOG_CDW10_LSP_SHIFT))
330 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(lt->cfg.type) & (NVME_LOG_CDW10_LSP_MASK)) <<
(NVME_LOG_CDW10_LSP_SHIFT))
331 NVME_LOG_CDW10_LSP_MASK)(((__u32)(lt->cfg.type) & (NVME_LOG_CDW10_LSP_MASK)) <<
(NVME_LOG_CDW10_LSP_SHIFT))
;
332 cmd.cdw14 |= NVME_FIELD_ENCODE(lt->uuid_index,(((__u32)(lt->uuid_index) & (NVME_LOG_CDW14_UUID_MASK)
) << (NVME_LOG_CDW14_UUID_SHIFT))
333 NVME_LOG_CDW14_UUID_SHIFT,(((__u32)(lt->uuid_index) & (NVME_LOG_CDW14_UUID_MASK)
) << (NVME_LOG_CDW14_UUID_SHIFT))
334 NVME_LOG_CDW14_UUID_MASK)(((__u32)(lt->uuid_index) & (NVME_LOG_CDW14_UUID_MASK)
) << (NVME_LOG_CDW14_UUID_SHIFT))
;
335 err = libnvme_get_log(lt->hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
336 if (err)
13
Assuming 'err' is 0
14
Taking false branch
337 return err;
338
339 if (lt->print_flags & BINARY)
15
Assuming the condition is false
16
Taking false branch
340 d_raw((unsigned char *)&lt->stats,
341 sizeof(lt->stats));
342 else {
343 latency_tracker_parse(lt);
17
Calling 'latency_tracker_parse'
344 }
345 return err;
346}
347
348int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *acmd,
349 struct plugin *plugin)
350{
351 const char *desc = "Get and Parse Solidigm Latency Tracking Statistics log.";
352 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
353 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
354 __u64 enabled;
355 int err;
356
357 struct latency_tracker lt = {
358 .uuid_index = 0,
359 .base_range_bits = BASE_RANGE_BITS_4_16,
360 .bucket_list_size = BUCKET_LIST_SIZE_4_11216,
361 .has_average_latency_field = false0,
362 };
363
364 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"enable", 'e', ((void*)0), CFG_FLAG, &lt.cfg.enable
, 0, "Enable Latency Tracking", 0, }, {"disable", 'd', ((void
*)0), CFG_FLAG, &lt.cfg.disable, 0, "Disable Latency Tracking"
, 0, }, {"read", 'r', ((void*)0), CFG_FLAG, &lt.cfg.read,
0, "Get read statistics", 0, }, {"write", 'w', ((void*)0), CFG_FLAG
, &lt.cfg.write, 0, "Get write statistics", 0, }, {"type"
, 't', "NUM", CFG_BYTE, &lt.cfg.type, 1, "Log type to get"
, 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) } }
365 OPT_FLAG("enable", 'e', &lt.cfg.enable, "Enable Latency Tracking"),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"enable", 'e', ((void*)0), CFG_FLAG, &lt.cfg.enable
, 0, "Enable Latency Tracking", 0, }, {"disable", 'd', ((void
*)0), CFG_FLAG, &lt.cfg.disable, 0, "Disable Latency Tracking"
, 0, }, {"read", 'r', ((void*)0), CFG_FLAG, &lt.cfg.read,
0, "Get read statistics", 0, }, {"write", 'w', ((void*)0), CFG_FLAG
, &lt.cfg.write, 0, "Get write statistics", 0, }, {"type"
, 't', "NUM", CFG_BYTE, &lt.cfg.type, 1, "Log type to get"
, 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) } }
366 OPT_FLAG("disable", 'd', &lt.cfg.disable, "Disable Latency Tracking"),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"enable", 'e', ((void*)0), CFG_FLAG, &lt.cfg.enable
, 0, "Enable Latency Tracking", 0, }, {"disable", 'd', ((void
*)0), CFG_FLAG, &lt.cfg.disable, 0, "Disable Latency Tracking"
, 0, }, {"read", 'r', ((void*)0), CFG_FLAG, &lt.cfg.read,
0, "Get read statistics", 0, }, {"write", 'w', ((void*)0), CFG_FLAG
, &lt.cfg.write, 0, "Get write statistics", 0, }, {"type"
, 't', "NUM", CFG_BYTE, &lt.cfg.type, 1, "Log type to get"
, 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) } }
367 OPT_FLAG("read", 'r', &lt.cfg.read, "Get read statistics"),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"enable", 'e', ((void*)0), CFG_FLAG, &lt.cfg.enable
, 0, "Enable Latency Tracking", 0, }, {"disable", 'd', ((void
*)0), CFG_FLAG, &lt.cfg.disable, 0, "Disable Latency Tracking"
, 0, }, {"read", 'r', ((void*)0), CFG_FLAG, &lt.cfg.read,
0, "Get read statistics", 0, }, {"write", 'w', ((void*)0), CFG_FLAG
, &lt.cfg.write, 0, "Get write statistics", 0, }, {"type"
, 't', "NUM", CFG_BYTE, &lt.cfg.type, 1, "Log type to get"
, 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) } }
368 OPT_FLAG("write", 'w', &lt.cfg.write, "Get write statistics"),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"enable", 'e', ((void*)0), CFG_FLAG, &lt.cfg.enable
, 0, "Enable Latency Tracking", 0, }, {"disable", 'd', ((void
*)0), CFG_FLAG, &lt.cfg.disable, 0, "Disable Latency Tracking"
, 0, }, {"read", 'r', ((void*)0), CFG_FLAG, &lt.cfg.read,
0, "Get read statistics", 0, }, {"write", 'w', ((void*)0), CFG_FLAG
, &lt.cfg.write, 0, "Get write statistics", 0, }, {"type"
, 't', "NUM", CFG_BYTE, &lt.cfg.type, 1, "Log type to get"
, 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) } }
369 OPT_BYTE("type", 't', &lt.cfg.type, "Log type to get"))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"enable", 'e', ((void*)0), CFG_FLAG, &lt.cfg.enable
, 0, "Enable Latency Tracking", 0, }, {"disable", 'd', ((void
*)0), CFG_FLAG, &lt.cfg.disable, 0, "Disable Latency Tracking"
, 0, }, {"read", 'r', ((void*)0), CFG_FLAG, &lt.cfg.read,
0, "Get read statistics", 0, }, {"write", 'w', ((void*)0), CFG_FLAG
, &lt.cfg.write, 0, "Get write statistics", 0, }, {"type"
, 't', "NUM", CFG_BYTE, &lt.cfg.type, 1, "Log type to get"
, 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) } }
;
370
371 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
372 if (err)
1
Assuming 'err' is 0
2
Taking false branch
373 return err;
374
375 lt.hdl = hdl;
376
377 err = validate_output_format(nvme_args.output_format, &lt.print_flags);
378 if (err < 0) {
3
Assuming 'err' is >= 0
4
Taking false branch
379 fprintf(stderrstderr, "Invalid output format '%s'\n",
380 nvme_args.output_format);
381 return -EINVAL22;
382 }
383
384 if (lt.cfg.type > 0xf) {
5
Assuming field 'type' is <= 15
385 fprintf(stderrstderr, "Invalid Log type value '%d'\n", lt.cfg.type);
386 return -EINVAL22;
387 }
388
389 if (lt.cfg.type && !(lt.cfg.read || lt.cfg.write)) {
6
Assuming field 'type' is 0
390 fprintf(stderrstderr, "Log type option valid only when retrieving statistics\n");
391 return -EINVAL22;
392 }
393
394 sldgm_get_uuid_index(hdl, &lt.uuid_index);
395
396 err = latency_tracking_enable(&lt);
397 if (err
6.1
'err' is 0
)
7
Taking false branch
398 return err;
399
400 err = latency_tracker_get_log(&lt);
8
Calling 'latency_tracker_get_log'
401 if (err)
402 return err;
403
404 if ((lt.cfg.read || lt.cfg.write || lt.cfg.enable || lt.cfg.disable))
405 return 0;
406
407 err = latency_tracking_is_enable(&lt, &enabled);
408 if (!err) {
409 if (lt.print_flags == JSON) {
410 struct json_object *root = json_create_object()json_object_new_object();
411
412 json_object_add_value_int(root, "enabled", enabled)json_object_object_add(root, "enabled", json_object_new_int(enabled
))
;
413 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
414 json_free_object(root)json_object_put(root);
415 printf("\n");
416 } else if (lt.print_flags == BINARY) {
417 putchar(enabled);
418 } else {
419 printf("Latency Statistics Tracking (UUID-idx:%d, FID:0x%X) is currently %"PRIu64"l" "u"".\n",
420 lt.uuid_index, LATENCY_TRACKING_FID0xe2,
421 (uint64_t)enabled);
422 }
423 } else {
424 fprintf(stderrstderr, "Could not read feature id 0xE2.\n");
425 }
426 return err;
427}