Bug Summary

File:.build-ci/../src/nvme-cmds-passthru.c
Warning:line 249, column 4
Potential leak of memory pointed to by 'mdata'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nvme-cmds-passthru.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/bin/../lib/clang/22 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -I src -I ../src -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu11 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-10-24-125112-639-1 -x c ../src/nvme-cmds-passthru.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * NVM-Express command line utility.
4 *
5 * Copyright (c) 2014-2015, Intel Corporation.
6 *
7 * Written by Keith Busch <kbusch@kernel.org>
8 */
9
10/**
11 * This program uses NVMe IOCTLs to run native nvme commands to a device.
12 */
13#include <dirent.h>
14#include <errno(*__errno_location ()).h>
15#include <fcntl.h>
16#include <inttypes.h>
17#include <libgen.h>
18#include <locale.h>
19#include <math.h>
20#include <signal.h>
21#include <stdint.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27#include <sys/stat.h>
28#include <sys/types.h>
29
30#include <libnvme-mi.h>
31#include <libnvme.h>
32
33#include <ccan/array_size/array_size.h>
34#include <ccan/endian/endian.h>
35#include <ccan/minmax/minmax.h>
36#include <shared/compiler-attributes-util.h>
37#include <shared/fs-util.h>
38#include <shared/mmio-util.h>
39#include <shared/parse-util.h>
40#include <shared/sig-util.h>
41#include <shared/suffix-util.h>
42#include <shared/time-util.h>
43
44#include "argconfig.h"
45#include "cleanup.h"
46#include "global-ctx.h"
47#include "logging.h"
48#include "nvme-cmds-common.h"
49#include "nvme-print.h"
50#include "plugin.h"
51
52static const char *latency = "output latency statistics";
53static const char *namespace_desired = "desired namespace";
54static const char *raw_dump = "dump output in binary format";
55
56static void passthru_print_read_output(struct passthru_config cfg, void *data, int dfd, void *mdata,
57 int mfd, int err)
58{
59 if (strlen(cfg.input_file)) {
60 if (write(dfd, (void *)data, cfg.data_len) < 0)
61 perror("failed to write data buffer");
62 } else if (data) {
63 if (cfg.raw_binary)
64 d_raw((unsigned char *)data, cfg.data_len);
65 else if (!err)
66 d((unsigned char *)data, cfg.data_len, 16, 1);
67 }
68 if (cfg.metadata_len && cfg.metadata) {
69 if (strlen(cfg.metadata)) {
70 if (write(mfd, (void *)mdata, cfg.metadata_len) < 0)
71 perror("failed to write metadata buffer");
72 } else {
73 if (cfg.raw_binary)
74 d_raw((unsigned char *)mdata, cfg.metadata_len);
75 else if (!err)
76 d((unsigned char *)mdata, cfg.metadata_len, 16, 1);
77 }
78 }
79}
80
81static int passthru(int argc, char **argv, bool_Bool admin,
82 const char *desc, struct command *acmd)
83{
84 const char *opcode = "opcode (required)";
85 const char *cflags = "command flags";
86 const char *rsvd = "value for reserved field";
87 const char *data_len = "data I/O length (bytes)";
88 const char *metadata_len = "metadata seg. length (bytes)";
89 const char *metadata = "metadata input or output file";
90 const char *cdw2 = "command dword 2 value";
91 const char *cdw3 = "command dword 3 value";
92 const char *cdw10 = "command dword 10 value";
93 const char *cdw11 = "command dword 11 value";
94 const char *cdw12 = "command dword 12 value";
95 const char *cdw13 = "command dword 13 value";
96 const char *cdw14 = "command dword 14 value";
97 const char *cdw15 = "command dword 15 value";
98 const char *input = "data input or output file";
99 const char *show = "print command before sending";
100 const char *re = "set dataflow direction to receive";
101 const char *wr = "set dataflow direction to send";
102 const char *prefill = "prefill buffers with known byte-value, default 0";
103
104 __cleanup_huge__attribute__((cleanup(libnvme_free_huge))) struct libnvme_mem_huge mh = { 0, };
105 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
106 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
107 __cleanup_fd__attribute__((cleanup(shr_cleanup_fd))) int dfd = -1, mfd = -1;
108 int flags = -1;
109 int mode = 0644;
110 void *data = NULL((void*)0);
111 __cleanup_free__attribute__((cleanup(shr_freep))) void *mdata = NULL((void*)0);
112 int err = 0;
113 const char *cmd_name = NULL((void*)0);
114 struct timeval start_time, end_time;
115
116 struct passthru_config cfg = {
117 .opcode = 0,
118 .flags = 0,
119 .prefill = 0,
120 .rsvd = 0,
121 .namespace_id = 0,
122 .data_len = 0,
123 .metadata_len = 0,
124 .cdw2 = 0,
125 .cdw3 = 0,
126 .cdw10 = 0,
127 .cdw11 = 0,
128 .cdw12 = 0,
129 .cdw13 = 0,
130 .cdw14 = 0,
131 .cdw15 = 0,
132 .input_file = "",
133 .metadata = "",
134 .raw_binary = false0,
135 .show_command = false0,
136 .read = false0,
137 .write = false0,
138 .latency = false0,
139 };
140
141 OPT_ARGS(opts)struct argconfig_commandline_options opts[] = {
142 OPT_BYTE("opcode", 'O', &cfg.opcode, opcode){"opcode", 'O', "NUM", CFG_BYTE, _Generic(&cfg.opcode, uint8_t
* : (&cfg.opcode)), ARGCONFIG_ARG_REQUIRED, opcode, 0, }
,
143 OPT_BYTE("flags", 'f', &cfg.flags, cflags){"flags", 'f', "NUM", CFG_BYTE, _Generic(&cfg.flags, uint8_t
* : (&cfg.flags)), ARGCONFIG_ARG_REQUIRED, cflags, 0, }
,
144 OPT_BYTE("prefill", 'p', &cfg.prefill, prefill){"prefill", 'p', "NUM", CFG_BYTE, _Generic(&cfg.prefill, uint8_t
* : (&cfg.prefill)), ARGCONFIG_ARG_REQUIRED, prefill, 0,
}
,
145 OPT_SHRT("rsvd", 'R', &cfg.rsvd, rsvd){"rsvd", 'R', "NUM", CFG_SHORT, _Generic(&cfg.rsvd, uint16_t
* : (&cfg.rsvd)), ARGCONFIG_ARG_REQUIRED, rsvd, 0, }
,
146 OPT_UINT("namespace-id", 'n', &cfg.namespace_id,{"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_desired, 0, nvme_nsid_values}
147 namespace_desired, nvme_nsid_values){"namespace-id", 'n', "NUM", CFG_POSITIVE, _Generic(&cfg.
namespace_id, uint32_t * : (&cfg.namespace_id)), ARGCONFIG_ARG_REQUIRED
, namespace_desired, 0, nvme_nsid_values}
,
148 OPT_UINT("data-len", 'l', &cfg.data_len, data_len){"data-len", 'l', "NUM", CFG_POSITIVE, _Generic(&cfg.data_len
, uint32_t * : (&cfg.data_len)), ARGCONFIG_ARG_REQUIRED, data_len
, 0, }
,
149 OPT_UINT("metadata-len", 'm', &cfg.metadata_len, metadata_len){"metadata-len", 'm', "NUM", CFG_POSITIVE, _Generic(&cfg.
metadata_len, uint32_t * : (&cfg.metadata_len)), ARGCONFIG_ARG_REQUIRED
, metadata_len, 0, }
,
150 OPT_UINT("cdw2", '2', &cfg.cdw2, cdw2){"cdw2", '2', "NUM", CFG_POSITIVE, _Generic(&cfg.cdw2, uint32_t
* : (&cfg.cdw2)), ARGCONFIG_ARG_REQUIRED, cdw2, 0, }
,
151 OPT_UINT("cdw3", '3', &cfg.cdw3, cdw3){"cdw3", '3', "NUM", CFG_POSITIVE, _Generic(&cfg.cdw3, uint32_t
* : (&cfg.cdw3)), ARGCONFIG_ARG_REQUIRED, cdw3, 0, }
,
152 OPT_UINT("cdw10", '4', &cfg.cdw10, cdw10){"cdw10", '4', "NUM", CFG_POSITIVE, _Generic(&cfg.cdw10, uint32_t
* : (&cfg.cdw10)), ARGCONFIG_ARG_REQUIRED, cdw10, 0, }
,
153 OPT_UINT("cdw11", '5', &cfg.cdw11, cdw11){"cdw11", '5', "NUM", CFG_POSITIVE, _Generic(&cfg.cdw11, uint32_t
* : (&cfg.cdw11)), ARGCONFIG_ARG_REQUIRED, cdw11, 0, }
,
154 OPT_UINT("cdw12", '6', &cfg.cdw12, cdw12){"cdw12", '6', "NUM", CFG_POSITIVE, _Generic(&cfg.cdw12, uint32_t
* : (&cfg.cdw12)), ARGCONFIG_ARG_REQUIRED, cdw12, 0, }
,
155 OPT_UINT("cdw13", '7', &cfg.cdw13, cdw13){"cdw13", '7', "NUM", CFG_POSITIVE, _Generic(&cfg.cdw13, uint32_t
* : (&cfg.cdw13)), ARGCONFIG_ARG_REQUIRED, cdw13, 0, }
,
156 OPT_UINT("cdw14", '8', &cfg.cdw14, cdw14){"cdw14", '8', "NUM", CFG_POSITIVE, _Generic(&cfg.cdw14, uint32_t
* : (&cfg.cdw14)), ARGCONFIG_ARG_REQUIRED, cdw14, 0, }
,
157 OPT_UINT("cdw15", '9', &cfg.cdw15, cdw15){"cdw15", '9', "NUM", CFG_POSITIVE, _Generic(&cfg.cdw15, uint32_t
* : (&cfg.cdw15)), ARGCONFIG_ARG_REQUIRED, cdw15, 0, }
,
158 OPT_FILE("input-file", 'i', &cfg.input_file, input){"input-file", 'i', "FILE", CFG_FILE, _Generic(&cfg.input_file
, char ** : (&cfg.input_file), const char ** : (&cfg.
input_file)), ARGCONFIG_ARG_REQUIRED, input, 0, }
,
159 OPT_FILE("metadata", 'M', &cfg.metadata, metadata){"metadata", 'M', "FILE", CFG_FILE, _Generic(&cfg.metadata
, char ** : (&cfg.metadata), const char ** : (&cfg.metadata
)), ARGCONFIG_ARG_REQUIRED, metadata, 0, }
,
160 OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_dump){"raw-binary", 'b', ((void*)0), CFG_FLAG, _Generic(&cfg.raw_binary
, _Bool * : (&cfg.raw_binary)), ARGCONFIG_ARG_NONE, raw_dump
, 0, }
,
161 OPT_FLAG("show-command", 's', &cfg.show_command, show){"show-command", 's', ((void*)0), CFG_FLAG, _Generic(&cfg
.show_command, _Bool * : (&cfg.show_command)), ARGCONFIG_ARG_NONE
, show, 0, }
,
162 OPT_FLAG("read", 'r', &cfg.read, re){"read", 'r', ((void*)0), CFG_FLAG, _Generic(&cfg.read, _Bool
* : (&cfg.read)), ARGCONFIG_ARG_NONE, re, 0, }
,
163 OPT_FLAG("write", 'w', &cfg.write, wr){"write", 'w', ((void*)0), CFG_FLAG, _Generic(&cfg.write,
_Bool * : (&cfg.write)), ARGCONFIG_ARG_NONE, wr, 0, }
,
164 OPT_FLAG("latency", 'T', &cfg.latency, latency){"latency", 'T', ((void*)0), CFG_FLAG, _Generic(&cfg.latency
, _Bool * : (&cfg.latency)), ARGCONFIG_ARG_NONE, latency,
0, }
,
165 OPT_END(){ ((void*)0) }
166 };
167
168 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
169 if (err)
2
Assuming 'err' is 0
3
Taking false branch
170 return err;
171
172 if (!argconfig_given(opts, &cfg.opcode)) {
4
Assuming the condition is false
5
Taking false branch
173 nvme_show_error("%s: opcode parameter required", acmd->name)nvme_show_message(1, "%s: opcode parameter required", acmd->
name)
;
174 return -EINVAL22;
175 }
176
177 if (cfg.opcode & 0x01) {
6
Assuming the condition is false
7
Taking false branch
178 cfg.write = true1;
179 flags = O_RDONLY00;
180 dfd = mfd = STDIN_FILENO0;
181 }
182
183 if (cfg.opcode & 0x02) {
8
Assuming the condition is false
184 cfg.read = true1;
185 flags = O_WRONLY01 | O_CREAT0100 | O_TRUNC01000;
186 dfd = mfd = STDOUT_FILENO1;
187 }
188
189 /*
190 * Fallback to user specified data direction in case from opcode
191 * we can't decode direction.
192 */
193 if (cfg.write && flags < 0) {
9
Assuming field 'write' is false
194 flags = O_RDONLY00;
195 dfd = mfd = STDIN_FILENO0;
196 }
197
198 if (cfg.read && flags < 0) {
10
Assuming field 'read' is false
199 flags = O_WRONLY01 | O_CREAT0100 | O_TRUNC01000;
200 dfd = mfd = STDOUT_FILENO1;
201 }
202 if (strlen(cfg.input_file)) {
11
Assuming the condition is false
203 if (flags < 0) {
204 nvme_show_error("input file specified for opcode 0x%x "nvme_show_message(1, "input file specified for opcode 0x%x " "without a data transfer direction"
, cfg.opcode)
205 "without a data transfer direction",nvme_show_message(1, "input file specified for opcode 0x%x " "without a data transfer direction"
, cfg.opcode)
206 cfg.opcode)nvme_show_message(1, "input file specified for opcode 0x%x " "without a data transfer direction"
, cfg.opcode)
;
207 return -EINVAL22;
208 }
209 dfd = shr_open_rawdata(cfg.input_file, flags, mode)open((cfg.input_file), (flags), mode);
210 if (dfd < 0) {
211 nvme_show_perror(cfg.input_file);
212 return -EINVAL22;
213 }
214 }
215
216 if (cfg.metadata && strlen(cfg.metadata)) {
12
Assuming field 'metadata' is null
217 if (flags < 0) {
218 nvme_show_error("metadata file specified for opcode 0x%x "nvme_show_message(1, "metadata file specified for opcode 0x%x "
"without a data transfer direction", cfg.opcode)
219 "without a data transfer direction",nvme_show_message(1, "metadata file specified for opcode 0x%x "
"without a data transfer direction", cfg.opcode)
220 cfg.opcode)nvme_show_message(1, "metadata file specified for opcode 0x%x "
"without a data transfer direction", cfg.opcode)
;
221 return -EINVAL22;
222 }
223 mfd = shr_open_rawdata(cfg.metadata, flags, mode)open((cfg.metadata), (flags), mode);
224 if (mfd < 0) {
225 nvme_show_perror(cfg.metadata);
226 return -EINVAL22;
227 }
228 }
229
230 if (cfg.metadata_len) {
13
Assuming field 'metadata_len' is not equal to 0
14
Taking true branch
231 mdata = malloc(cfg.metadata_len);
15
Memory is allocated
232 if (!mdata)
16
Assuming 'mdata' is non-null
17
Taking false branch
233 return -ENOMEM12;
234
235 if (cfg.write
17.1
Field 'write' is false
) {
18
Taking false branch
236 if (read(mfd, mdata, cfg.metadata_len) < 0) {
237 err = -errno(*__errno_location ());
238 nvme_show_perror("failed to read metadata write buffer");
239 return err;
240 }
241 } else {
242 memset(mdata, cfg.prefill, cfg.metadata_len);
243 }
244 }
245
246 if (cfg.data_len) {
19
Assuming field 'data_len' is not equal to 0
20
Taking true branch
247 data = libnvme_alloc_huge(cfg.data_len, &mh);
248 if (!data) {
21
Assuming 'data' is null
22
Taking true branch
249 nvme_show_error("failed to allocate huge memory")nvme_show_message(1, "failed to allocate huge memory");
23
Potential leak of memory pointed to by 'mdata'
250 return -ENOMEM12;
251 }
252
253 memset(data, cfg.prefill, cfg.data_len);
254 if (!cfg.read && !cfg.write) {
255 nvme_show_error("data direction not given")nvme_show_message(1, "data direction not given");
256 return -EINVAL22;
257 } else if (cfg.write) {
258 if (read(dfd, data, cfg.data_len) < 0) {
259 err = -errno(*__errno_location ());
260 nvme_show_error("failed to read write buffer %s", libnvme_strerror(errno))nvme_show_message(1, "failed to read write buffer %s", libnvme_strerror
((*__errno_location ())))
;
261 return err;
262 }
263 }
264 }
265
266 if (cfg.show_command || nvme_args.dry_run) {
267 nvme_show_result("opcode : %02x", cfg.opcode)nvme_show_message(0, "opcode : %02x", cfg.opcode);
268 nvme_show_result("flags : %02x", cfg.flags)nvme_show_message(0, "flags : %02x", cfg.flags);
269 nvme_show_result("rsvd1 : %04x", cfg.rsvd)nvme_show_message(0, "rsvd1 : %04x", cfg.rsvd);
270 nvme_show_result("nsid : %08x", cfg.namespace_id)nvme_show_message(0, "nsid : %08x", cfg.namespace_id);
271 nvme_show_result("cdw2 : %08x", cfg.cdw2)nvme_show_message(0, "cdw2 : %08x", cfg.cdw2);
272 nvme_show_result("cdw3 : %08x", cfg.cdw3)nvme_show_message(0, "cdw3 : %08x", cfg.cdw3);
273 nvme_show_result("data_len : %08x", cfg.data_len)nvme_show_message(0, "data_len : %08x", cfg.data_len);
274 nvme_show_result("metadata_len : %08x", cfg.metadata_len)nvme_show_message(0, "metadata_len : %08x", cfg.metadata_len);
275 nvme_show_result("addr : %"PRIx64, (uint64_t)(uintptr_t)data)nvme_show_message(0, "addr : %""l" "x", (uint64_t)(uintptr_t
)data)
;
276 nvme_show_result("metadata : %"PRIx64, (uint64_t)(uintptr_t)mdata)nvme_show_message(0, "metadata : %""l" "x", (uint64_t)(uintptr_t
)mdata)
;
277 nvme_show_result("cdw10 : %08x", cfg.cdw10)nvme_show_message(0, "cdw10 : %08x", cfg.cdw10);
278 nvme_show_result("cdw11 : %08x", cfg.cdw11)nvme_show_message(0, "cdw11 : %08x", cfg.cdw11);
279 nvme_show_result("cdw12 : %08x", cfg.cdw12)nvme_show_message(0, "cdw12 : %08x", cfg.cdw12);
280 nvme_show_result("cdw13 : %08x", cfg.cdw13)nvme_show_message(0, "cdw13 : %08x", cfg.cdw13);
281 nvme_show_result("cdw14 : %08x", cfg.cdw14)nvme_show_message(0, "cdw14 : %08x", cfg.cdw14);
282 nvme_show_result("cdw15 : %08x", cfg.cdw15)nvme_show_message(0, "cdw15 : %08x", cfg.cdw15);
283 nvme_show_result("timeout_ms : %08x", nvme_args.timeout)nvme_show_message(0, "timeout_ms : %08x", nvme_args.timeout
)
;
284 }
285 if (nvme_args.dry_run)
286 return 0;
287
288 gettimeofday(&start_time, NULL((void*)0));
289
290 struct libnvme_passthru_cmd cmd = {
291 .opcode = cfg.opcode,
292 .flags = cfg.flags,
293 .nsid = cfg.namespace_id,
294 .cdw2 = cfg.cdw2,
295 .cdw3 = cfg.cdw3,
296 .metadata = (__u64)(uintptr_t)mdata,
297 .addr = (__u64)(uintptr_t)data,
298 .metadata_len = cfg.metadata_len,
299 .data_len = cfg.data_len,
300 .cdw10 = cfg.cdw10,
301 .cdw11 = cfg.cdw11,
302 .cdw12 = cfg.cdw12,
303 .cdw13 = cfg.cdw13,
304 .cdw14 = cfg.cdw14,
305 .cdw15 = cfg.cdw15,
306 .timeout_ms = nvme_args.timeout,
307 };
308 if (admin)
309 err = libnvme_exec_admin_passthru(hdl, &cmd);
310 else
311 err = libnvme_exec_io_passthru(hdl, &cmd);
312
313 gettimeofday(&end_time, NULL((void*)0));
314 cmd_name = nvme_cmd_to_string(admin, cfg.opcode);
315 if (cfg.latency)
316 nvme_show_result("%s Command %s latency: %llu us", admin ? "Admin" : "IO",nvme_show_message(0, "%s Command %s latency: %llu us", admin ?
"Admin" : "IO", strcmp(cmd_name, "Unknown") ? cmd_name : "Vendor Specific"
, shr_elapsed_utime(start_time, end_time))
317 strcmp(cmd_name, "Unknown") ? cmd_name : "Vendor Specific",nvme_show_message(0, "%s Command %s latency: %llu us", admin ?
"Admin" : "IO", strcmp(cmd_name, "Unknown") ? cmd_name : "Vendor Specific"
, shr_elapsed_utime(start_time, end_time))
318 shr_elapsed_utime(start_time, end_time))nvme_show_message(0, "%s Command %s latency: %llu us", admin ?
"Admin" : "IO", strcmp(cmd_name, "Unknown") ? cmd_name : "Vendor Specific"
, shr_elapsed_utime(start_time, end_time))
;
319
320 if (err) {
321 nvme_show_err(err, __func__);
322 return err;
323 }
324
325 nvme_show_verbose_result("%s Command %s is Success and result: 0x%" PRIx64,nvme_show_verbose_message("%s Command %s is Success and result: 0x%"
"l" "x", admin ? "Admin" : "IO", strcmp(cmd_name, "Unknown")
? cmd_name : "Vendor Specific", (uint64_t)cmd.result)
326 admin ? "Admin" : "IO",nvme_show_verbose_message("%s Command %s is Success and result: 0x%"
"l" "x", admin ? "Admin" : "IO", strcmp(cmd_name, "Unknown")
? cmd_name : "Vendor Specific", (uint64_t)cmd.result)
327 strcmp(cmd_name, "Unknown") ?nvme_show_verbose_message("%s Command %s is Success and result: 0x%"
"l" "x", admin ? "Admin" : "IO", strcmp(cmd_name, "Unknown")
? cmd_name : "Vendor Specific", (uint64_t)cmd.result)
328 cmd_name : "Vendor Specific", (uint64_t)cmd.result)nvme_show_verbose_message("%s Command %s is Success and result: 0x%"
"l" "x", admin ? "Admin" : "IO", strcmp(cmd_name, "Unknown")
? cmd_name : "Vendor Specific", (uint64_t)cmd.result)
;
329 if (cfg.read)
330 passthru_print_read_output(cfg, data, dfd, mdata, mfd, err);
331
332 return err;
333}
334
335static int io_passthru(int argc, char **argv, struct command *acmd, struct plugin *plugin)
336{
337 const char *desc =
338 "Send a user-defined IO command to the specified device via IOCTL passthrough, return results.";
339
340 return passthru(argc, argv, false0, desc, acmd);
341}
342
343static int admin_passthru(int argc, char **argv, struct command *acmd, struct plugin *plugin)
344{
345 const char *desc =
346 "Send a user-defined Admin command to the specified device via IOCTL passthrough, return results.";
347
348 return passthru(argc, argv, true1, desc, acmd);
1
Calling 'passthru'
349}
350
351static struct command admin_passthru_cmd = {
352 .name = "admin-passthru",
353 .help = "Submit an arbitrary admin command, return results",
354 .fn = admin_passthru,
355};
356
357static struct command io_passthru_cmd = {
358 .name = "io-passthru",
359 .help = "Submit an arbitrary IO command, return results",
360 .fn = io_passthru,
361};
362
363static struct command *commands[] = {
364 &admin_passthru_cmd,
365 &io_passthru_cmd,
366 NULL((void*)0),
367};
368
369static void __shr_constructor__attribute__((constructor)) register_group(void)
370{
371 plugin_add_group(&builtin, "Passthrough", commands);
372}