Bug Summary

File:.build-ci/../libnvme/src/nvme/attr-accessors-custom-linux.c
Warning:line 123, column 9
Potential leak of memory pointed to by 'target_addr'

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 attr-accessors-custom-linux.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 -fhalf-no-semantic-interposition -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 libnvme/src/libnvme3.so.1.0.0.p -I libnvme/src -I ../libnvme/src -I ccan -I ../ccan -I . -I .. -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 -fvisibility=hidden -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-09-23-073103-589-1 -x c ../libnvme/src/nvme/attr-accessors-custom-linux.c

../libnvme/src/nvme/generated/attr-accessors.c

1// SPDX-License-Identifier: LGPL-2.1-or-later
2
3/*
4 * This file is part of libnvme.
5 *
6 * Copyright (c) 2025, Dell Technologies Inc. or its subsidiaries.
7 * Authors: Martin Belanger <Martin.Belanger@dell.com>
8 *
9 * ____ _ _ ____ _
10 * / ___| ___ _ __ ___ _ __ __ _| |_ ___ __| | / ___|___ __| | ___
11 * | | _ / _ \ '_ \ / _ \ '__/ _` | __/ _ \/ _` | | | / _ \ / _` |/ _ \
12 * | |_| | __/ | | | __/ | | (_| | || __/ (_| | | |__| (_) | (_| | __/
13 * \____|\___|_| |_|\___|_| \__,_|\__\___|\__,_| \____\___/ \__,_|\___|
14 *
15 * Auto-generated struct member accessors (setter/getter)
16 *
17 * To update run: meson compile -C [BUILD-DIR] update-accessors
18 * Or: make update-accessors
19 */
20
21#include <errno(*__errno_location ()).h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <shared/compiler-attributes-util.h>
27
28#include "../private.h"
29#include "../private-tree.h"
30#include "attr-accessors.h"
31
32struct libnvme_ctrl_attrs {
33 char *numa_node;
34 char *queue_count;
35 char *sqsize;
36 long command_error_count;
37 long reset_count;
38 long reconnect_count;
39 char *firmware;
40 char *model;
41 char *serial;
42 char *cntrltype;
43 char *cntlid;
44 char *dctype;
45 char *phy_slot;
46 char *kxchap_host_key;
47 char *kxchap_ctrl_key;
48 char *keyring;
49};
50
51struct libnvme_ctrl_attrs *libnvme_ctrl_attrs_alloc(void)
52{
53 return calloc(1, sizeof(struct libnvme_ctrl_attrs));
54}
55
56void libnvme_ctrl_attrs_reset(
57 struct libnvme_ctrl_attrs *attrs)
58{
59 if (!attrs)
60 return;
61
62 ATTR_FREE(attrs->numa_node)do { if ((attrs->numa_node) != ((void*)0) && !((void
*)(attrs->numa_node) == (void *)NO_ATTR)) free(attrs->
numa_node); (attrs->numa_node) = ((void*)0); } while (0)
;
63 ATTR_FREE(attrs->queue_count)do { if ((attrs->queue_count) != ((void*)0) && !((
void *)(attrs->queue_count) == (void *)NO_ATTR)) free(attrs
->queue_count); (attrs->queue_count) = ((void*)0); } while
(0)
;
64 ATTR_FREE(attrs->sqsize)do { if ((attrs->sqsize) != ((void*)0) && !((void *
)(attrs->sqsize) == (void *)NO_ATTR)) free(attrs->sqsize
); (attrs->sqsize) = ((void*)0); } while (0)
;
65 ATTR_FREE(attrs->firmware)do { if ((attrs->firmware) != ((void*)0) && !((void
*)(attrs->firmware) == (void *)NO_ATTR)) free(attrs->firmware
); (attrs->firmware) = ((void*)0); } while (0)
;
66 ATTR_FREE(attrs->model)do { if ((attrs->model) != ((void*)0) && !((void *
)(attrs->model) == (void *)NO_ATTR)) free(attrs->model)
; (attrs->model) = ((void*)0); } while (0)
;
67 ATTR_FREE(attrs->serial)do { if ((attrs->serial) != ((void*)0) && !((void *
)(attrs->serial) == (void *)NO_ATTR)) free(attrs->serial
); (attrs->serial) = ((void*)0); } while (0)
;
68 ATTR_FREE(attrs->cntrltype)do { if ((attrs->cntrltype) != ((void*)0) && !((void
*)(attrs->cntrltype) == (void *)NO_ATTR)) free(attrs->
cntrltype); (attrs->cntrltype) = ((void*)0); } while (0)
;
69 ATTR_FREE(attrs->cntlid)do { if ((attrs->cntlid) != ((void*)0) && !((void *
)(attrs->cntlid) == (void *)NO_ATTR)) free(attrs->cntlid
); (attrs->cntlid) = ((void*)0); } while (0)
;
70 ATTR_FREE(attrs->dctype)do { if ((attrs->dctype) != ((void*)0) && !((void *
)(attrs->dctype) == (void *)NO_ATTR)) free(attrs->dctype
); (attrs->dctype) = ((void*)0); } while (0)
;
71 ATTR_FREE(attrs->phy_slot)do { if ((attrs->phy_slot) != ((void*)0) && !((void
*)(attrs->phy_slot) == (void *)NO_ATTR)) free(attrs->phy_slot
); (attrs->phy_slot) = ((void*)0); } while (0)
;
72 ATTR_FREE(attrs->kxchap_host_key)do { if ((attrs->kxchap_host_key) != ((void*)0) &&
!((void *)(attrs->kxchap_host_key) == (void *)NO_ATTR)) free
(attrs->kxchap_host_key); (attrs->kxchap_host_key) = ((
void*)0); } while (0)
;
73 ATTR_FREE(attrs->kxchap_ctrl_key)do { if ((attrs->kxchap_ctrl_key) != ((void*)0) &&
!((void *)(attrs->kxchap_ctrl_key) == (void *)NO_ATTR)) free
(attrs->kxchap_ctrl_key); (attrs->kxchap_ctrl_key) = ((
void*)0); } while (0)
;
74 ATTR_FREE(attrs->keyring)do { if ((attrs->keyring) != ((void*)0) && !((void
*)(attrs->keyring) == (void *)NO_ATTR)) free(attrs->keyring
); (attrs->keyring) = ((void*)0); } while (0)
;
75}
76
77void libnvme_ctrl_attrs_free(
78 struct libnvme_ctrl_attrs *attrs)
79{
80 if (!attrs)
81 return;
82
83 free(attrs);
84}
85
86__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_numa_node(
87 const struct libnvme_ctrl *p,
88 const char **val,
89 const char *dflt)
90{
91 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
92
93 *val = dflt;
94
95 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->numa_node))__builtin_expect(!!(!((c->attrs->numa_node) != ((void*)
0))), 0)
) {
96 c->attrs->numa_node = libnvme_get_ctrl_attr(c, "numa_node");
97 if (!c->attrs->numa_node)
98 c->attrs->numa_node = NO_ATTR;
99 }
100
101 if (ATTR_IS_ABSENT(c->attrs->numa_node)((void *)(c->attrs->numa_node) == (void *)NO_ATTR))
102 return -ENOENT2;
103
104 *val = c->attrs->numa_node;
105 return 0;
106}
107
108__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_queue_count(
109 const struct libnvme_ctrl *p,
110 const char **val,
111 const char *dflt)
112{
113 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
114
115 *val = dflt;
116
117 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->queue_count))__builtin_expect(!!(!((c->attrs->queue_count) != ((void
*)0))), 0)
) {
118 c->attrs->queue_count = libnvme_get_ctrl_attr(c, "queue_count");
119 if (!c->attrs->queue_count)
120 c->attrs->queue_count = NO_ATTR;
121 }
122
123 if (ATTR_IS_ABSENT(c->attrs->queue_count)((void *)(c->attrs->queue_count) == (void *)NO_ATTR))
124 return -ENOENT2;
125
126 *val = c->attrs->queue_count;
127 return 0;
128}
129
130__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_sqsize(
131 const struct libnvme_ctrl *p,
132 const char **val,
133 const char *dflt)
134{
135 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
136
137 *val = dflt;
138
139 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->sqsize))__builtin_expect(!!(!((c->attrs->sqsize) != ((void*)0))
), 0)
) {
140 c->attrs->sqsize = libnvme_get_ctrl_attr(c, "sqsize");
141 if (!c->attrs->sqsize)
142 c->attrs->sqsize = NO_ATTR;
143 }
144
145 if (ATTR_IS_ABSENT(c->attrs->sqsize)((void *)(c->attrs->sqsize) == (void *)NO_ATTR))
146 return -ENOENT2;
147
148 *val = c->attrs->sqsize;
149 return 0;
150}
151
152__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_command_error_count(
153 const struct libnvme_ctrl *p,
154 long *val,
155 long dflt)
156{
157 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
158 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
159
160 *val = dflt;
161
162 str = libnvme_get_ctrl_attr(c, "diag/command_error_count");
163 if (!str)
164 return -ENOENT2;
165
166 if (sscanf(str, "%ld", &c->attrs->command_error_count) != 1)
167 return -EINVAL22;
168
169 *val = c->attrs->command_error_count;
170 return 0;
171}
172
173__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_reset_count(
174 const struct libnvme_ctrl *p,
175 long *val,
176 long dflt)
177{
178 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
179 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
180
181 *val = dflt;
182
183 str = libnvme_get_ctrl_attr(c, "diag/reset_count");
184 if (!str)
185 return -ENOENT2;
186
187 if (sscanf(str, "%ld", &c->attrs->reset_count) != 1)
188 return -EINVAL22;
189
190 *val = c->attrs->reset_count;
191 return 0;
192}
193
194__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_reconnect_count(
195 const struct libnvme_ctrl *p,
196 long *val,
197 long dflt)
198{
199 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
200 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
201
202 *val = dflt;
203
204 str = libnvme_get_ctrl_attr(c, "diag/reconnect_count");
205 if (!str)
206 return -ENOENT2;
207
208 if (sscanf(str, "%ld", &c->attrs->reconnect_count) != 1)
209 return -EINVAL22;
210
211 *val = c->attrs->reconnect_count;
212 return 0;
213}
214
215__shr_public__attribute__((visibility("default"))) void libnvme_ctrl_set_firmware(
216 struct libnvme_ctrl *p,
217 const char *firmware)
218{
219 ATTR_FREE(p->attrs->firmware)do { if ((p->attrs->firmware) != ((void*)0) && !
((void *)(p->attrs->firmware) == (void *)NO_ATTR)) free
(p->attrs->firmware); (p->attrs->firmware) = ((void
*)0); } while (0)
;
220 p->attrs->firmware = firmware ? strdup(firmware) : NO_ATTR;
221}
222
223__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_firmware(
224 const struct libnvme_ctrl *p,
225 const char **val,
226 const char *dflt)
227{
228 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
229 int ret;
230
231 *val = dflt;
232
233 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->firmware))__builtin_expect(!!(!((c->attrs->firmware) != ((void*)0
))), 0)
) {
234 ret = libnvme_ctrl_load_identity(c);
235 if (ret)
236 return ret;
237 if (!c->attrs->firmware)
238 c->attrs->firmware = NO_ATTR;
239 }
240
241 if (ATTR_IS_ABSENT(c->attrs->firmware)((void *)(c->attrs->firmware) == (void *)NO_ATTR))
242 return -ENOENT2;
243
244 *val = c->attrs->firmware;
245 return 0;
246}
247
248__shr_public__attribute__((visibility("default"))) void libnvme_ctrl_set_model(
249 struct libnvme_ctrl *p,
250 const char *model)
251{
252 ATTR_FREE(p->attrs->model)do { if ((p->attrs->model) != ((void*)0) && !((
void *)(p->attrs->model) == (void *)NO_ATTR)) free(p->
attrs->model); (p->attrs->model) = ((void*)0); } while
(0)
;
253 p->attrs->model = model ? strdup(model) : NO_ATTR;
254}
255
256__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_model(
257 const struct libnvme_ctrl *p,
258 const char **val,
259 const char *dflt)
260{
261 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
262 int ret;
263
264 *val = dflt;
265
266 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->model))__builtin_expect(!!(!((c->attrs->model) != ((void*)0)))
, 0)
) {
267 ret = libnvme_ctrl_load_identity(c);
268 if (ret)
269 return ret;
270 if (!c->attrs->model)
271 c->attrs->model = NO_ATTR;
272 }
273
274 if (ATTR_IS_ABSENT(c->attrs->model)((void *)(c->attrs->model) == (void *)NO_ATTR))
275 return -ENOENT2;
276
277 *val = c->attrs->model;
278 return 0;
279}
280
281__shr_public__attribute__((visibility("default"))) void libnvme_ctrl_set_serial(
282 struct libnvme_ctrl *p,
283 const char *serial)
284{
285 ATTR_FREE(p->attrs->serial)do { if ((p->attrs->serial) != ((void*)0) && !(
(void *)(p->attrs->serial) == (void *)NO_ATTR)) free(p->
attrs->serial); (p->attrs->serial) = ((void*)0); } while
(0)
;
286 p->attrs->serial = serial ? strdup(serial) : NO_ATTR;
287}
288
289__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_serial(
290 const struct libnvme_ctrl *p,
291 const char **val,
292 const char *dflt)
293{
294 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
295 int ret;
296
297 *val = dflt;
298
299 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->serial))__builtin_expect(!!(!((c->attrs->serial) != ((void*)0))
), 0)
) {
300 ret = libnvme_ctrl_load_identity(c);
301 if (ret)
302 return ret;
303 if (!c->attrs->serial)
304 c->attrs->serial = NO_ATTR;
305 }
306
307 if (ATTR_IS_ABSENT(c->attrs->serial)((void *)(c->attrs->serial) == (void *)NO_ATTR))
308 return -ENOENT2;
309
310 *val = c->attrs->serial;
311 return 0;
312}
313
314__shr_public__attribute__((visibility("default"))) void libnvme_ctrl_set_cntrltype(
315 struct libnvme_ctrl *p,
316 const char *cntrltype)
317{
318 ATTR_FREE(p->attrs->cntrltype)do { if ((p->attrs->cntrltype) != ((void*)0) &&
!((void *)(p->attrs->cntrltype) == (void *)NO_ATTR)) free
(p->attrs->cntrltype); (p->attrs->cntrltype) = ((
void*)0); } while (0)
;
319 p->attrs->cntrltype = cntrltype ? strdup(cntrltype) : NO_ATTR;
320}
321
322__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_cntrltype(
323 const struct libnvme_ctrl *p,
324 const char **val,
325 const char *dflt)
326{
327 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
328 int ret;
329
330 *val = dflt;
331
332 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->cntrltype))__builtin_expect(!!(!((c->attrs->cntrltype) != ((void*)
0))), 0)
) {
333 ret = libnvme_ctrl_load_identity(c);
334 if (ret)
335 return ret;
336 if (!c->attrs->cntrltype)
337 c->attrs->cntrltype = NO_ATTR;
338 }
339
340 if (ATTR_IS_ABSENT(c->attrs->cntrltype)((void *)(c->attrs->cntrltype) == (void *)NO_ATTR))
341 return -ENOENT2;
342
343 *val = c->attrs->cntrltype;
344 return 0;
345}
346
347__shr_public__attribute__((visibility("default"))) void libnvme_ctrl_set_cntlid(
348 struct libnvme_ctrl *p,
349 const char *cntlid)
350{
351 ATTR_FREE(p->attrs->cntlid)do { if ((p->attrs->cntlid) != ((void*)0) && !(
(void *)(p->attrs->cntlid) == (void *)NO_ATTR)) free(p->
attrs->cntlid); (p->attrs->cntlid) = ((void*)0); } while
(0)
;
352 p->attrs->cntlid = cntlid ? strdup(cntlid) : NO_ATTR;
353}
354
355__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_cntlid(
356 const struct libnvme_ctrl *p,
357 const char **val,
358 const char *dflt)
359{
360 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
361 int ret;
362
363 *val = dflt;
364
365 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->cntlid))__builtin_expect(!!(!((c->attrs->cntlid) != ((void*)0))
), 0)
) {
366 ret = libnvme_ctrl_load_identity(c);
367 if (ret)
368 return ret;
369 if (!c->attrs->cntlid)
370 c->attrs->cntlid = NO_ATTR;
371 }
372
373 if (ATTR_IS_ABSENT(c->attrs->cntlid)((void *)(c->attrs->cntlid) == (void *)NO_ATTR))
374 return -ENOENT2;
375
376 *val = c->attrs->cntlid;
377 return 0;
378}
379
380__shr_public__attribute__((visibility("default"))) void libnvme_ctrl_set_dctype(
381 struct libnvme_ctrl *p,
382 const char *dctype)
383{
384 ATTR_FREE(p->attrs->dctype)do { if ((p->attrs->dctype) != ((void*)0) && !(
(void *)(p->attrs->dctype) == (void *)NO_ATTR)) free(p->
attrs->dctype); (p->attrs->dctype) = ((void*)0); } while
(0)
;
385 p->attrs->dctype = dctype ? strdup(dctype) : NO_ATTR;
386}
387
388__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_dctype(
389 const struct libnvme_ctrl *p,
390 const char **val,
391 const char *dflt)
392{
393 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
394 int ret;
395
396 *val = dflt;
397
398 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->dctype))__builtin_expect(!!(!((c->attrs->dctype) != ((void*)0))
), 0)
) {
399 ret = libnvme_ctrl_load_identity(c);
400 if (ret)
401 return ret;
402 if (!c->attrs->dctype)
403 c->attrs->dctype = NO_ATTR;
404 }
405
406 if (ATTR_IS_ABSENT(c->attrs->dctype)((void *)(c->attrs->dctype) == (void *)NO_ATTR))
407 return -ENOENT2;
408
409 *val = c->attrs->dctype;
410 return 0;
411}
412
413__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_phy_slot(
414 const struct libnvme_ctrl *p,
415 const char **val,
416 const char *dflt)
417{
418 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
419 int ret;
420
421 *val = dflt;
422
423 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->phy_slot))__builtin_expect(!!(!((c->attrs->phy_slot) != ((void*)0
))), 0)
) {
1
Assuming field 'phy_slot' is equal to null
2
Taking true branch
424 ret = libnvme_ctrl_load_phy_slot(c);
3
Calling 'libnvme_ctrl_load_phy_slot'
425 if (ret)
426 return ret;
427 if (!c->attrs->phy_slot)
428 c->attrs->phy_slot = NO_ATTR;
429 }
430
431 if (ATTR_IS_ABSENT(c->attrs->phy_slot)((void *)(c->attrs->phy_slot) == (void *)NO_ATTR))
432 return -ENOENT2;
433
434 *val = c->attrs->phy_slot;
435 return 0;
436}
437
438__shr_public__attribute__((visibility("default"))) void libnvme_ctrl_set_kxchap_host_key(
439 struct libnvme_ctrl *p,
440 const char *kxchap_host_key)
441{
442 ATTR_FREE(p->attrs->kxchap_host_key)do { if ((p->attrs->kxchap_host_key) != ((void*)0) &&
!((void *)(p->attrs->kxchap_host_key) == (void *)NO_ATTR
)) free(p->attrs->kxchap_host_key); (p->attrs->kxchap_host_key
) = ((void*)0); } while (0)
;
443 p->attrs->kxchap_host_key =
444 kxchap_host_key ? strdup(kxchap_host_key) : NO_ATTR;
445}
446
447__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_kxchap_host_key(
448 const struct libnvme_ctrl *p,
449 const char **val,
450 const char *dflt)
451{
452 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
453 int ret;
454
455 *val = dflt;
456
457 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->kxchap_host_key))__builtin_expect(!!(!((c->attrs->kxchap_host_key) != ((
void*)0))), 0)
) {
458 ret = libnvmf_ctrl_load_fabrics_attrs(c);
459 if (ret)
460 return ret;
461 if (!c->attrs->kxchap_host_key)
462 c->attrs->kxchap_host_key = NO_ATTR;
463 }
464
465 if (ATTR_IS_ABSENT(c->attrs->kxchap_host_key)((void *)(c->attrs->kxchap_host_key) == (void *)NO_ATTR
)
)
466 return -ENOENT2;
467
468 *val = c->attrs->kxchap_host_key;
469 return 0;
470}
471
472__shr_public__attribute__((visibility("default"))) void libnvme_ctrl_set_kxchap_ctrl_key(
473 struct libnvme_ctrl *p,
474 const char *kxchap_ctrl_key)
475{
476 ATTR_FREE(p->attrs->kxchap_ctrl_key)do { if ((p->attrs->kxchap_ctrl_key) != ((void*)0) &&
!((void *)(p->attrs->kxchap_ctrl_key) == (void *)NO_ATTR
)) free(p->attrs->kxchap_ctrl_key); (p->attrs->kxchap_ctrl_key
) = ((void*)0); } while (0)
;
477 p->attrs->kxchap_ctrl_key =
478 kxchap_ctrl_key ? strdup(kxchap_ctrl_key) : NO_ATTR;
479}
480
481__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_kxchap_ctrl_key(
482 const struct libnvme_ctrl *p,
483 const char **val,
484 const char *dflt)
485{
486 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
487 int ret;
488
489 *val = dflt;
490
491 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->kxchap_ctrl_key))__builtin_expect(!!(!((c->attrs->kxchap_ctrl_key) != ((
void*)0))), 0)
) {
492 ret = libnvmf_ctrl_load_fabrics_attrs(c);
493 if (ret)
494 return ret;
495 if (!c->attrs->kxchap_ctrl_key)
496 c->attrs->kxchap_ctrl_key = NO_ATTR;
497 }
498
499 if (ATTR_IS_ABSENT(c->attrs->kxchap_ctrl_key)((void *)(c->attrs->kxchap_ctrl_key) == (void *)NO_ATTR
)
)
500 return -ENOENT2;
501
502 *val = c->attrs->kxchap_ctrl_key;
503 return 0;
504}
505
506__shr_public__attribute__((visibility("default"))) void libnvme_ctrl_set_keyring(
507 struct libnvme_ctrl *p,
508 const char *keyring)
509{
510 ATTR_FREE(p->attrs->keyring)do { if ((p->attrs->keyring) != ((void*)0) && !
((void *)(p->attrs->keyring) == (void *)NO_ATTR)) free(
p->attrs->keyring); (p->attrs->keyring) = ((void*
)0); } while (0)
;
511 p->attrs->keyring = keyring ? strdup(keyring) : NO_ATTR;
512}
513
514__shr_public__attribute__((visibility("default"))) int libnvme_ctrl_get_keyring(
515 const struct libnvme_ctrl *p,
516 const char **val,
517 const char *dflt)
518{
519 struct libnvme_ctrl *c = (struct libnvme_ctrl *)p;
520 int ret;
521
522 *val = dflt;
523
524 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->keyring))__builtin_expect(!!(!((c->attrs->keyring) != ((void*)0)
)), 0)
) {
525 ret = libnvmf_ctrl_load_fabrics_attrs(c);
526 if (ret)
527 return ret;
528 if (!c->attrs->keyring)
529 c->attrs->keyring = NO_ATTR;
530 }
531
532 if (ATTR_IS_ABSENT(c->attrs->keyring)((void *)(c->attrs->keyring) == (void *)NO_ATTR))
533 return -ENOENT2;
534
535 *val = c->attrs->keyring;
536 return 0;
537}
538
539struct libnvme_path_attrs {
540 char *ana_state;
541 char *numa_nodes;
542 int *grpid;
543 int queue_depth;
544 long multipath_failover_count;
545 long command_retry_count;
546 long command_error_count;
547};
548
549struct libnvme_path_attrs *libnvme_path_attrs_alloc(void)
550{
551 return calloc(1, sizeof(struct libnvme_path_attrs));
552}
553
554void libnvme_path_attrs_reset(
555 struct libnvme_path_attrs *attrs)
556{
557 if (!attrs)
558 return;
559
560}
561
562void libnvme_path_attrs_free(
563 struct libnvme_path_attrs *attrs)
564{
565 if (!attrs)
566 return;
567
568 ATTR_FREE(attrs->ana_state)do { if ((attrs->ana_state) != ((void*)0) && !((void
*)(attrs->ana_state) == (void *)NO_ATTR)) free(attrs->
ana_state); (attrs->ana_state) = ((void*)0); } while (0)
;
569 ATTR_FREE(attrs->numa_nodes)do { if ((attrs->numa_nodes) != ((void*)0) && !((void
*)(attrs->numa_nodes) == (void *)NO_ATTR)) free(attrs->
numa_nodes); (attrs->numa_nodes) = ((void*)0); } while (0)
;
570 ATTR_FREE(attrs->grpid)do { if ((attrs->grpid) != ((void*)0) && !((void *
)(attrs->grpid) == (void *)NO_ATTR)) free(attrs->grpid)
; (attrs->grpid) = ((void*)0); } while (0)
;
571 free(attrs);
572}
573
574struct libnvme_ns_attrs {
575 int *lba_size;
576 int *lba_shift;
577 uint64_t *lba_count;
578 uint64_t *lba_util;
579 int *meta_size;
580 enum nvme_csi *csi;
581 uint8_t *eui64;
582 uint8_t *nguid;
583 unsigned char *uuid;
584 long command_retry_count;
585 long command_error_count;
586 long io_requeue_no_usable_path_count;
587 long io_fail_no_available_path_count;
588};
589
590struct libnvme_ns_attrs *libnvme_ns_attrs_alloc(void)
591{
592 return calloc(1, sizeof(struct libnvme_ns_attrs));
593}
594
595void libnvme_ns_attrs_reset(
596 struct libnvme_ns_attrs *attrs)
597{
598 if (!attrs)
599 return;
600
601}
602
603void libnvme_ns_attrs_free(
604 struct libnvme_ns_attrs *attrs)
605{
606 if (!attrs)
607 return;
608
609 ATTR_FREE(attrs->lba_size)do { if ((attrs->lba_size) != ((void*)0) && !((void
*)(attrs->lba_size) == (void *)NO_ATTR)) free(attrs->lba_size
); (attrs->lba_size) = ((void*)0); } while (0)
;
610 ATTR_FREE(attrs->lba_shift)do { if ((attrs->lba_shift) != ((void*)0) && !((void
*)(attrs->lba_shift) == (void *)NO_ATTR)) free(attrs->
lba_shift); (attrs->lba_shift) = ((void*)0); } while (0)
;
611 ATTR_FREE(attrs->lba_count)do { if ((attrs->lba_count) != ((void*)0) && !((void
*)(attrs->lba_count) == (void *)NO_ATTR)) free(attrs->
lba_count); (attrs->lba_count) = ((void*)0); } while (0)
;
612 ATTR_FREE(attrs->lba_util)do { if ((attrs->lba_util) != ((void*)0) && !((void
*)(attrs->lba_util) == (void *)NO_ATTR)) free(attrs->lba_util
); (attrs->lba_util) = ((void*)0); } while (0)
;
613 ATTR_FREE(attrs->meta_size)do { if ((attrs->meta_size) != ((void*)0) && !((void
*)(attrs->meta_size) == (void *)NO_ATTR)) free(attrs->
meta_size); (attrs->meta_size) = ((void*)0); } while (0)
;
614 ATTR_FREE(attrs->csi)do { if ((attrs->csi) != ((void*)0) && !((void *)(
attrs->csi) == (void *)NO_ATTR)) free(attrs->csi); (attrs
->csi) = ((void*)0); } while (0)
;
615 ATTR_FREE(attrs->eui64)do { if ((attrs->eui64) != ((void*)0) && !((void *
)(attrs->eui64) == (void *)NO_ATTR)) free(attrs->eui64)
; (attrs->eui64) = ((void*)0); } while (0)
;
616 ATTR_FREE(attrs->nguid)do { if ((attrs->nguid) != ((void*)0) && !((void *
)(attrs->nguid) == (void *)NO_ATTR)) free(attrs->nguid)
; (attrs->nguid) = ((void*)0); } while (0)
;
617 ATTR_FREE(attrs->uuid)do { if ((attrs->uuid) != ((void*)0) && !((void *)
(attrs->uuid) == (void *)NO_ATTR)) free(attrs->uuid); (
attrs->uuid) = ((void*)0); } while (0)
;
618 free(attrs);
619}
620
621__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_command_retry_count(
622 const struct libnvme_ns *p,
623 long *val,
624 long dflt)
625{
626 struct libnvme_ns *c = (struct libnvme_ns *)p;
627 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
628
629 *val = dflt;
630
631 str = libnvme_get_ns_attr(c, "diag/command_retry_count");
632 if (!str)
633 return -ENOENT2;
634
635 if (sscanf(str, "%ld", &c->attrs->command_retry_count) != 1)
636 return -EINVAL22;
637
638 *val = c->attrs->command_retry_count;
639 return 0;
640}
641
642__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_command_error_count(
643 const struct libnvme_ns *p,
644 long *val,
645 long dflt)
646{
647 struct libnvme_ns *c = (struct libnvme_ns *)p;
648 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
649
650 *val = dflt;
651
652 str = libnvme_get_ns_attr(c, "diag/command_error_count");
653 if (!str)
654 return -ENOENT2;
655
656 if (sscanf(str, "%ld", &c->attrs->command_error_count) != 1)
657 return -EINVAL22;
658
659 *val = c->attrs->command_error_count;
660 return 0;
661}
662
663__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_io_requeue_no_usable_path_count(
664 const struct libnvme_ns *p,
665 long *val,
666 long dflt)
667{
668 struct libnvme_ns *c = (struct libnvme_ns *)p;
669 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
670
671 *val = dflt;
672
673 str = libnvme_get_ns_attr(c, "diag/io_requeue_no_usable_path_count");
674 if (!str)
675 return -ENOENT2;
676
677 if (sscanf(str, "%ld", &c->attrs->io_requeue_no_usable_path_count) != 1)
678 return -EINVAL22;
679
680 *val = c->attrs->io_requeue_no_usable_path_count;
681 return 0;
682}
683
684__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_io_fail_no_available_path_count(
685 const struct libnvme_ns *p,
686 long *val,
687 long dflt)
688{
689 struct libnvme_ns *c = (struct libnvme_ns *)p;
690 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
691
692 *val = dflt;
693
694 str = libnvme_get_ns_attr(c, "diag/io_fail_no_available_path_count");
695 if (!str)
696 return -ENOENT2;
697
698 if (sscanf(str, "%ld", &c->attrs->io_fail_no_available_path_count) != 1)
699 return -EINVAL22;
700
701 *val = c->attrs->io_fail_no_available_path_count;
702 return 0;
703}
704
705struct libnvme_subsystem_attrs {
706 char *model;
707 char *serial;
708 char *firmware;
709 char *iopolicy;
710};
711
712struct libnvme_subsystem_attrs *libnvme_subsystem_attrs_alloc(void)
713{
714 return calloc(1, sizeof(struct libnvme_subsystem_attrs));
715}
716
717void libnvme_subsystem_attrs_reset(
718 struct libnvme_subsystem_attrs *attrs)
719{
720 if (!attrs)
721 return;
722
723}
724
725void libnvme_subsystem_attrs_free(
726 struct libnvme_subsystem_attrs *attrs)
727{
728 if (!attrs)
729 return;
730
731 ATTR_FREE(attrs->model)do { if ((attrs->model) != ((void*)0) && !((void *
)(attrs->model) == (void *)NO_ATTR)) free(attrs->model)
; (attrs->model) = ((void*)0); } while (0)
;
732 ATTR_FREE(attrs->serial)do { if ((attrs->serial) != ((void*)0) && !((void *
)(attrs->serial) == (void *)NO_ATTR)) free(attrs->serial
); (attrs->serial) = ((void*)0); } while (0)
;
733 ATTR_FREE(attrs->firmware)do { if ((attrs->firmware) != ((void*)0) && !((void
*)(attrs->firmware) == (void *)NO_ATTR)) free(attrs->firmware
); (attrs->firmware) = ((void*)0); } while (0)
;
734 ATTR_FREE(attrs->iopolicy)do { if ((attrs->iopolicy) != ((void*)0) && !((void
*)(attrs->iopolicy) == (void *)NO_ATTR)) free(attrs->iopolicy
); (attrs->iopolicy) = ((void*)0); } while (0)
;
735 free(attrs);
736}
737
738__shr_public__attribute__((visibility("default"))) void libnvme_subsystem_set_model(
739 struct libnvme_subsystem *p,
740 const char *model)
741{
742 ATTR_FREE(p->attrs->model)do { if ((p->attrs->model) != ((void*)0) && !((
void *)(p->attrs->model) == (void *)NO_ATTR)) free(p->
attrs->model); (p->attrs->model) = ((void*)0); } while
(0)
;
743 p->attrs->model = model ? strdup(model) : NO_ATTR;
744}
745
746__shr_public__attribute__((visibility("default"))) int libnvme_subsystem_get_model(
747 const struct libnvme_subsystem *p,
748 const char **val,
749 const char *dflt)
750{
751 struct libnvme_subsystem *c = (struct libnvme_subsystem *)p;
752
753 *val = dflt;
754
755 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->model))__builtin_expect(!!(!((c->attrs->model) != ((void*)0)))
, 0)
) {
756 c->attrs->model = libnvme_get_subsys_attr(c, "model");
757 if (!c->attrs->model)
758 c->attrs->model = NO_ATTR;
759 }
760
761 if (ATTR_IS_ABSENT(c->attrs->model)((void *)(c->attrs->model) == (void *)NO_ATTR))
762 return -ENOENT2;
763
764 *val = c->attrs->model;
765 return 0;
766}
767
768__shr_public__attribute__((visibility("default"))) void libnvme_subsystem_set_serial(
769 struct libnvme_subsystem *p,
770 const char *serial)
771{
772 ATTR_FREE(p->attrs->serial)do { if ((p->attrs->serial) != ((void*)0) && !(
(void *)(p->attrs->serial) == (void *)NO_ATTR)) free(p->
attrs->serial); (p->attrs->serial) = ((void*)0); } while
(0)
;
773 p->attrs->serial = serial ? strdup(serial) : NO_ATTR;
774}
775
776__shr_public__attribute__((visibility("default"))) int libnvme_subsystem_get_serial(
777 const struct libnvme_subsystem *p,
778 const char **val,
779 const char *dflt)
780{
781 struct libnvme_subsystem *c = (struct libnvme_subsystem *)p;
782
783 *val = dflt;
784
785 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->serial))__builtin_expect(!!(!((c->attrs->serial) != ((void*)0))
), 0)
) {
786 c->attrs->serial = libnvme_get_subsys_attr(c, "serial");
787 if (!c->attrs->serial)
788 c->attrs->serial = NO_ATTR;
789 }
790
791 if (ATTR_IS_ABSENT(c->attrs->serial)((void *)(c->attrs->serial) == (void *)NO_ATTR))
792 return -ENOENT2;
793
794 *val = c->attrs->serial;
795 return 0;
796}
797
798__shr_public__attribute__((visibility("default"))) void libnvme_subsystem_set_firmware(
799 struct libnvme_subsystem *p,
800 const char *firmware)
801{
802 ATTR_FREE(p->attrs->firmware)do { if ((p->attrs->firmware) != ((void*)0) && !
((void *)(p->attrs->firmware) == (void *)NO_ATTR)) free
(p->attrs->firmware); (p->attrs->firmware) = ((void
*)0); } while (0)
;
803 p->attrs->firmware = firmware ? strdup(firmware) : NO_ATTR;
804}
805
806__shr_public__attribute__((visibility("default"))) int libnvme_subsystem_get_firmware(
807 const struct libnvme_subsystem *p,
808 const char **val,
809 const char *dflt)
810{
811 struct libnvme_subsystem *c = (struct libnvme_subsystem *)p;
812
813 *val = dflt;
814
815 if (__shr_unlikely(!ATTR_IS_LOADED(c->attrs->firmware))__builtin_expect(!!(!((c->attrs->firmware) != ((void*)0
))), 0)
) {
816 c->attrs->firmware = libnvme_get_subsys_attr(c, "firmware_rev");
817 if (!c->attrs->firmware)
818 c->attrs->firmware = NO_ATTR;
819 }
820
821 if (ATTR_IS_ABSENT(c->attrs->firmware)((void *)(c->attrs->firmware) == (void *)NO_ATTR))
822 return -ENOENT2;
823
824 *val = c->attrs->firmware;
825 return 0;
826}
827
828__shr_public__attribute__((visibility("default"))) int libnvme_subsystem_get_iopolicy(
829 const struct libnvme_subsystem *p,
830 const char **val,
831 const char *dflt)
832{
833 struct libnvme_subsystem *c = (struct libnvme_subsystem *)p;
834 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
835
836 *val = dflt;
837
838 str = libnvme_get_subsys_attr(c, "iopolicy");
839 if (!str)
840 return -ENOENT2;
841
842 if (!c->attrs->iopolicy || strcmp(str, c->attrs->iopolicy)) {
843 free(c->attrs->iopolicy);
844 c->attrs->iopolicy = strdup(str);
845 if (!c->attrs->iopolicy)
846 return -ENOMEM12;
847 }
848
849 *val = c->attrs->iopolicy;
850 return 0;
851}
852

