Bug Summary

File:.build-ci/../plugins/micron/micron-utils-linux.c
Warning:line 62, column 2
Value stored to 'fd' is never read

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 micron-utils-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 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 ../plugins/micron/micron-utils-linux.c
1// SPDX-License-Identifier: LGPL-2.1-or-later
2/*
3 * Copyright (c) 2025 Micron Technology, Inc.
4 *
5 * Authors: Broc Going <bgoing@micron.com>
6 */
7
8#include <errno(*__errno_location ()).h>
9#include <fcntl.h>
10#include <limits.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <unistd.h>
15
16#include <sys/klog.h>
17#include <sys/utsname.h>
18
19#include <libnvme.h>
20
21#include <ccan/array_size/array_size.h>
22
23#include <shared/fs-util.h>
24#include <shared/io-util.h>
25#include <shared/pci-util.h>
26
27#include "micron-utils.h"
28#include "nvme-print.h"
29#include "src/cleanup.h"
30#include "src/global-ctx.h"
31
32/*
33 * Resolves ctrl_name (e.g. "nvme0") to its PCI AER capability.
34 * Return: 0 on success (with *out_fd and *out_aer_offset set), negative
35 * errno otherwise.
36 */
37static int open_aer_cap(const char *ctrl_name, int flags,
38 int *out_fd, unsigned int *out_aer_offset)
39{
40 __cleanup_free__attribute__((cleanup(shr_freep))) char *ctrl_dir = NULL((void*)0);
41 __cleanup_fd__attribute__((cleanup(shr_cleanup_fd))) int fd = -1;
42 int offset;
43 int ret;
44
45 ret = nvme_sysfs_ctrl_path(ctrl_name, &ctrl_dir);
46 if (ret)
47 return ret;
48
49 fd = shr_pci_open_class_config(ctrl_dir, flags);
50 if (fd < 0) {
51 nvme_show_perror("%s/device/config", ctrl_dir);
52 return fd;
53 }
54
55 offset = shr_pci_find_ext_cap(fd, SHR_PCI_EXT_CAP_ID_AER0x0001);
56 if (offset < 0) {
57 nvme_show_error("Device has no PCIe AER capability")nvme_show_message(1, "Device has no PCIe AER capability");
58 return offset;
59 }
60
61 *out_fd = fd;
62 fd = -1; /* ownership moves to the caller */
Value stored to 'fd' is never read
63 *out_aer_offset = (unsigned int)offset;
64 return 0;
65}
66
67int micron_get_pcie_aer_errors(struct libnvme_transport_handle *hdl,
68 __u32 *correctable_errors, __u32 *uncorrectable_errors)
69{
70 __cleanup_free__attribute__((cleanup(shr_freep))) char *ctrl_name = micron_get_ctrl_name(hdl);
71 __cleanup_fd__attribute__((cleanup(shr_cleanup_fd))) int fd = -1;
72 unsigned int aer;
73 int ret;
74
75 if (!ctrl_name)
76 return -EINVAL22;
77
78 ret = open_aer_cap(ctrl_name, O_RDONLY00, &fd, &aer);
79 if (ret)
80 return ret;
81
82 ret = shr_pci_config_read32(fd, aer + SHR_PCI_AER_COR_STATUS_OFF0x10,
83 correctable_errors);
84 if (ret) {
85 nvme_show_error("Failed to retrieve error count")nvme_show_message(1, "Failed to retrieve error count");
86 return ret;
87 }
88
89 ret = shr_pci_config_read32(fd, aer + SHR_PCI_AER_UNCOR_STATUS_OFF0x04,
90 uncorrectable_errors);
91 if (ret) {
92 nvme_show_error("Failed to retrieve error count")nvme_show_message(1, "Failed to retrieve error count");
93 return ret;
94 }
95
96 return 0;
97}
98
99int micron_clear_pcie_aer_correctable_errors(
100 struct libnvme_transport_handle *hdl)
101{
102 __cleanup_free__attribute__((cleanup(shr_freep))) char *ctrl_name = micron_get_ctrl_name(hdl);
103 __cleanup_fd__attribute__((cleanup(shr_cleanup_fd))) int fd = -1;
104 unsigned int aer;
105 __u32 correctable;
106 int ret;
107
108 if (!ctrl_name)
109 return -EINVAL22;
110
111 ret = open_aer_cap(ctrl_name, O_RDWR02, &fd, &aer);
112 if (ret)
113 return ret;
114
115 /* Writing all 1s clears the write-1-to-clear status bits. */
116 ret = shr_pci_config_write32(fd, aer + SHR_PCI_AER_COR_STATUS_OFF0x10,
117 0xffffffff);
118 if (ret) {
119 nvme_show_error("Failed to clear error count")nvme_show_message(1, "Failed to clear error count");
120 return ret;
121 }
122
123 ret = shr_pci_config_read32(fd, aer + SHR_PCI_AER_COR_STATUS_OFF0x10,
124 &correctable);
125 if (ret) {
126 nvme_show_error("Failed to retrieve error count")nvme_show_message(1, "Failed to retrieve error count");
127 return ret;
128 }
129 nvme_show_verbose_result("Device correctable errors cleared!")nvme_show_verbose_message("Device correctable errors cleared!"
)
;
130 nvme_show_result("Device correctable errors detected: %08x",nvme_show_message(0, "Device correctable errors detected: %08x"
, correctable)
131 correctable)nvme_show_message(0, "Device correctable errors detected: %08x"
, correctable)
;
132 return 0;
133}
134
135/* Generous but bounded: this is a human-readable support dump, not a
136 * guarantee of capturing every byte of a possibly huge /proc file or log.
137 */
138#define OS_CONFIG_CAPTURE_MAX(1 << 20) (1 << 20)
139
140static int append_file_contents(int out_fd, const char *path)
141{
142 __cleanup_fd__attribute__((cleanup(shr_cleanup_fd))) int fd = open(path, O_RDONLY00);
143 __cleanup_free__attribute__((cleanup(shr_freep))) char *buf = NULL((void*)0);
144 int ret;
145
146 if (fd < 0)
147 return -errno(*__errno_location ());
148
149 buf = malloc(OS_CONFIG_CAPTURE_MAX(1 << 20));
150 if (!buf)
151 return -ENOMEM12;
152
153 ret = shr_read_all(fd, buf, OS_CONFIG_CAPTURE_MAX(1 << 20));
154 if (ret)
155 return ret;
156
157 return shr_write_all(out_fd, buf, strlen(buf));
158}
159
160static int append_uname(int out_fd)
161{
162 struct utsname uts;
163 char line[512];
164 int n;
165
166 if (uname(&uts))
167 return -errno(*__errno_location ());
168
169 n = snprintf(line, sizeof(line), "%s %s %s %s %s\n",
170 uts.sysname, uts.nodename, uts.release, uts.version,
171 uts.machine);
172 if (n < 0)
173 return -errno(*__errno_location ());
174 if ((size_t)n >= sizeof(line))
175 n = sizeof(line) - 1;
176
177 return shr_write_all(out_fd, line, (size_t)n);
178}
179
180/*
181 * man 2 syslog documents these action numbers; <sys/klog.h> declares
182 * klogctl() but, oddly, not the actions it takes.
183 */
184#define SYSLOG_ACTION_READ_ALL3 3
185#define SYSLOG_ACTION_SIZE_BUFFER10 10
186
187static int append_dmesg(int out_fd)
188{
189 __cleanup_free__attribute__((cleanup(shr_freep))) char *buf = NULL((void*)0);
190 int len;
191
192 len = klogctl(SYSLOG_ACTION_SIZE_BUFFER10, NULL((void*)0), 0);
193 if (len <= 0 || len > OS_CONFIG_CAPTURE_MAX(1 << 20))
194 len = OS_CONFIG_CAPTURE_MAX(1 << 20);
195
196 buf = malloc(len);
197 if (!buf)
198 return -ENOMEM12;
199
200 len = klogctl(SYSLOG_ACTION_READ_ALL3, buf, len);
201 if (len < 0)
202 return -errno(*__errno_location ());
203
204 return shr_write_all(out_fd, buf, (size_t)len);
205}
206
207enum os_config_kind {
208 OS_CONFIG_FILE,
209 OS_CONFIG_UNAME,
210 OS_CONFIG_DMESG,
211};
212
213struct os_config_item {
214 const char *header;
215 enum os_config_kind kind;
216 const char *path;
217};
218
219static const struct os_config_item os_config_items[] = {
220 { "SYSTEM INFORMATION", OS_CONFIG_UNAME, NULL((void*)0) },
221 { "LINUX KERNEL MODULE INFORMATION", OS_CONFIG_FILE, "/proc/modules" },
222 { "LINUX SYSTEM MEMORY INFORMATION", OS_CONFIG_FILE, "/proc/meminfo" },
223 { "SYSTEM INTERRUPT INFORMATION", OS_CONFIG_FILE, "/proc/interrupts" },
224 { "CPU INFORMATION", OS_CONFIG_FILE, "/proc/cpuinfo" },
225 { "IO MEMORY MAP INFORMATION", OS_CONFIG_FILE, "/proc/iomem" },
226 { "MAJOR NUMBER AND DEVICE GROUP", OS_CONFIG_FILE, "/proc/devices" },
227 { "KERNEL DMESG", OS_CONFIG_DMESG, NULL((void*)0) },
228 { "/VAR/LOG/MESSAGES", OS_CONFIG_FILE, "/var/log/messages" },
229};
230
231void micron_write_os_config_to_file(const char *file_name)
232{
233 size_t i;
234
235 for (i = 0; i < ARRAY_SIZE(os_config_items)(sizeof(os_config_items) / sizeof((os_config_items)[0]) + 0); i++) {
236 const struct os_config_item *item = &os_config_items[i];
237 __cleanup_fd__attribute__((cleanup(shr_cleanup_fd))) int out_fd = -1;
238 FILE *header_file;
239 int ret;
240
241 header_file = fopen(file_name, "a+");
242 if (header_file) {
243 fprintf(header_file,
244 "\n\n\n\n%s\n-----------------------------------------------\n",
245 item->header);
246 fclose(header_file);
247 }
248
249 out_fd = shr_open_rawdata(file_name,open((file_name), (01 | 0100 | 02000), 0644)
250 O_WRONLY | O_CREAT | O_APPEND, 0644)open((file_name), (01 | 0100 | 02000), 0644);
251 if (out_fd < 0) {
252 nvme_show_error("Failed to open \"%s\": %s",nvme_show_message(1, "Failed to open \"%s\": %s", file_name, strerror
((*__errno_location ())))
253 file_name, strerror(errno))nvme_show_message(1, "Failed to open \"%s\": %s", file_name, strerror
((*__errno_location ())))
;
254 continue;
255 }
256
257 switch (item->kind) {
258 case OS_CONFIG_UNAME:
259 ret = append_uname(out_fd);
260 break;
261 case OS_CONFIG_DMESG:
262 ret = append_dmesg(out_fd);
263 break;
264 case OS_CONFIG_FILE:
265 default:
266 ret = append_file_contents(out_fd, item->path);
267 break;
268 }
269 if (ret)
270 nvme_show_error("Failed to capture \"%s\": %s",nvme_show_message(1, "Failed to capture \"%s\": %s", item->
header, strerror(-ret))
271 item->header, strerror(-ret))nvme_show_message(1, "Failed to capture \"%s\": %s", item->
header, strerror(-ret))
;
272 }
273}
274
275void micron_get_os_string(char *buf, size_t len)
276{
277 struct utsname un;
278
279 if (!buf || !len)
280 return;
281 buf[0] = '\0';
282
283 if (uname(&un))
284 return;
285
286 snprintf(buf, len, "%s %s %s", un.sysname, un.release, un.machine);
287}