../libnvme/src/nvme/attr-accessors-custom-linux.c

1// SPDX-License-Identifier: LGPL-2.1-or-later
2/*
3 * This file is part of libnvme.
4 * Copyright (c) 2026, Dell Technologies Inc. or its subsidiaries.
5 *
6 * Authors: Martin Belanger <Martin.Belanger@dell.com>
7 */
8
9#include <ccan/endian/endian.h>
10#include <ccan/ilog/ilog.h>
11#include <dirent.h>
12#include <errno(*__errno_location ()).h>
13
14#include "cleanup-linux.h"
15#include "lib.h"
16#include "mem.h"
17#include "util.h"
18
19#include "generated/attr-accessors.c"
20#include "generated/attr-accessors-linux.c"
21
22#ifdef CONFIG_FABRICS
23int libnvmf_ctrl_load_fabrics_attrs(struct libnvme_ctrl *c)
24{
25 __cleanup_free__attribute__((cleanup(shr_freep))) char *tls_key = NULL((void*)0);
26 char *host_key, *ctrl_key;
27
28 host_key = libnvme_get_ctrl_attr(c, "dhchap_secret");
29 if (host_key && !strcmp(host_key, "none")) {
30 free(host_key);
31 host_key = NULL((void*)0);
32 }
33 if (host_key) {
34 ATTR_FREE(c->attrs->kxchap_host_key)do { if ((c->attrs->kxchap_host_key) != ((void*)0) &&
!((void *)(c->attrs->kxchap_host_key) == (void *)NO_ATTR
)) free(c->attrs->kxchap_host_key); (c->attrs->kxchap_host_key
) = ((void*)0); } while (0)
;
35 c->attrs->kxchap_host_key = host_key;
36 }
37
38 ctrl_key = libnvme_get_ctrl_attr(c, "dhchap_ctrl_secret");
39 if (ctrl_key && !strcmp(ctrl_key, "none")) {
40 free(ctrl_key);
41 ctrl_key = NULL((void*)0);
42 }
43 if (ctrl_key) {
44 ATTR_FREE(c->attrs->kxchap_ctrl_key)do { if ((c->attrs->kxchap_ctrl_key) != ((void*)0) &&
!((void *)(c->attrs->kxchap_ctrl_key) == (void *)NO_ATTR
)) free(c->attrs->kxchap_ctrl_key); (c->attrs->kxchap_ctrl_key
) = ((void*)0); } while (0)
;
45 c->attrs->kxchap_ctrl_key = ctrl_key;
46 }
47
48 /*
49 * tls_key's presence gates keyring the same way it gates cfg's
50 * tls_key_id in tree-fabrics.c's libnvmf_read_sysfs_tls() -- read
51 * again here rather than threading state between the two, since
52 * cfg stays eager while this group is lazy.
53 */
54 tls_key = libnvme_get_ctrl_attr(c, "tls_key");
55 if (tls_key)
56 c->attrs->keyring = libnvme_get_ctrl_attr(c, "tls_keyring");
57
58 return 0;
59}
60#else
61int libnvmf_ctrl_load_fabrics_attrs(__shr_unused__attribute__((__unused__)) struct libnvme_ctrl *c)
62{
63 return 0;
64}
65#endif
66
67int libnvme_ctrl_load_identity(struct libnvme_ctrl *c)
68{
69 c->attrs->firmware = libnvme_get_ctrl_attr(c, "firmware_rev");
70 c->attrs->model = libnvme_get_ctrl_attr(c, "model");
71 c->attrs->serial = libnvme_get_ctrl_attr(c, "serial");
72 c->attrs->cntrltype = libnvme_get_ctrl_attr(c, "cntrltype");
73 c->attrs->cntlid = libnvme_get_ctrl_attr(c, "cntlid");
74 c->attrs->dctype = libnvme_get_ctrl_attr(c, "dctype");
75
76 return 0;
77}
78
79int libnvme_ctrl_load_phy_slot(struct libnvme_ctrl *c)
80{
81 const char *slots_sysfs_dir = libnvme_slots_sysfs_dir(c->ctx);
82 __cleanup_free__attribute__((cleanup(shr_freep))) char *target_addr = NULL((void*)0);
83 __cleanup_dir__attribute__((cleanup(cleanup_dir))) DIR *slots_dir = NULL((void*)0);
84 struct dirent *entry;
85 int ret;
86
87 if (!c->address)
4
Assuming field 'address' is non-null
5
Taking false branch
88 return 0;
89
90 slots_dir = opendir(slots_sysfs_dir);
91 if (!slots_dir
5.1
'slots_dir' is non-null
5.1
'slots_dir' is non-null
) {
6
Taking false branch
92 ret = -errno(*__errno_location ());
93 libnvme_msg(c->ctx, LIBNVME_LOG_WARN,__libnvme_msg(c->ctx, LIBNVME_LOG_WARN, ((void*)0), "failed to open slots dir %s\n"
, slots_sysfs_dir)
94 "failed to open slots dir %s\n", slots_sysfs_dir)__libnvme_msg(c->ctx, LIBNVME_LOG_WARN, ((void*)0), "failed to open slots dir %s\n"
, slots_sysfs_dir)
;
95 return ret;
96 }
97
98 target_addr = strndup(c->address, 10);
7
Memory is allocated
99 while ((entry = readdir(slots_dir))) {
8
Loop condition is false. Execution jumps to the end of the function
100 __cleanup_free__attribute__((cleanup(shr_freep))) char *path = NULL((void*)0);
101 __cleanup_free__attribute__((cleanup(shr_freep))) char *addr = NULL((void*)0);
102
103 if (entry->d_type != DT_DIRDT_DIR ||
104 !strncmp(entry->d_name, ".", 1) ||
105 !strncmp(entry->d_name, "..", 2))
106 continue;
107
108 ret = asprintf(&path, "%s/%s", slots_sysfs_dir, entry->d_name);
109 if (ret < 0)
110 return -ENOMEM12;
111
112 /* some directories don't have an address entry */
113 addr = libnvme_get_attr(path, "address");
114 if (!addr)
115 continue;
116 if (strcmp(addr, target_addr))
117 continue;
118
119 c->attrs->phy_slot = strdup(entry->d_name);
120 return 0;
121 }
122
123 return 0;
9
Potential leak of memory pointed to by 'target_addr'
124}
125
126/*
127 * No "csi" attribute: lba_count/lba_util/meta_size come from one
128 * Identify Namespace command instead. Each field's own
129 * ATTR_IS_LOADED() check keeps a caller that only reads one of these
130 * three from paying for more than one Identify command in the common
131 * case, but a prior call can leave some fields loaded and others not
132 * (e.g. -ENOMEM after lba_count's malloc but before lba_util's) --
133 * guard each field here too, so a retry never re-mallocs an
134 * already-loaded field and leaks the old allocation.
135 */
136static int ns_identify_geometry(struct libnvme_ns *n)
137{
138 __cleanup_libnvme_free__attribute__((cleanup(libnvme_freep))) struct nvme_id_ns *id = NULL((void*)0);
139 uint8_t flbas;
140 int ret;
141
142 id = libnvme_alloc(sizeof(*id));
143 if (!id)
144 return -ENOMEM12;
145
146 ret = libnvme_ns_identify(n, id);
147 if (ret)
148 return ret;
149
150 nvme_id_ns_flbas_to_lbaf_inuse(id->flbas, &flbas);
151
152 if (!ATTR_IS_LOADED(n->attrs->lba_count)((n->attrs->lba_count) != ((void*)0))) {
153 n->attrs->lba_count = malloc(sizeof(uint64_t));
154 if (!n->attrs->lba_count)
155 return -ENOMEM12;
156 *n->attrs->lba_count = le64_to_cpu(id->nsze);
157 }
158
159 if (!ATTR_IS_LOADED(n->attrs->lba_util)((n->attrs->lba_util) != ((void*)0))) {
160 n->attrs->lba_util = malloc(sizeof(uint64_t));
161 if (!n->attrs->lba_util)
162 return -ENOMEM12;
163 *n->attrs->lba_util = le64_to_cpu(id->nuse);
164 }
165
166 if (!ATTR_IS_LOADED(n->attrs->meta_size)((n->attrs->meta_size) != ((void*)0))) {
167 n->attrs->meta_size = malloc(sizeof(int));
168 if (!n->attrs->meta_size)
169 return -ENOMEM12;
170 *n->attrs->meta_size = le16_to_cpu(id->lbaf[flbas].ms);
171 }
172
173 return 0;
174}
175
176/*
177 * "size" is in 512-byte units and lba_count is in lba_size units, which
178 * are not necessarily the same -- matches the shift math libnvme_ns_init()
179 * used to do unconditionally before this conversion.
180 */
181static int ns_load_lba_count_from_size_attr(struct libnvme_ns *n)
182{
183 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
184 char *endptr;
185 int lba_shift;
186 uint64_t size;
187 int ret;
188
189 str = libnvme_get_ns_attr(n, "size");
190 if (!str)
191 return -ENOENT2;
192
193 errno(*__errno_location ()) = 0;
194 size = strtoull(str, &endptr, 0);
195 if (errno(*__errno_location ()) != 0)
196 return -errno(*__errno_location ());
197 if (endptr == str)
198 return -EINVAL22;
199
200 ret = libnvme_ns_get_lba_shift(n, &lba_shift, 0);
201 if (ret)
202 return ret;
203
204 n->attrs->lba_count = malloc(sizeof(uint64_t));
205 if (!n->attrs->lba_count)
206 return -ENOMEM12;
207
208 *n->attrs->lba_count = size >> (lba_shift - SECTOR_SHIFT9);
209 return 0;
210}
211
212static int ns_load_lba_util_attr(struct libnvme_ns *n)
213{
214 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
215 char *endptr;
216 uint64_t val;
217
218 str = libnvme_get_ns_attr(n, "nuse");
219 if (!str)
220 return -ENOENT2;
221
222 errno(*__errno_location ()) = 0;
223 val = strtoull(str, &endptr, 0);
224 if (errno(*__errno_location ()) != 0)
225 return -errno(*__errno_location ());
226 if (endptr == str)
227 return -EINVAL22;
228
229 n->attrs->lba_util = malloc(sizeof(uint64_t));
230 if (!n->attrs->lba_util)
231 return -ENOMEM12;
232
233 *n->attrs->lba_util = val;
234 return 0;
235}
236
237static int ns_load_meta_size_attr(struct libnvme_ns *n)
238{
239 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
240 char *endptr;
241 long val;
242
243 str = libnvme_get_ns_attr(n, "metadata_bytes");
244 if (!str)
245 return -ENOENT2;
246
247 errno(*__errno_location ()) = 0;
248 val = strtol(str, &endptr, 0);
249 if (errno(*__errno_location ()) != 0)
250 return -errno(*__errno_location ());
251 if (endptr == str)
252 return -EINVAL22;
253
254 n->attrs->meta_size = malloc(sizeof(int));
255 if (!n->attrs->meta_size)
256 return -ENOMEM12;
257
258 *n->attrs->meta_size = (int)val;
259 return 0;
260}
261
262/*
263 * The "csi" sysfs attribute exists on newer kernels only; its
264 * presence decides how the lba/metadata attributes are read.
265 *
266 * Return: 1 if present, 0 if absent, or a negative errno on a real
267 * failure reading it (not just absence).
268 */
269static int ns_csi_attr_exists(struct libnvme_ns *n)
270{
271 enum nvme_csi csi;
272 int ret;
273
274 ret = libnvme_ns_get_csi(n, &csi, NVME_CSI_NVM);
275 if (ret == -ENOENT2)
276 return 0;
277 if (ret)
278 return ret;
279
280 return 1;
281}
282
283/*
284 * Read unconditionally, regardless of whether "csi" exists -- unlike
285 * lba_count/lba_util/meta_size/csi, this attribute isn't gated by it.
286 */
287__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_lba_size(
288 const struct libnvme_ns *p,
289 int *val,
290 int dflt)
291{
292 struct libnvme_ns *n = (struct libnvme_ns *)p;
293 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
294
295 *val = dflt;
296
297 if (__shr_unlikely(!ATTR_IS_LOADED(n->attrs->lba_size))__builtin_expect(!!(!((n->attrs->lba_size) != ((void*)0
))), 0)
) {
298 str = libnvme_get_ns_attr(n, "queue/logical_block_size");
299 if (!str)
300 n->attrs->lba_size = (int *)NO_ATTR;
301 else {
302 n->attrs->lba_size = malloc(sizeof(int));
303 if (!n->attrs->lba_size)
304 return -ENOMEM12;
305 if (sscanf(str, "%d", n->attrs->lba_size) != 1) {
306 free(n->attrs->lba_size);
307 n->attrs->lba_size = NULL((void*)0);
308 return -EINVAL22;
309 }
310 }
311 }
312
313 if (ATTR_IS_ABSENT(n->attrs->lba_size)((void *)(n->attrs->lba_size) == (void *)NO_ATTR))
314 return -ENOENT2;
315
316 *val = *n->attrs->lba_size;
317 return 0;
318}
319
320/* Pure derivation, no field of its own -- recomputed every call from
321 * lba_size's own (already cached) getter.
322 */
323__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_lba_shift(
324 const struct libnvme_ns *p,
325 int *val,
326 int dflt)
327{
328 int lba_size;
329 int ret;
330
331 *val = dflt;
332
333 ret = libnvme_ns_get_lba_size(p, &lba_size, 0);
334 if (ret)
335 return ret;
336
337 /* lba_size is a power of two (NVMe LBADS is defined as an
338 * exponent, 2^n), so it has exactly one bit set -- ilog32()
339 * reports the position of that bit, i.e. the shift.
340 */
341 *val = ilog32(lba_size)(0 ? (((((uint32_t)(lba_size))&0xFFFF0000)?16+(((((uint32_t
)(lba_size))>>16)&0xFF00)?8+((((((uint32_t)(lba_size
))>>16)>>8)&0xF0)?4+(((((((uint32_t)(lba_size
))>>16)>>8)>>4)&0xC)?2+((((((((uint32_t
)(lba_size))>>16)>>8)>>4)>>2)&0x2
)?2:(!!((((((uint32_t)(lba_size))>>16)>>8)>>
4)>>2))):(((((((uint32_t)(lba_size))>>16)>>
8)>>4)&0x2)?2:(!!(((((uint32_t)(lba_size))>>16
)>>8)>>4)))):((((((uint32_t)(lba_size))>>16
)>>8)&0xC)?2+(((((((uint32_t)(lba_size))>>16)
>>8)>>2)&0x2)?2:(!!(((((uint32_t)(lba_size))>>
16)>>8)>>2))):((((((uint32_t)(lba_size))>>16
)>>8)&0x2)?2:(!!((((uint32_t)(lba_size))>>16)
>>8))))):(((((uint32_t)(lba_size))>>16)&0xF0)
?4+((((((uint32_t)(lba_size))>>16)>>4)&0xC)?2
+(((((((uint32_t)(lba_size))>>16)>>4)>>2)&
0x2)?2:(!!(((((uint32_t)(lba_size))>>16)>>4)>>
2))):((((((uint32_t)(lba_size))>>16)>>4)&0x2)
?2:(!!((((uint32_t)(lba_size))>>16)>>4)))):(((((uint32_t
)(lba_size))>>16)&0xC)?2+((((((uint32_t)(lba_size))
>>16)>>2)&0x2)?2:(!!((((uint32_t)(lba_size))>>
16)>>2))):(((((uint32_t)(lba_size))>>16)&0x2)
?2:(!!(((uint32_t)(lba_size))>>16)))))):((((uint32_t)(lba_size
))&0xFF00)?8+(((((uint32_t)(lba_size))>>8)&0xF0
)?4+((((((uint32_t)(lba_size))>>8)>>4)&0xC)?2
+(((((((uint32_t)(lba_size))>>8)>>4)>>2)&
0x2)?2:(!!(((((uint32_t)(lba_size))>>8)>>4)>>
2))):((((((uint32_t)(lba_size))>>8)>>4)&0x2)?
2:(!!((((uint32_t)(lba_size))>>8)>>4)))):(((((uint32_t
)(lba_size))>>8)&0xC)?2+((((((uint32_t)(lba_size))>>
8)>>2)&0x2)?2:(!!((((uint32_t)(lba_size))>>8)
>>2))):(((((uint32_t)(lba_size))>>8)&0x2)?2:(
!!(((uint32_t)(lba_size))>>8))))):((((uint32_t)(lba_size
))&0xF0)?4+(((((uint32_t)(lba_size))>>4)&0xC)?2
+((((((uint32_t)(lba_size))>>4)>>2)&0x2)?2:(!
!((((uint32_t)(lba_size))>>4)>>2))):(((((uint32_t
)(lba_size))>>4)&0x2)?2:(!!(((uint32_t)(lba_size))>>
4)))):((((uint32_t)(lba_size))&0xC)?2+(((((uint32_t)(lba_size
))>>2)&0x2)?2:(!!(((uint32_t)(lba_size))>>2))
):((((uint32_t)(lba_size))&0x2)?2:(!!((uint32_t)(lba_size
))))))))) : ilog32(lba_size))
- 1;
342 return 0;
343}
344
345__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_lba_count(
346 const struct libnvme_ns *p,
347 uint64_t *val,
348 uint64_t dflt)
349{
350 struct libnvme_ns *n = (struct libnvme_ns *)p;
351 int has_csi, ret;
352
353 *val = dflt;
354
355 if (__shr_unlikely(!ATTR_IS_LOADED(n->attrs->lba_count))__builtin_expect(!!(!((n->attrs->lba_count) != ((void*)
0))), 0)
) {
356 has_csi = ns_csi_attr_exists(n);
357 if (has_csi < 0)
358 return has_csi;
359
360 if (has_csi)
361 ret = ns_load_lba_count_from_size_attr(n);
362 else
363 ret = ns_identify_geometry(n);
364 if (ret)
365 return ret;
366 if (!n->attrs->lba_count)
367 n->attrs->lba_count = (uint64_t *)NO_ATTR;
368 }
369
370 if (ATTR_IS_ABSENT(n->attrs->lba_count)((void *)(n->attrs->lba_count) == (void *)NO_ATTR))
371 return -ENOENT2;
372
373 *val = *n->attrs->lba_count;
374 return 0;
375}
376
377__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_lba_util(
378 const struct libnvme_ns *p,
379 uint64_t *val,
380 uint64_t dflt)
381{
382 struct libnvme_ns *n = (struct libnvme_ns *)p;
383 int has_csi, ret;
384
385 *val = dflt;
386
387 if (__shr_unlikely(!ATTR_IS_LOADED(n->attrs->lba_util))__builtin_expect(!!(!((n->attrs->lba_util) != ((void*)0
))), 0)
) {
388 has_csi = ns_csi_attr_exists(n);
389 if (has_csi < 0)
390 return has_csi;
391
392 if (has_csi)
393 ret = ns_load_lba_util_attr(n);
394 else
395 ret = ns_identify_geometry(n);
396 if (ret)
397 return ret;
398 if (!n->attrs->lba_util)
399 n->attrs->lba_util = (uint64_t *)NO_ATTR;
400 }
401
402 if (ATTR_IS_ABSENT(n->attrs->lba_util)((void *)(n->attrs->lba_util) == (void *)NO_ATTR))
403 return -ENOENT2;
404
405 *val = *n->attrs->lba_util;
406 return 0;
407}
408
409__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_meta_size(
410 const struct libnvme_ns *p,
411 int *val,
412 int dflt)
413{
414 struct libnvme_ns *n = (struct libnvme_ns *)p;
415 int has_csi, ret;
416
417 *val = dflt;
418
419 if (__shr_unlikely(!ATTR_IS_LOADED(n->attrs->meta_size))__builtin_expect(!!(!((n->attrs->meta_size) != ((void*)
0))), 0)
) {
420 has_csi = ns_csi_attr_exists(n);
421 if (has_csi < 0)
422 return has_csi;
423
424 if (has_csi)
425 ret = ns_load_meta_size_attr(n);
426 else
427 ret = ns_identify_geometry(n);
428 if (ret)
429 return ret;
430 if (!n->attrs->meta_size)
431 n->attrs->meta_size = (int *)NO_ATTR;
432 }
433
434 if (ATTR_IS_ABSENT(n->attrs->meta_size)((void *)(n->attrs->meta_size) == (void *)NO_ATTR))
435 return -ENOENT2;
436
437 *val = *n->attrs->meta_size;
438 return 0;
439}
440
441__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_csi(
442 const struct libnvme_ns *p,
443 enum nvme_csi *val,
444 enum nvme_csi dflt)
445{
446 struct libnvme_ns *n = (struct libnvme_ns *)p;
447 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
448
449 *val = dflt;
450
451 if (__shr_unlikely(!ATTR_IS_LOADED(n->attrs->csi))__builtin_expect(!!(!((n->attrs->csi) != ((void*)0))), 0
)
) {
452 str = libnvme_get_ns_attr(n, "csi");
453 if (!str) {
454 n->attrs->csi = (enum nvme_csi *)NO_ATTR;
455 } else {
456 n->attrs->csi = malloc(sizeof(enum nvme_csi));
457 if (!n->attrs->csi)
458 return -ENOMEM12;
459
460 if (sscanf(str, "%d", (int *)n->attrs->csi) != 1) {
461 free(n->attrs->csi);
462 n->attrs->csi = NULL((void*)0);
463 return -EINVAL22;
464 }
465 }
466 }
467
468 if (ATTR_IS_ABSENT(n->attrs->csi)((void *)(n->attrs->csi) == (void *)NO_ATTR))
469 return -ENOENT2;
470
471 *val = *n->attrs->csi;
472 return 0;
473}
474
475/*
476 * eui64/nguid/uuid each live in their own optional sysfs attribute,
477 * read lazily and independently on first use, and cached for the
478 * lifetime of the namespace object -- the returned pointer stays valid
479 * until the namespace is freed, same lifetime guarantee every other
480 * pointer-returning lazy getter (e.g. libnvme_ctrl_get_model()) already
481 * gives its caller. "eui" is raw text copied byte-for-byte;
482 * "nguid"/"uuid" are hyphenated hex strings decoded with
483 * libnvme_uuid_from_string(), the same helper used everywhere else a
484 * UUID-shaped attribute is parsed.
485 */
486__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_eui64(
487 const struct libnvme_ns *p,
488 const uint8_t **val,
489 const uint8_t *dflt)
490{
491 struct libnvme_ns *n = (struct libnvme_ns *)p;
492 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
493
494 *val = dflt;
495
496 if (__shr_unlikely(!ATTR_IS_LOADED(n->attrs->eui64))__builtin_expect(!!(!((n->attrs->eui64) != ((void*)0)))
, 0)
) {
497 str = libnvme_get_ns_attr(n, "eui");
498 if (!str) {
499 n->attrs->eui64 = (uint8_t *)NO_ATTR;
500 } else {
501 n->attrs->eui64 = malloc(8);
502 if (!n->attrs->eui64)
503 return -ENOMEM12;
504 memcpy(n->attrs->eui64, str, 8);
505 }
506 }
507
508 if (ATTR_IS_ABSENT(n->attrs->eui64)((void *)(n->attrs->eui64) == (void *)NO_ATTR))
509 return -ENOENT2;
510
511 *val = n->attrs->eui64;
512 return 0;
513}
514
515__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_nguid(
516 const struct libnvme_ns *p,
517 const uint8_t **val,
518 const uint8_t *dflt)
519{
520 struct libnvme_ns *n = (struct libnvme_ns *)p;
521 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
522
523 *val = dflt;
524
525 if (__shr_unlikely(!ATTR_IS_LOADED(n->attrs->nguid))__builtin_expect(!!(!((n->attrs->nguid) != ((void*)0)))
, 0)
) {
526 str = libnvme_get_ns_attr(n, "nguid");
527 if (!str) {
528 n->attrs->nguid = (uint8_t *)NO_ATTR;
529 } else {
530 n->attrs->nguid = malloc(16);
531 if (!n->attrs->nguid)
532 return -ENOMEM12;
533 if (libnvme_uuid_from_string(str, n->attrs->nguid)) {
534 free(n->attrs->nguid);
535 n->attrs->nguid = NULL((void*)0);
536 return -EINVAL22;
537 }
538 }
539 }
540
541 if (ATTR_IS_ABSENT(n->attrs->nguid)((void *)(n->attrs->nguid) == (void *)NO_ATTR))
542 return -ENOENT2;
543
544 *val = n->attrs->nguid;
545 return 0;
546}
547
548__shr_public__attribute__((visibility("default"))) int libnvme_ns_get_uuid(
549 const struct libnvme_ns *p,
550 const unsigned char **val,
551 const unsigned char *dflt)
552{
553 struct libnvme_ns *n = (struct libnvme_ns *)p;
554 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
555
556 *val = dflt;
557
558 if (__shr_unlikely(!ATTR_IS_LOADED(n->attrs->uuid))__builtin_expect(!!(!((n->attrs->uuid) != ((void*)0))),
0)
) {
559 str = libnvme_get_ns_attr(n, "uuid");
560 if (!str) {
561 n->attrs->uuid = (unsigned char *)NO_ATTR;
562 } else {
563 n->attrs->uuid = malloc(NVME_UUID_LEN16);
564 if (!n->attrs->uuid)
565 return -ENOMEM12;
566 if (libnvme_uuid_from_string(str, n->attrs->uuid)) {
567 free(n->attrs->uuid);
568 n->attrs->uuid = NULL((void*)0);
569 return -EINVAL22;
570 }
571 }
572 }
573
574 if (ATTR_IS_ABSENT(n->attrs->uuid)((void *)(n->attrs->uuid) == (void *)NO_ATTR))
575 return -ENOENT2;
576
577 *val = n->attrs->uuid;
578 return 0;
579}