Bug Summary

File:.build-ci/../plugins/scaleflux/sfx-nvme.c
Warning:line 1228, column 11
Result of 'calloc' is converted to a pointer of type 'struct nvme_persistent_event_log', which is incompatible with sizeof operand type '__u8'

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 sfx-nvme.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I nvme.p -I . -I .. -I ccan -I ../ccan -I libnvme/src -I ../libnvme/src -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -std=gnu99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-06-24-175442-590-1 -x c ../plugins/scaleflux/sfx-nvme.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2#include <fcntl.h>
3#include <errno(*__errno_location ()).h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <unistd.h>
8#include <linux1/fs.h>
9#include <inttypes.h>
10#include <asm/byteorder.h>
11#include <sys/sysinfo.h>
12#include <sys/stat.h>
13#include <sys/types.h>
14#include <sys/ioctl.h>
15#include <dirent.h>
16#include <time.h>
17
18#include <libnvme.h>
19
20#include "common.h"
21#include "nvme-cmds.h"
22#include "nvme-print.h"
23#include "nvme.h"
24#include "plugin.h"
25#include "util/cleanup.h"
26#include "util/types.h"
27
28#define CREATE_CMD
29#include "sfx-nvme.h"
30#include "sfx-types.h"
31
32#define SFX_PAGE_SHIFT12 12
33#define SECTOR_SHIFT9 9
34
35#define SFX_GET_FREESPACE(((2U|1U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8
)) | (((0x240)) << 0) | ((((sizeof(struct sfx_freespace_ctx
)))) << ((0 +8)+8)))
_IOWR('N', 0x240, struct sfx_freespace_ctx)(((2U|1U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8
)) | (((0x240)) << 0) | ((((sizeof(struct sfx_freespace_ctx
)))) << ((0 +8)+8)))
36#define NVME_IOCTL_CLR_CARD(((0U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8)) |
(((0x47)) << 0) | ((0) << ((0 +8)+8)))
_IO('N', 0x47)(((0U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8)) |
(((0x47)) << 0) | ((0) << ((0 +8)+8)))
37
38//See IDEMA LBA1-03
39#define IDEMA_CAP(exp_GB)(((__u64)exp_GB - 50ULL) * 1953504ULL + 97696368ULL) (((__u64)exp_GB - 50ULL) * 1953504ULL + 97696368ULL)
40#define IDEMA_CAP2GB(exp_sector)(((__u64)exp_sector - 97696368ULL) / 1953504ULL + 50ULL) (((__u64)exp_sector - 97696368ULL) / 1953504ULL + 50ULL)
41#define IDEMA_CAP2GB_LDS(exp_sector)(((__u64)exp_sector - 12212046ULL) / 244188ULL + 50ULL) (((__u64)exp_sector - 12212046ULL) / 244188ULL + 50ULL)
42
43#define VANDA_MAJOR_IDX0 0
44#define VANDA_MINOR_IDX0 0
45
46#define MYRTLE_MAJOR_IDX4 4
47#define MYRTLE_MINOR_IDX1 1
48
49
50
51int nvme_query_cap(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 data_len, void *data)
52{
53 int rc = 0;
54 struct libnvme_passthru_cmd cmd = {
55 .opcode = nvme_admin_query_cap_info,
56 .nsid = nsid,
57 .addr = (__u64)(uintptr_t) data,
58 .data_len = data_len,
59 };
60
61 rc = ioctl(libnvme_transport_handle_get_fd(hdl), SFX_GET_FREESPACE(((2U|1U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8
)) | (((0x240)) << 0) | ((((sizeof(struct sfx_freespace_ctx
)))) << ((0 +8)+8)))
, data);
62 return rc ? libnvme_exec_admin_passthru(hdl, &cmd) : 0;
63}
64
65int nvme_change_cap(struct libnvme_transport_handle *hdl, __u32 nsid, __u64 capacity)
66{
67 struct libnvme_passthru_cmd cmd = {
68 .opcode = nvme_admin_change_cap,
69 .nsid = nsid,
70 .cdw10 = (capacity & 0xffffffff),
71 .cdw11 = (capacity >> 32),
72 };
73
74 return libnvme_exec_admin_passthru(hdl, &cmd);
75}
76
77int nvme_sfx_set_features(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 fid, __u32 value)
78{
79 struct libnvme_passthru_cmd cmd = {
80 .opcode = nvme_admin_sfx_set_features,
81 .nsid = nsid,
82 .cdw10 = fid,
83 .cdw11 = value,
84 };
85
86 return libnvme_exec_admin_passthru(hdl, &cmd);
87}
88
89int nvme_sfx_get_features(struct libnvme_transport_handle *hdl, __u32 nsid, __u32 fid, __u32 *result)
90{
91 int err = 0;
92 struct libnvme_passthru_cmd cmd = {
93 .opcode = nvme_admin_sfx_get_features,
94 .nsid = nsid,
95 .cdw10 = fid,
96 };
97
98 err = libnvme_exec_admin_passthru(hdl, &cmd);
99 if (!err && result)
100 *result = cmd.result;
101
102 return err;
103}
104
105#ifdef CONFIG_JSONC
106static void show_sfx_smart_log_jsn(struct nvme_additional_smart_log *smart,
107 unsigned int nsid, const char *devname)
108{
109 struct json_object *root, *entry_stats, *dev_stats, *multi;
110
111 root = json_create_object()json_object_new_object();
112 json_object_add_value_string(root, "ScaleFlux Smart log", devname);
113
114 dev_stats = json_create_object()json_object_new_object();
115
116 entry_stats = json_create_object()json_object_new_object();
117 json_object_add_value_int(entry_stats, "normalized", smart->program_fail_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->program_fail_cnt.norm))
;
118 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->program_fail_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->program_fail_cnt.raw)))
;
119 json_object_add_value_object(dev_stats, "program_fail_count", entry_stats)json_object_object_add(dev_stats, "program_fail_count", entry_stats
)
;
120
121 entry_stats = json_create_object()json_object_new_object();
122 json_object_add_value_int(entry_stats, "normalized", smart->erase_fail_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->erase_fail_cnt.norm))
;
123 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->erase_fail_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->erase_fail_cnt.raw)))
;
124 json_object_add_value_object(dev_stats, "erase_fail_count", entry_stats)json_object_object_add(dev_stats, "erase_fail_count", entry_stats
)
;
125
126 entry_stats = json_create_object()json_object_new_object();
127 json_object_add_value_int(entry_stats, "normalized", smart->wear_leveling_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->wear_leveling_cnt.norm))
;
128 multi = json_create_object()json_object_new_object();
129 json_object_add_value_int(multi, "min", le16_to_cpu(smart->wear_leveling_cnt.wear_level.min))json_object_object_add(multi, "min", json_object_new_int(le16_to_cpu
(smart->wear_leveling_cnt.wear_level.min)))
;
130 json_object_add_value_int(multi, "max", le16_to_cpu(smart->wear_leveling_cnt.wear_level.max))json_object_object_add(multi, "max", json_object_new_int(le16_to_cpu
(smart->wear_leveling_cnt.wear_level.max)))
;
131 json_object_add_value_int(multi, "avg", le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg))json_object_object_add(multi, "avg", json_object_new_int(le16_to_cpu
(smart->wear_leveling_cnt.wear_level.avg)))
;
132 json_object_add_value_object(entry_stats, "raw", multi)json_object_object_add(entry_stats, "raw", multi);
133 json_object_add_value_object(dev_stats, "wear_leveling", entry_stats)json_object_object_add(dev_stats, "wear_leveling", entry_stats
)
;
134
135 entry_stats = json_create_object()json_object_new_object();
136 json_object_add_value_int(entry_stats, "normalized", smart->e2e_err_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->e2e_err_cnt.norm))
;
137 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->e2e_err_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->e2e_err_cnt.raw)))
;
138 json_object_add_value_object(dev_stats, "end_to_end_error_detection_count", entry_stats)json_object_object_add(dev_stats, "end_to_end_error_detection_count"
, entry_stats)
;
139
140 entry_stats = json_create_object()json_object_new_object();
141 json_object_add_value_int(entry_stats, "normalized", smart->crc_err_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->crc_err_cnt.norm))
;
142 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->crc_err_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->crc_err_cnt.raw)))
;
143 json_object_add_value_object(dev_stats, "crc_error_count", entry_stats)json_object_object_add(dev_stats, "crc_error_count", entry_stats
)
;
144
145 entry_stats = json_create_object()json_object_new_object();
146 json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_media_wear.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->timed_workload_media_wear.norm))
;
147 json_object_add_value_float(entry_stats, "raw", ((float)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024)json_object_object_add(entry_stats, "raw", json_object_new_double
(((float)int48_to_long(smart->timed_workload_media_wear.raw
)) / 1024))
;
148 json_object_add_value_object(dev_stats, "timed_workload_media_wear", entry_stats)json_object_object_add(dev_stats, "timed_workload_media_wear"
, entry_stats)
;
149
150 entry_stats = json_create_object()json_object_new_object();
151 json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_host_reads.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->timed_workload_host_reads.norm))
;
152 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->timed_workload_host_reads.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->timed_workload_host_reads.raw)))
;
153 json_object_add_value_object(dev_stats, "timed_workload_host_reads", entry_stats)json_object_object_add(dev_stats, "timed_workload_host_reads"
, entry_stats)
;
154
155 entry_stats = json_create_object()json_object_new_object();
156 json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_timer.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->timed_workload_timer.norm))
;
157 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->timed_workload_timer.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->timed_workload_timer.raw)))
;
158 json_object_add_value_object(dev_stats, "timed_workload_timer", entry_stats)json_object_object_add(dev_stats, "timed_workload_timer", entry_stats
)
;
159
160 entry_stats = json_create_object()json_object_new_object();
161 json_object_add_value_int(entry_stats, "normalized", smart->thermal_throttle_status.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->thermal_throttle_status.norm))
;
162 multi = json_create_object()json_object_new_object();
163 json_object_add_value_int(multi, "pct", smart->thermal_throttle_status.thermal_throttle.pct)json_object_object_add(multi, "pct", json_object_new_int(smart
->thermal_throttle_status.thermal_throttle.pct))
;
164 json_object_add_value_int(multi, "cnt", smart->thermal_throttle_status.thermal_throttle.count)json_object_object_add(multi, "cnt", json_object_new_int(smart
->thermal_throttle_status.thermal_throttle.count))
;
165 json_object_add_value_object(entry_stats, "raw", multi)json_object_object_add(entry_stats, "raw", multi);
166 json_object_add_value_object(dev_stats, "thermal_throttle_status", entry_stats)json_object_object_add(dev_stats, "thermal_throttle_status", entry_stats
)
;
167
168 entry_stats = json_create_object()json_object_new_object();
169 json_object_add_value_int(entry_stats, "normalized", smart->retry_buffer_overflow_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->retry_buffer_overflow_cnt.norm))
;
170 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->retry_buffer_overflow_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->retry_buffer_overflow_cnt.raw)))
;
171 json_object_add_value_object(dev_stats, "retry_buffer_overflow_count", entry_stats)json_object_object_add(dev_stats, "retry_buffer_overflow_count"
, entry_stats)
;
172
173 entry_stats = json_create_object()json_object_new_object();
174 json_object_add_value_int(entry_stats, "normalized", smart->pll_lock_loss_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->pll_lock_loss_cnt.norm))
;
175 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->pll_lock_loss_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->pll_lock_loss_cnt.raw)))
;
176 json_object_add_value_object(dev_stats, "pll_lock_loss_count", entry_stats)json_object_object_add(dev_stats, "pll_lock_loss_count", entry_stats
)
;
177
178 entry_stats = json_create_object()json_object_new_object();
179 json_object_add_value_int(entry_stats, "normalized", smart->nand_bytes_written.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->nand_bytes_written.norm))
;
180 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->nand_bytes_written.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->nand_bytes_written.raw)))
;
181 json_object_add_value_object(dev_stats, "nand_bytes_written", entry_stats)json_object_object_add(dev_stats, "nand_bytes_written", entry_stats
)
;
182
183 entry_stats = json_create_object()json_object_new_object();
184 json_object_add_value_int(entry_stats, "normalized", smart->host_bytes_written.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->host_bytes_written.norm))
;
185 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_bytes_written.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->host_bytes_written.raw)))
;
186 json_object_add_value_object(dev_stats, "host_bytes_written", entry_stats)json_object_object_add(dev_stats, "host_bytes_written", entry_stats
)
;
187
188 entry_stats = json_create_object()json_object_new_object();
189 json_object_add_value_int(entry_stats, "normalized", smart->raid_recover_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->raid_recover_cnt.norm))
;
190 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->raid_recover_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->raid_recover_cnt.raw)))
;
191 json_object_add_value_object(dev_stats, "raid_recover_cnt", entry_stats)json_object_object_add(dev_stats, "raid_recover_cnt", entry_stats
)
;
192
193 entry_stats = json_create_object()json_object_new_object();
194 json_object_add_value_int(entry_stats, "normalized", smart->prog_timeout_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->prog_timeout_cnt.norm))
;
195 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->prog_timeout_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->prog_timeout_cnt.raw)))
;
196 json_object_add_value_object(dev_stats, "prog_timeout_cnt", entry_stats)json_object_object_add(dev_stats, "prog_timeout_cnt", entry_stats
)
;
197
198 entry_stats = json_create_object()json_object_new_object();
199 json_object_add_value_int(entry_stats, "normalized", smart->erase_timeout_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->erase_timeout_cnt.norm))
;
200 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->erase_timeout_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->erase_timeout_cnt.raw)))
;
201 json_object_add_value_object(dev_stats, "erase_timeout_cnt", entry_stats)json_object_object_add(dev_stats, "erase_timeout_cnt", entry_stats
)
;
202
203 entry_stats = json_create_object()json_object_new_object();
204 json_object_add_value_int(entry_stats, "normalized", smart->read_timeout_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->read_timeout_cnt.norm))
;
205 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->read_timeout_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->read_timeout_cnt.raw)))
;
206 json_object_add_value_object(dev_stats, "read_timeout_cnt", entry_stats)json_object_object_add(dev_stats, "read_timeout_cnt", entry_stats
)
;
207
208 entry_stats = json_create_object()json_object_new_object();
209 json_object_add_value_int(entry_stats, "normalized", smart->read_ecc_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->read_ecc_cnt.norm))
;
210 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->read_ecc_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->read_ecc_cnt.raw)))
;
211 json_object_add_value_object(dev_stats, "read_ecc_cnt", entry_stats)json_object_object_add(dev_stats, "read_ecc_cnt", entry_stats
)
;
212
213 entry_stats = json_create_object()json_object_new_object();
214 json_object_add_value_int(entry_stats, "normalized", smart->non_media_crc_err_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->non_media_crc_err_cnt.norm))
;
215 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->non_media_crc_err_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->non_media_crc_err_cnt.raw)))
;
216 json_object_add_value_object(dev_stats, "non_media_crc_err_cnt", entry_stats)json_object_object_add(dev_stats, "non_media_crc_err_cnt", entry_stats
)
;
217
218 entry_stats = json_create_object()json_object_new_object();
219 json_object_add_value_int(entry_stats, "normalized", smart->compression_path_err_cnt.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->compression_path_err_cnt.norm))
;
220 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->compression_path_err_cnt.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->compression_path_err_cnt.raw)))
;
221 json_object_add_value_object(dev_stats, "compression_path_err_cnt", entry_stats)json_object_object_add(dev_stats, "compression_path_err_cnt",
entry_stats)
;
222
223 entry_stats = json_create_object()json_object_new_object();
224 json_object_add_value_int(entry_stats, "normalized", smart->out_of_space_flag.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->out_of_space_flag.norm))
;
225 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->out_of_space_flag.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->out_of_space_flag.raw)))
;
226 json_object_add_value_object(dev_stats, "out_of_space_flag", entry_stats)json_object_object_add(dev_stats, "out_of_space_flag", entry_stats
)
;
227
228 entry_stats = json_create_object()json_object_new_object();
229 json_object_add_value_int(entry_stats, "normalized", smart->physical_usage_ratio.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->physical_usage_ratio.norm))
;
230 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->physical_usage_ratio.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->physical_usage_ratio.raw)))
;
231 json_object_add_value_object(dev_stats, "physical_usage_ratio", entry_stats)json_object_object_add(dev_stats, "physical_usage_ratio", entry_stats
)
;
232
233 entry_stats = json_create_object()json_object_new_object();
234 json_object_add_value_int(entry_stats, "normalized", smart->grown_bb.norm)json_object_object_add(entry_stats, "normalized", json_object_new_int
(smart->grown_bb.norm))
;
235 json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->grown_bb.raw))json_object_object_add(entry_stats, "raw", json_object_new_int
(int48_to_long(smart->grown_bb.raw)))
;
236 json_object_add_value_object(dev_stats, "grown_bb", entry_stats)json_object_object_add(dev_stats, "grown_bb", entry_stats);
237
238 json_object_add_value_object(root, "Device stats", dev_stats)json_object_object_add(root, "Device stats", dev_stats);
239
240 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
241 printf("\n");
242 json_free_object(root)json_object_put(root);
243}
244#else /* CONFIG_JSONC */
245#define show_sfx_smart_log_jsn(smart, nsid, devname)
246#endif /* CONFIG_JSONC */
247
248static void show_sfx_smart_log(struct nvme_additional_smart_log *smart,
249 unsigned int nsid, const char *devname)
250{
251 printf("Additional Smart Log for ScaleFlux device:%s namespace-id:%x\n",
252 devname, nsid);
253 printf("key normalized raw\n");
254 printf("program_fail_count : %3d%% %"PRIu64"l" "u""\n",
255 smart->program_fail_cnt.norm,
256 int48_to_long(smart->program_fail_cnt.raw));
257 printf("erase_fail_count : %3d%% %"PRIu64"l" "u""\n",
258 smart->erase_fail_cnt.norm,
259 int48_to_long(smart->erase_fail_cnt.raw));
260 printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n",
261 smart->wear_leveling_cnt.norm,
262 le16_to_cpu(smart->wear_leveling_cnt.wear_level.min),
263 le16_to_cpu(smart->wear_leveling_cnt.wear_level.max),
264 le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg));
265 printf("end_to_end_error_detection_count: %3d%% %"PRIu64"l" "u""\n",
266 smart->e2e_err_cnt.norm,
267 int48_to_long(smart->e2e_err_cnt.raw));
268 printf("crc_error_count : %3d%% %"PRIu64"l" "u""\n",
269 smart->crc_err_cnt.norm,
270 int48_to_long(smart->crc_err_cnt.raw));
271 printf("timed_workload_media_wear : %3d%% %.3f%%\n",
272 smart->timed_workload_media_wear.norm,
273 ((float)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024);
274 printf("timed_workload_host_reads : %3d%% %"PRIu64"l" "u""%%\n",
275 smart->timed_workload_host_reads.norm,
276 int48_to_long(smart->timed_workload_host_reads.raw));
277 printf("timed_workload_timer : %3d%% %"PRIu64"l" "u"" min\n",
278 smart->timed_workload_timer.norm,
279 int48_to_long(smart->timed_workload_timer.raw));
280 printf("thermal_throttle_status : %3d%% %u%%, cnt: %u\n",
281 smart->thermal_throttle_status.norm,
282 smart->thermal_throttle_status.thermal_throttle.pct,
283 smart->thermal_throttle_status.thermal_throttle.count);
284 printf("retry_buffer_overflow_count : %3d%% %"PRIu64"l" "u""\n",
285 smart->retry_buffer_overflow_cnt.norm,
286 int48_to_long(smart->retry_buffer_overflow_cnt.raw));
287 printf("pll_lock_loss_count : %3d%% %"PRIu64"l" "u""\n",
288 smart->pll_lock_loss_cnt.norm,
289 int48_to_long(smart->pll_lock_loss_cnt.raw));
290 printf("nand_bytes_written : %3d%% sectors: %"PRIu64"l" "u""\n",
291 smart->nand_bytes_written.norm,
292 int48_to_long(smart->nand_bytes_written.raw));
293 printf("host_bytes_written : %3d%% sectors: %"PRIu64"l" "u""\n",
294 smart->host_bytes_written.norm,
295 int48_to_long(smart->host_bytes_written.raw));
296 printf("raid_recover_cnt : %3d%% %"PRIu64"l" "u""\n",
297 smart->raid_recover_cnt.norm,
298 int48_to_long(smart->raid_recover_cnt.raw));
299 printf("read_ecc_cnt : %3d%% %"PRIu64"l" "u""\n",
300 smart->read_ecc_cnt.norm,
301 int48_to_long(smart->read_ecc_cnt.raw));
302 printf("prog_timeout_cnt : %3d%% %"PRIu64"l" "u""\n",
303 smart->prog_timeout_cnt.norm,
304 int48_to_long(smart->prog_timeout_cnt.raw));
305 printf("erase_timeout_cnt : %3d%% %"PRIu64"l" "u""\n",
306 smart->erase_timeout_cnt.norm,
307 int48_to_long(smart->erase_timeout_cnt.raw));
308 printf("read_timeout_cnt : %3d%% %"PRIu64"l" "u""\n",
309 smart->read_timeout_cnt.norm,
310 int48_to_long(smart->read_timeout_cnt.raw));
311 printf("non_media_crc_err_cnt : %3d%% %" PRIu64"l" "u" "\n",
312 smart->non_media_crc_err_cnt.norm,
313 int48_to_long(smart->non_media_crc_err_cnt.raw));
314 printf("compression_path_err_cnt : %3d%% %" PRIu64"l" "u" "\n",
315 smart->compression_path_err_cnt.norm,
316 int48_to_long(smart->compression_path_err_cnt.raw));
317 printf("out_of_space_flag : %3d%% %" PRIu64"l" "u" "\n",
318 smart->out_of_space_flag.norm,
319 int48_to_long(smart->out_of_space_flag.raw));
320 printf("phy_capacity_used_ratio : %3d%% %" PRIu64"l" "u" "\n",
321 smart->physical_usage_ratio.norm,
322 int48_to_long(smart->physical_usage_ratio.raw));
323 printf("grown_bb_count : %3d%% %" PRIu64"l" "u" "\n",
324 smart->grown_bb.norm, int48_to_long(smart->grown_bb.raw));
325
326
327}
328
329static int get_additional_smart_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
330{
331 struct nvme_additional_smart_log smart_log;
332 char *desc =
333 "Get ScaleFlux vendor specific additional smart log (optionally, for the specified namespace), and show it.";
334 const char *namespace = "(optional) desired namespace";
335 const char *raw = "dump output in binary format";
336#ifdef CONFIG_JSONC
337 const char *json = "Dump output in json format";
338#endif /* CONFIG_JSONC */
339 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
340 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
341 nvme_print_flags_t flags;
342 struct config {
343 __u32 namespace_id;
344 bool_Bool raw_binary;
345 bool_Bool json;
346 };
347 int err;
348
349 struct config cfg = {
350 .namespace_id = NVME_NSID_ALL,
351 };
352
353 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG
, &cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0)
, CFG_FLAG, &cfg.json, 0, json, 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) } }
354 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG
, &cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0)
, CFG_FLAG, &cfg.json, 0, json, 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) } }
355 OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG
, &cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0)
, CFG_FLAG, &cfg.json, 0, json, 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) } }
356 OPT_FLAG_JSON("json", 'j', &cfg.json, json))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG
, &cfg.raw_binary, 0, raw, 0, }, {"json", 'j', ((void*)0)
, CFG_FLAG, &cfg.json, 0, json, 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) } }
;
357
358 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
359 if (err)
360 return err;
361
362 err = validate_output_format(nvme_args.output_format, &flags);
363 if (err < 0) {
364 nvme_show_error("Invalid output format")nvme_show_message(1, "Invalid output format");
365 return err;
366 }
367
368 err = nvme_get_nsid_log(hdl, cfg.namespace_id, false0, 0xca,
369 (void *)&smart_log, sizeof(smart_log));
370 if (!err) {
371 if (flags & JSON || cfg.json)
372 show_sfx_smart_log_jsn(&smart_log, cfg.namespace_id,
373 libnvme_transport_handle_get_name(hdl));
374 else if (!cfg.raw_binary)
375 show_sfx_smart_log(&smart_log, cfg.namespace_id,
376 libnvme_transport_handle_get_name(hdl));
377 else
378 d_raw((unsigned char *)&smart_log, sizeof(smart_log));
379 } else if (err > 0) {
380 nvme_show_status(err);
381 }
382 return err;
383}
384
385static void show_lat_stats_vanda(struct sfx_lat_stats_vanda *stats, int write)
386{
387 int i;
388
389 printf("ScaleFlux IO %s Command Latency Statistics\n", write ? "Write" : "Read");
390 printf("-------------------------------------\n");
391 printf("Major Revision : %u\n", stats->maj);
392 printf("Minor Revision : %u\n", stats->min);
393
394 printf("\nGroup 1: Range is 0-1ms, step is 32us\n");
395 for (i = 0; i < 32; i++)
396 printf("Bucket %2d: %u\n", i, stats->bucket_1[i]);
397
398 printf("\nGroup 2: Range is 1-32ms, step is 1ms\n");
399 for (i = 0; i < 31; i++)
400 printf("Bucket %2d: %u\n", i, stats->bucket_2[i]);
401
402 printf("\nGroup 3: Range is 32ms-1s, step is 32ms:\n");
403 for (i = 0; i < 31; i++)
404 printf("Bucket %2d: %u\n", i, stats->bucket_3[i]);
405
406 printf("\nGroup 4: Range is 1s-2s:\n");
407 printf("Bucket %2d: %u\n", 0, stats->bucket_4[0]);
408
409 printf("\nGroup 5: Range is 2s-4s:\n");
410 printf("Bucket %2d: %u\n", 0, stats->bucket_5[0]);
411
412 printf("\nGroup 6: Range is 4s+:\n");
413 printf("Bucket %2d: %u\n", 0, stats->bucket_6[0]);
414}
415
416static void show_lat_stats_myrtle(struct sfx_lat_stats_myrtle *stats, int write)
417{
418 int i;
419
420 printf("ScaleFlux IO %s Command Latency Statistics\n", write ? "Write" : "Read");
421 printf("-------------------------------------\n");
422 printf("Major Revision : %u\n", stats->maj);
423 printf("Minor Revision : %u\n", stats->min);
424
425 printf("\nGroup 1: Range is 0us~63us, step 1us\n");
426 for (i = 0; i < 64; i++)
427 printf("Bucket %2d: %u\n", i, stats->bucket_1[i]);
428
429 printf("\nGroup 2: Range is 63us~127us, step 1us\n");
430 for (i = 0; i < 64; i++)
431 printf("Bucket %2d: %u\n", i, stats->bucket_2[i]);
432
433 printf("\nGroup 3: Range is 127us~255us, step 2us\n");
434 for (i = 0; i < 64; i++)
435 printf("Bucket %2d: %u\n", i, stats->bucket_3[i]);
436
437 printf("\nGroup 4: Range is 255us~510us, step 4us\n");
438 for (i = 0; i < 64; i++)
439 printf("Bucket %2d: %u\n", i, stats->bucket_4[i]);
440
441 printf("\nGroup 5: Range is 510us~1.02ms step\n");
442 for (i = 0; i < 64; i++)
443 printf("Bucket %2d: %u\n", i, stats->bucket_5[i]);
444
445 printf("\nGroup 6: Range is 1.02ms~2.04ms step 16us\n");
446 for (i = 0; i < 64; i++)
447 printf("Bucket %2d: %u\n", i, stats->bucket_6[i]);
448
449 printf("\nGroup 7: Range is 2.04ms~4.08ms step 32us\n");
450 for (i = 0; i < 64; i++)
451 printf("Bucket %2d: %u\n", i, stats->bucket_7[i]);
452
453 printf("\nGroup 8: Range is 4.08ms~8.16ms step 64us\n");
454 for (i = 0; i < 64; i++)
455 printf("Bucket %2d: %u\n", i, stats->bucket_8[i]);
456
457 printf("\nGroup 9: Range is 8.16ms~16.32ms step 128us\n");
458 for (i = 0; i < 64; i++)
459 printf("Bucket %2d: %u\n", i, stats->bucket_9[i]);
460
461 printf("\nGroup 10: Range is 16.32ms~32.64ms step 256us\n");
462 for (i = 0; i < 64; i++)
463 printf("Bucket %2d: %u\n", i, stats->bucket_10[i]);
464
465 printf("\nGroup 11: Range is 32.64ms~65.28ms step 512us\n");
466 for (i = 0; i < 64; i++)
467 printf("Bucket %2d: %u\n", i, stats->bucket_11[i]);
468
469 printf("\nGroup 12: Range is 65.28ms~130.56ms step 1.024ms\n");
470 for (i = 0; i < 64; i++)
471 printf("Bucket %2d: %u\n", i, stats->bucket_12[i]);
472
473 printf("\nGroup 13: Range is 130.56ms~261.12ms step 2.048ms\n");
474 for (i = 0; i < 64; i++)
475 printf("Bucket %2d: %u\n", i, stats->bucket_13[i]);
476
477 printf("\nGroup 14: Range is 261.12ms~522.24ms step 4.096ms\n");
478 for (i = 0; i < 64; i++)
479 printf("Bucket %2d: %u\n", i, stats->bucket_14[i]);
480
481 printf("\nGroup 15: Range is 522.24ms~1.04s step 8.192ms\n");
482 for (i = 0; i < 64; i++)
483 printf("Bucket %2d: %u\n", i, stats->bucket_15[i]);
484
485 printf("\nGroup 16: Range is 1.04s~2.09s step 16.384ms\n");
486 for (i = 0; i < 64; i++)
487 printf("Bucket %2d: %u\n", i, stats->bucket_16[i]);
488
489 printf("\nGroup 17: Range is 2.09s~4.18s step 32.768ms\n");
490 for (i = 0; i < 64; i++)
491 printf("Bucket %2d: %u\n", i, stats->bucket_17[i]);
492
493 printf("\nGroup 18: Range is 4.18s~8.36s step 65.536ms\n");
494 for (i = 0; i < 64; i++)
495 printf("Bucket %2d: %u\n", i, stats->bucket_18[i]);
496
497 printf("\nGroup 19: Range is 8.36s~ step 131.072ms\n");
498 for (i = 0; i < 64; i++)
499 printf("Bucket %2d: %u\n", i, stats->bucket_19[i]);
500
501 printf("\nAverage latency statistics %" PRIu64"l" "u" "\n",
502 (uint64_t)stats->average);
503}
504
505
506static int get_lat_stats_log(int argc, char **argv, struct command *acmd, struct plugin *plugin)
507{
508 struct sfx_lat_stats stats;
509 char *desc = "Get ScaleFlux Latency Statistics log and show it.";
510 const char *raw = "dump output in binary format";
511 const char *write = "Get write statistics (read default)";
512 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
513 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
514 struct config {
515 bool_Bool raw_binary;
516 bool_Bool write;
517 };
518 int err;
519
520 struct config cfg = {
521 };
522
523 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &
cfg.raw_binary, 0, raw, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
524 OPT_FLAG("write", 'w', &cfg.write, write),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &
cfg.raw_binary, 0, raw, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
525 OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"write", 'w', ((void*)0), CFG_FLAG, &cfg.write, 0
, write, 0, }, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &
cfg.raw_binary, 0, raw, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR
, ((void*)0), 0, "Global options", 0, ((void*)0)}, {"verbose"
, 'v', "NUM", CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
;
526
527 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
528 if (err)
529 return err;
530
531 err = nvme_get_log_simple(hdl, cfg.write ? 0xc3 : 0xc1,
532 (void *)&stats, sizeof(stats));
533 if (!err) {
534 if ((stats.ver.maj == VANDA_MAJOR_IDX0) && (stats.ver.min == VANDA_MINOR_IDX0)) {
535 if (!cfg.raw_binary)
536 show_lat_stats_vanda(&stats.vanda, cfg.write);
537 else
538 d_raw((unsigned char *)&stats.vanda, sizeof(struct sfx_lat_stats_vanda));
539 } else if ((stats.ver.maj == MYRTLE_MAJOR_IDX4) && (stats.ver.min == MYRTLE_MINOR_IDX1)) {
540 if (!cfg.raw_binary)
541 show_lat_stats_myrtle(&stats.myrtle, cfg.write);
542 else
543 d_raw((unsigned char *)&stats.myrtle, sizeof(struct sfx_lat_stats_myrtle));
544 } else {
545 printf("ScaleFlux IO %s Command Latency Statistics Invalid Version Maj %d Min %d\n",
546 cfg.write ? "Write" : "Read", stats.ver.maj, stats.ver.min);
547 }
548 } else if (err > 0) {
549 nvme_show_status(err);
550 }
551 return err;
552}
553
554int sfx_nvme_get_log(struct libnvme_transport_handle *hdl, __u32 nsid, __u8 log_id, __u32 data_len, void *data)
555{
556 struct libnvme_passthru_cmd cmd = {
557 .opcode = nvme_admin_get_log_page,
558 .nsid = nsid,
559 .addr = (__u64)(uintptr_t) data,
560 .data_len = data_len,
561 };
562 __u32 numd = (data_len >> 2) - 1;
563 __u16 numdu = numd >> 16, numdl = numd & 0xffff;
564
565 cmd.cdw10 = log_id | (numdl << 16);
566 cmd.cdw11 = numdu;
567
568 return libnvme_exec_admin_passthru(hdl, &cmd);
569}
570
571/**
572 * @brief get bb table through admin_passthru
573 *
574 * @param fd
575 * @param buf
576 * @param size
577 *
578 * @return -1 fail ; 0 success
579 */
580static int get_bb_table(struct libnvme_transport_handle *hdl, __u32 nsid, unsigned char *buf, __u64 size)
581{
582 if (libnvme_transport_handle_get_fd(hdl) < 0 || !buf || size != 256*4096*sizeof(unsigned char)) {
583 fprintf(stderrstderr, "Invalid Param \r\n");
584 return -EINVAL22;
585 }
586
587 return sfx_nvme_get_log(hdl, nsid, SFX_LOG_BBT, size, (void *)buf);
588}
589
590/**
591 * @brief display bb table
592 *
593 * @param bd_table buffer that contain bb table dumped from driver
594 * @param table_size buffer size (BYTES), should at least has 8 bytes for mf_bb_count and grown_bb_count
595 */
596static void bd_table_show(unsigned char *bd_table, __u64 table_size)
597{
598 __u32 mf_bb_count = 0;
599 __u32 grown_bb_count = 0;
600 __u32 total_bb_count = 0;
601 __u32 remap_mfbb_count = 0;
602 __u32 remap_gbb_count = 0;
603 __u64 *bb_elem;
604 __u64 *elem_end = (__u64 *)(bd_table + table_size);
605 __u64 i;
606
607 /*buf should at least have 8bytes for mf_bb_count & total_bb_count*/
608 if (!bd_table || table_size < sizeof(__u64))
609 return;
610
611 mf_bb_count = *((__u32 *)bd_table);
612 grown_bb_count = *((__u32 *)(bd_table + sizeof(__u32)));
613 total_bb_count = *((__u32 *)(bd_table + 2 * sizeof(__u32)));
614 remap_mfbb_count = *((__u32 *)(bd_table + 3 * sizeof(__u32)));
615 remap_gbb_count = *((__u32 *)(bd_table + 4 * sizeof(__u32)));
616 bb_elem = (__u64 *)(bd_table + 5 * sizeof(__u32));
617
618 printf("Bad Block Table\n");
619 printf("MF_BB_COUNT: %u\n", mf_bb_count);
620 printf("GROWN_BB_COUNT: %u\n", grown_bb_count);
621 printf("TOTAL_BB_COUNT: %u\n", total_bb_count);
622 printf("REMAP_MFBB_COUNT: %u\n", remap_mfbb_count);
623 printf("REMAP_GBB_COUNT: %u\n", remap_gbb_count);
624
625 printf("REMAP_MFBB_TABLE [");
626 i = 0;
627 while (bb_elem < elem_end && i < remap_mfbb_count) {
628 printf(" 0x%"PRIx64"l" "x""", (uint64_t)*(bb_elem++));
629 i++;
630 }
631 printf(" ]\n");
632
633 printf("REMAP_GBB_TABLE [");
634 i = 0;
635 while (bb_elem < elem_end && i < remap_gbb_count) {
636 printf(" 0x%"PRIx64"l" "x""", (uint64_t)*(bb_elem++));
637 i++;
638 }
639 printf(" ]\n");
640}
641
642/**
643 * @brief "hooks of sfx get-bad-block"
644 *
645 * @param argc
646 * @param argv
647 * @param cmd
648 * @param plugin
649 *
650 * @return
651 */
652static int sfx_get_bad_block(int argc, char **argv, struct command *acmd, struct plugin *plugin)
653{
654 const __u64 buf_size = 256*4096*sizeof(unsigned char);
655 unsigned char *data_buf;
656 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
657 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
658 int err = 0;
659
660 char *desc = "Get bad block table of sfx block device.";
661
662 NVME_ARGS(opts)struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0
, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM", CFG_INCREMENT
, &nvme_args.verbose, 0, "Increase output verbosity", 0, }
, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args.output_format
, 1, "Output format: normal|json|binary|tabular", 0, }, {"timeout"
, 0, "NUM", CFG_POSITIVE, &nvme_args.timeout, 1, "timeout value, in milliseconds"
, 0, }, {"dry-run", 0, ((void*)0), CFG_FLAG, &nvme_args.dry_run
, 0, "show command instead of executing", 0, }, {"no-retries"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_retries, 0, "disable retry logic on errors"
, 0, }, {"no-ioctl-probing", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_ioctl_probing, 0, "disable 64-bit IOCTL support probing",
0, }, {"output-format-version", 0, "NUM", CFG_POSITIVE, &
nvme_args.output_format_ver, 1, "output format version: 1|2",
0, }, {"human-readable", 'H', ((void*)0), CFG_FLAG, &nvme_args
.verbose, 0, ((void*)0), 0, ((void*)0), 1}, { ((void*)0) } }
;
663
664 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
665 if (err)
666 return err;
667
668 data_buf = malloc(buf_size);
669 if (!data_buf) {
670 fprintf(stderrstderr, "malloc fail, errno %d\r\n", errno(*__errno_location ()));
671 return -1;
672 }
673
674 err = get_bb_table(hdl, NVME_NSID_ALL, data_buf, buf_size);
675 if (err < 0) {
676 perror("get-bad-block");
677 } else if (err) {
678 nvme_show_status(err);
679 } else {
680 bd_table_show(data_buf, buf_size);
681 printf("ScaleFlux get bad block table: success\n");
682 }
683
684 free(data_buf);
685 return 0;
686}
687
688static void show_cap_info(struct sfx_freespace_ctx *ctx)
689{
690
691 printf("logic capacity:%5lluGB(0x%"PRIx64"l" "x"")\n",
692 IDEMA_CAP2GB(ctx->user_space)(((__u64)ctx->user_space - 97696368ULL) / 1953504ULL + 50ULL
)
, (uint64_t)ctx->user_space);
693 printf("provisioned capacity:%5lluGB(0x%"PRIx64"l" "x"")\n",
694 IDEMA_CAP2GB(ctx->phy_space)(((__u64)ctx->phy_space - 97696368ULL) / 1953504ULL + 50ULL
)
, (uint64_t)ctx->phy_space);
695 printf("free provisioned capacity:%5lluGB(0x%"PRIx64"l" "x"")\n",
696 IDEMA_CAP2GB(ctx->free_space)(((__u64)ctx->free_space - 97696368ULL) / 1953504ULL + 50ULL
)
, (uint64_t)ctx->free_space);
697 printf("used provisioned capacity:%5lluGB(0x%"PRIx64"l" "x"")\n",
698 IDEMA_CAP2GB(ctx->phy_space)(((__u64)ctx->phy_space - 97696368ULL) / 1953504ULL + 50ULL
)
- IDEMA_CAP2GB(ctx->free_space)(((__u64)ctx->free_space - 97696368ULL) / 1953504ULL + 50ULL
)
,
699 (uint64_t)(ctx->phy_space - ctx->free_space));
700 printf("map_unit :0x%"PRIx64"l" "x""K\n", (uint64_t)(ctx->map_unit * 4));
701}
702
703static int query_cap_info(int argc, char **argv, struct command *acmd, struct plugin *plugin)
704{
705 struct sfx_freespace_ctx sfctx = { 0 };
706 char *desc = "query current capacity info";
707 const char *raw = "dump output in binary format";
708 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
709 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
710 struct config {
711 bool_Bool raw_binary;
712 };
713 struct config cfg;
714 int err = 0;
715
716 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, raw, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
717 OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"raw-binary", 'b', ((void*)0), CFG_FLAG, &cfg.raw_binary
, 0, raw, 0, }, {"", 0, ((void*)0), CFG_GROUP_SEPARATOR, ((void
*)0), 0, "Global options", 0, ((void*)0)}, {"verbose", 'v', "NUM"
, CFG_INCREMENT, &nvme_args.verbose, 0, "Increase output verbosity"
, 0, }, {"output-format", 'o', "FMT", CFG_STRING, &nvme_args
.output_format, 1, "Output format: normal|json|binary|tabular"
, 0, }, {"timeout", 0, "NUM", CFG_POSITIVE, &nvme_args.timeout
, 1, "timeout value, in milliseconds", 0, }, {"dry-run", 0, (
(void*)0), CFG_FLAG, &nvme_args.dry_run, 0, "show command instead of executing"
, 0, }, {"no-retries", 0, ((void*)0), CFG_FLAG, &nvme_args
.no_retries, 0, "disable retry logic on errors", 0, }, {"no-ioctl-probing"
, 0, ((void*)0), CFG_FLAG, &nvme_args.no_ioctl_probing, 0
, "disable 64-bit IOCTL support probing", 0, }, {"output-format-version"
, 0, "NUM", CFG_POSITIVE, &nvme_args.output_format_ver, 1
, "output format version: 1|2", 0, }, {"human-readable", 'H',
((void*)0), CFG_FLAG, &nvme_args.verbose, 0, ((void*)0),
0, ((void*)0), 1}, { ((void*)0) } }
;
718
719 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
720 if (err)
721 return err;
722
723 if (nvme_query_cap(hdl, NVME_NSID_ALL, sizeof(sfctx), &sfctx)) {
724 perror("sfx-query-cap");
725 err = -1;
726 }
727
728 if (!err) {
729 if (!cfg.raw_binary)
730 show_cap_info(&sfctx);
731 else
732 d_raw((unsigned char *)&sfctx, sizeof(sfctx));
733 }
734 return err;
735}
736
737static int change_sanity_check(struct libnvme_transport_handle *hdl, __u64 trg_in_4k, int *shrink)
738{
739 struct sfx_freespace_ctx freespace_ctx = { 0 };
740 struct sysinfo s_info;
741 __u64 mem_need = 0;
742 __u64 cur_in_4k = 0;
743 __u64 provisioned_cap_4k = 0;
744 int extend = 0;
745
746 if (nvme_query_cap(hdl, NVME_NSID_ALL, sizeof(freespace_ctx), &freespace_ctx))
747 return -1;
748
749 /*
750 * capacity illegal check
751 */
752 provisioned_cap_4k = freespace_ctx.phy_space >>
753 (SFX_PAGE_SHIFT12 - SECTOR_SHIFT9);
754 if (trg_in_4k < provisioned_cap_4k ||
755 trg_in_4k > ((__u64)provisioned_cap_4k * 4)) {
756 fprintf(stderrstderr,
757 "WARNING: Only support 1.0~4.0 x provisioned capacity!\n");
758 if (trg_in_4k < provisioned_cap_4k)
759 fprintf(stderrstderr,
760 "WARNING: The target capacity is less than 1.0 x provisioned capacity!\n");
761 else
762 fprintf(stderrstderr,
763 "WARNING: The target capacity is larger than 4.0 x provisioned capacity!\n");
764 return -1;
765 }
766 if (trg_in_4k > ((__u64)provisioned_cap_4k*4)) {
767 fprintf(stderrstderr, "WARNING: the target capacity is too large\n");
768 return -1;
769 }
770
771 /*
772 * check whether mem enough if extend
773 */
774 cur_in_4k = freespace_ctx.user_space >> (SFX_PAGE_SHIFT12 - SECTOR_SHIFT9);
775 extend = (cur_in_4k <= trg_in_4k);
776 if (extend) {
777 if (sysinfo(&s_info) < 0) {
778 printf("change-cap query mem info fail\n");
779 return -1;
780 }
781 mem_need = (trg_in_4k - cur_in_4k) * 8;
782 if (s_info.freeram <= 10 || mem_need > s_info.freeram) {
783 fprintf(stderrstderr,
784 "WARNING: Free memory is not enough! Please drop cache or extend more memory and retry\n"
785 "WARNING: Memory needed is %"PRIu64"l" "u"", free memory is %"PRIu64"l" "u""\n",
786 (uint64_t)mem_need, (uint64_t)s_info.freeram);
787 return -1;
788 }
789 }
790 *shrink = !extend;
791
792 return 0;
793}
794
795/**
796 * @brief prompt and get user confirm input
797 *
798 * @param str, prompt string
799 *
800 * @return 0, canceled; 1 confirmed
801 */
802static int sfx_confirm_change(const char *str)
803{
804 unsigned char confirm;
805
806 fprintf(stderrstderr, "WARNING: %s.\n"
807 "Use the force [--force] option to suppress this warning.\n", str);
808
809 fprintf(stderrstderr, "Confirm Y/y, Others cancel:\n");
810 confirm = (unsigned char)fgetc(stdinstdin);
811 if (confirm != 'y' && confirm != 'Y') {
812 fprintf(stderrstderr, "Canceled.\n");
813 return 0;
814 }
815 fprintf(stderrstderr, "Sending operation ...\n");
816 return 1;
817}
818
819static int change_cap(int argc, char **argv, struct command *acmd, struct plugin *plugin)
820{
821 char *desc = "dynamic change capacity";
822 const char *cap_gb = "cap size in GB";
823 const char *cap_byte = "cap size in byte";
824 const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command";
825 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
826 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
827 __u64 cap_in_4k = 0;
828 __u64 cap_in_sec = 0;
829 int shrink = 0;
830 int err = -1;
831
832 struct config {
833 __u64 cap_in_byte;
834 __u32 capacity_in_gb;
835 bool_Bool force;
836 };
837
838 struct config cfg = {
839 .cap_in_byte = 0,
840 .capacity_in_gb = 0,
841 .force = 0,
842 };
843
844 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"cap", 'c', "NUM", CFG_POSITIVE, &cfg.capacity_in_gb
, 1, cap_gb, 0, }, {"cap-byte", 'z', "IONUM", CFG_LONG_SUFFIX
, &cfg.cap_in_byte, 1, cap_byte, 0, }, {"force", 'f', ((void
*)0), CFG_FLAG, &cfg.force, 0, force, 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) } }
845 OPT_UINT("cap", 'c', &cfg.capacity_in_gb, cap_gb),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"cap", 'c', "NUM", CFG_POSITIVE, &cfg.capacity_in_gb
, 1, cap_gb, 0, }, {"cap-byte", 'z', "IONUM", CFG_LONG_SUFFIX
, &cfg.cap_in_byte, 1, cap_byte, 0, }, {"force", 'f', ((void
*)0), CFG_FLAG, &cfg.force, 0, force, 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) } }
846 OPT_SUFFIX("cap-byte", 'z', &cfg.cap_in_byte, cap_byte),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"cap", 'c', "NUM", CFG_POSITIVE, &cfg.capacity_in_gb
, 1, cap_gb, 0, }, {"cap-byte", 'z', "IONUM", CFG_LONG_SUFFIX
, &cfg.cap_in_byte, 1, cap_byte, 0, }, {"force", 'f', ((void
*)0), CFG_FLAG, &cfg.force, 0, force, 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) } }
847 OPT_FLAG("force", 'f', &cfg.force, force))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"cap", 'c', "NUM", CFG_POSITIVE, &cfg.capacity_in_gb
, 1, cap_gb, 0, }, {"cap-byte", 'z', "IONUM", CFG_LONG_SUFFIX
, &cfg.cap_in_byte, 1, cap_byte, 0, }, {"force", 'f', ((void
*)0), CFG_FLAG, &cfg.force, 0, force, 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) } }
;
848
849 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
850 if (err)
851 return err;
852
853 cap_in_sec = IDEMA_CAP(cfg.capacity_in_gb)(((__u64)cfg.capacity_in_gb - 50ULL) * 1953504ULL + 97696368ULL
)
;
854 cap_in_4k = cap_in_sec >> 3;
855 if (cfg.cap_in_byte)
856 cap_in_4k = cfg.cap_in_byte >> 12;
857 printf("%dG %"PRIu64"l" "u""B %"PRIu64"l" "u"" 4K\n",
858 cfg.capacity_in_gb, (uint64_t)cfg.cap_in_byte, (uint64_t)cap_in_4k);
859
860 if (change_sanity_check(hdl, cap_in_4k, &shrink)) {
861 printf("ScaleFlux change-capacity: fail\n");
862 return err;
863 }
864
865 if (!cfg.force && shrink && !sfx_confirm_change("Changing Cap may irrevocably delete this device's data")) {
866 return 0;
867 }
868
869 err = nvme_change_cap(hdl, NVME_NSID_ALL, cap_in_4k);
870 if (err < 0) {
871 perror("sfx-change-cap");
872 } else if (err) {
873 nvme_show_status(err);
874 } else {
875 printf("ScaleFlux change-capacity: success\n");
876 ioctl(libnvme_transport_handle_get_fd(hdl), BLKRRPART(((0U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8))
| (((95)) << 0) | ((0) << ((0 +8)+8)))
);
877 }
878 return err;
879}
880
881static int sfx_verify_chr(struct libnvme_transport_handle *hdl)
882{
883 static struct stat nvme_stat;
884 int err = fstat(libnvme_transport_handle_get_fd(hdl), &nvme_stat);
885
886 if (err < 0) {
887 perror("fstat");
888 return errno(*__errno_location ());
889 }
890 if (!S_ISCHR(nvme_stat.st_mode)((((nvme_stat.st_mode)) & 0170000) == (0020000))) {
891 fprintf(stderrstderr,
892 "Error: requesting clean card on non-controller handle\n");
893 return -ENOTBLK15;
894 }
895 return 0;
896}
897
898static int sfx_clean_card(struct libnvme_transport_handle *hdl)
899{
900 int ret;
901
902 ret = sfx_verify_chr(hdl);
903 if (ret)
904 return ret;
905 ret = ioctl(libnvme_transport_handle_get_fd(hdl), NVME_IOCTL_CLR_CARD(((0U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8)) |
(((0x47)) << 0) | ((0) << ((0 +8)+8)))
);
906 if (ret)
907 perror("Ioctl Fail.");
908 else
909 printf("ScaleFlux clean card success\n");
910
911 return ret;
912}
913
914char *sfx_feature_to_string(int feature)
915{
916 switch (feature) {
917 case SFX_FEAT_ATOMIC:
918 return "ATOMIC";
919 case SFX_FEAT_UP_P_CAP:
920 return "UPDATE_PROVISION_CAPACITY";
921 default:
922 return "Unknown";
923 }
924}
925
926static int sfx_set_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin)
927{
928 char *desc = "ScaleFlux internal set features\n"
929 "feature id 1: ATOMIC\n"
930 "value 0: Disable atomic write\n"
931 " 1: Enable atomic write";
932 const char *value = "new value of feature (required)";
933 const char *feature_id = "hex feature name (required)";
934 const char *namespace_id = "desired namespace";
935 const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command";
936 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
937 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
938 struct nvme_id_ns ns;
939 int err = 0;
940
941 struct config {
942 __u32 namespace_id;
943 __u32 feature_id;
944 __u32 value;
945 bool_Bool force;
946 };
947 struct config cfg = {
948 .namespace_id = 1,
949 .feature_id = 0,
950 .value = 0,
951 .force = 0,
952 };
953
954 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"feature-id", 'f', "NUM", CFG_POSITIVE
, &cfg.feature_id, 1, feature_id, 0, }, {"value", 'V', "NUM"
, CFG_POSITIVE, &cfg.value, 1, value, 0, }, {"force", 's'
, ((void*)0), CFG_FLAG, &cfg.force, 0, force, 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) } }
955 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"feature-id", 'f', "NUM", CFG_POSITIVE
, &cfg.feature_id, 1, feature_id, 0, }, {"value", 'V', "NUM"
, CFG_POSITIVE, &cfg.value, 1, value, 0, }, {"force", 's'
, ((void*)0), CFG_FLAG, &cfg.force, 0, force, 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) } }
956 OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"feature-id", 'f', "NUM", CFG_POSITIVE
, &cfg.feature_id, 1, feature_id, 0, }, {"value", 'V', "NUM"
, CFG_POSITIVE, &cfg.value, 1, value, 0, }, {"force", 's'
, ((void*)0), CFG_FLAG, &cfg.force, 0, force, 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) } }
957 OPT_UINT("value", 'V', &cfg.value, value),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"feature-id", 'f', "NUM", CFG_POSITIVE
, &cfg.feature_id, 1, feature_id, 0, }, {"value", 'V', "NUM"
, CFG_POSITIVE, &cfg.value, 1, value, 0, }, {"force", 's'
, ((void*)0), CFG_FLAG, &cfg.force, 0, force, 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) } }
958 OPT_FLAG("force", 's', &cfg.force, force))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"feature-id", 'f', "NUM", CFG_POSITIVE
, &cfg.feature_id, 1, feature_id, 0, }, {"value", 'V', "NUM"
, CFG_POSITIVE, &cfg.value, 1, value, 0, }, {"force", 's'
, ((void*)0), CFG_FLAG, &cfg.force, 0, force, 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) } }
;
959
960 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
961 if (err)
962 return err;
963
964 if (!cfg.feature_id) {
965 fprintf(stderrstderr, "feature-id required param\n");
966 return -EINVAL22;
967 }
968
969 if (cfg.feature_id == SFX_FEAT_CLR_CARD) {
970 /*Warning for clean card*/
971 if (!cfg.force && !sfx_confirm_change("Going to clean device's data, confirm umount fs and try again")) {
972 return 0;
973 } else {
974 return sfx_clean_card(hdl);
975 }
976
977 }
978
979 if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value) {
980 if (cfg.namespace_id != NVME_NSID_ALL) {
981 err = nvme_identify_ns(hdl, cfg.namespace_id, &ns);
982 if (err) {
983 if (err < 0)
984 perror("identify-namespace");
985 else
986 nvme_show_status(err);
987 return err;
988 }
989 /*
990 * atomic only support with sector-size = 4k now
991 */
992 if ((ns.flbas & 0xf) != 1) {
993 printf("Please change-sector size to 4K, then retry\n");
994 return -EFAULT14;
995 }
996 }
997 } else if (cfg.feature_id == SFX_FEAT_UP_P_CAP) {
998 if (cfg.value <= 0) {
999 fprintf(stderrstderr, "Invalid Param\n");
1000 return -EINVAL22;
1001 }
1002
1003 /*Warning for change pacp by GB*/
1004 if (!cfg.force && !sfx_confirm_change("Changing physical capacity may irrevocably delete this device's data")) {
1005 return 0;
1006 }
1007 }
1008
1009 err = nvme_sfx_set_features(hdl, cfg.namespace_id,
1010 cfg.feature_id,
1011 cfg.value);
1012
1013 if (err < 0) {
1014 perror("ScaleFlux-set-feature");
1015 return errno(*__errno_location ());
1016 } else if (!err) {
1017 printf("ScaleFlux set-feature:%#02x (%s), value:%d\n", cfg.feature_id,
1018 sfx_feature_to_string(cfg.feature_id), cfg.value);
1019 } else if (err > 0) {
1020 nvme_show_status(err);
1021 }
1022
1023 return err;
1024}
1025
1026static int sfx_get_feature(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1027{
1028 char *desc = "ScaleFlux internal set features\n"
1029 "feature id 1: ATOMIC";
1030 const char *feature_id = "hex feature name (required)";
1031 const char *namespace_id = "desired namespace";
1032 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1033 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1034 __u32 result = 0;
1035 int err = 0;
1036
1037 struct config {
1038 __u32 namespace_id;
1039 __u32 feature_id;
1040 };
1041 struct config cfg = {
1042 .namespace_id = 0,
1043 .feature_id = 0,
1044 };
1045
1046 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"feature-id", 'f', "NUM", CFG_POSITIVE
, &cfg.feature_id, 1, feature_id, 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) } }
1047 OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"feature-id", 'f', "NUM", CFG_POSITIVE
, &cfg.feature_id, 1, feature_id, 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) } }
1048 OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"feature-id", 'f', "NUM", CFG_POSITIVE
, &cfg.feature_id, 1, feature_id, 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) } }
;
1049
1050 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1051 if (err)
1052 return err;
1053
1054 if (!cfg.feature_id) {
1055 fprintf(stderrstderr, "feature-id required param\n");
1056 return -EINVAL22;
1057 }
1058
1059 err = nvme_sfx_get_features(hdl, cfg.namespace_id,
1060 cfg.feature_id, &result);
1061 if (err < 0) {
1062 perror("ScaleFlux-get-feature");
1063 return errno(*__errno_location ());
1064 } else if (!err) {
1065 printf("ScaleFlux get-feature:%02x (%s), value:%d\n", cfg.feature_id,
1066 sfx_feature_to_string(cfg.feature_id), result);
1067 } else if (err > 0) {
1068 nvme_show_status(err);
1069 }
1070
1071 return err;
1072
1073}
1074
1075static int nvme_parse_evtlog(void *pevent_log_info, __u32 log_len, char *output)
1076{
1077 __u32 offset = 0;
1078 __u32 length = log_len;
1079 __u16 fw_core;
1080 __u64 fw_time;
1081 __u8 code_level;
1082 __u8 code_type;
1083 char str_buffer[512];
1084 __u32 str_pos;
1085 FILE *fd;
1086 int err = 0;
1087
1088 enum sfx_evtlog_level {
1089 sfx_evtlog_level_warning,
1090 sfx_evtlog_level_error,
1091 };
1092
1093 const char *sfx_evtlog_warning[4] = {
1094 "RESERVED",
1095 "TOO_MANY_BB",
1096 "LOW_SPACE",
1097 "HIGH_TEMPERATURE"
1098 };
1099
1100 const char *sfx_evtlog_error[14] = {
1101 "RESERVED",
1102 "HAS_ASSERT",
1103 "HAS_PANIC_DUMP",
1104 "INVALID_FORMAT_CAPACITY",
1105 "MAT_FAILED",
1106 "FREEZE_DUE_TO_RECOVERY_FAILED",
1107 "RFS_BROKEN",
1108 "MEDIA_ERR_ON_PAGE_IN",
1109 "MEDIA_ERR_ON_MPAGE_HEADER",
1110 "CAPACITOR_BROKEN",
1111 "READONLY_DUE_TO_RECOVERY_FAILED",
1112 "RD_ERR_IN_GSD_RECOVERY",
1113 "RD_ERR_ON_PF_RECOVERY",
1114 "MEDIA_ERR_ON_FULL_RECOVERY"
1115 };
1116
1117 struct sfx_nvme_evtlog_info {
1118 __u16 time_stamp[4];
1119 __u64 magic1;
1120 __u8 reverse[10];
1121 char evt_name[32];
1122 __u64 magic2;
1123 char fw_ver[24];
1124 char bl2_ver[32];
1125 __u16 code;
1126 __u16 assert_id;
1127 } __packed__attribute__((__packed__));
1128
1129 struct sfx_nvme_evtlog_info *info = NULL((void*)0);
1130
1131 fd = fopen(output, "w+");
1132 if (!fd) {
1133 fprintf(stderrstderr, "Failed to open %s file to write\n", output);
1134 err = ENOENT2;
1135 goto ret;
1136 }
1137
1138 while (length > 0) {
1139 info = (struct sfx_nvme_evtlog_info *)(pevent_log_info + offset);
1140
1141 if ((info->magic1 == 0x474F4C545645) &&
1142 (info->magic2 == 0x38B0B3ABA9BA)) {
1143
1144 memset(str_buffer, 0, 512);
1145 str_pos = 0;
1146
1147 fw_core = info->time_stamp[3];
1148 snprintf(str_buffer + str_pos, 16, "[%d-", fw_core);
1149 str_pos = strlen(str_buffer);
1150
1151 fw_time = ((__u64)info->time_stamp[2] << 32) + ((__u64)info->time_stamp[1] << 16) + (__u64)info->time_stamp[0];
1152 convert_ts(fw_time, str_buffer + str_pos);
1153 str_pos = strlen(str_buffer);
1154
1155 strcpy(str_buffer + str_pos, "] event-log:\n");
1156 str_pos = strlen(str_buffer);
1157
1158 snprintf(str_buffer + str_pos, 128,
1159 " > fw_version: %s\n > bl2_version: %s\n",
1160 info->fw_ver, info->bl2_ver);
1161 str_pos = strlen(str_buffer);
1162
1163 code_level = (info->code & 0x100) >> 8;
1164 code_type = (info->code % 0x100);
1165 if (code_level == sfx_evtlog_level_warning) {
1166 snprintf(str_buffer + str_pos, 128,
1167 " > error_str: [WARNING][%s]\n\n",
1168 sfx_evtlog_warning[code_type]);
1169 } else {
1170 if (info->assert_id)
1171 snprintf(str_buffer + str_pos, 128,
1172 " > error_str: [ERROR][%s]\n > assert_id: %d\n\n",
1173 sfx_evtlog_error[code_type], info->assert_id);
1174 else
1175 snprintf(str_buffer + str_pos, 128,
1176 " > error_str: [ERROR][%s]\n\n",
1177 sfx_evtlog_error[code_type]);
1178 }
1179 str_pos = strlen(str_buffer);
1180
1181 if (fwrite(str_buffer, 1, str_pos, fd) != str_pos) {
1182 fprintf(stderrstderr, "Failed to write parse result to output file\n");
1183 goto close_fd;
1184 }
1185 }
1186
1187 offset++;
1188 length--;
1189
1190 if (!(offset % (log_len / 100)) || (offset == log_len))
1191 util_spinner("Parse", (float) (offset) / (float) (log_len));
1192 }
1193
1194 printf("\nParse-evtlog: Success\n");
1195
1196close_fd:
1197 fclose(fd);
1198ret:
1199 return err;
1200}
1201
1202static int nvme_dump_evtlog(struct libnvme_transport_handle *hdl, __u32 namespace_id, __u32 storage_medium,
1203 char *file, bool_Bool parse, char *output)
1204{
1205 __cleanup_huge__attribute__((cleanup(libnvme_free_huge))) struct libnvme_mem_huge mh = { 0, };
1206 struct nvme_persistent_event_log *pevent;
1207 void *pevent_log_info;
1208 __u8 lsp_base, lsp;
1209 __u32 offset = 0;
1210 __u32 length = 0;
1211 __u32 single_len;
1212 __u32 log_len;
1213 __u32 len;
1214 __u64 lpo;
1215 void *log;
1216 int err = 0;
1217 FILE *fd = NULL((void*)0);
1218 struct libnvme_passthru_cmd cmd;
1219
1220 if (!storage_medium) {
1221 lsp_base = 0;
1222 single_len = 64 * 1024 - 4;
1223 } else {
1224 lsp_base = 4;
1225 single_len = 32 * 1024;
1226 }
1227
1228 pevent = calloc(sizeof(*pevent), sizeof(__u8));
Result of 'calloc' is converted to a pointer of type 'struct nvme_persistent_event_log', which is incompatible with sizeof operand type '__u8'
1229 if (!pevent) {
1230 err = -ENOMEM12;
1231 goto ret;
1232 }
1233
1234 lsp = lsp_base + NVME_PEVENT_LOG_RELEASE_CTX;
1235 log = pevent;
1236 len = sizeof(*pevent);
1237 nvme_init_get_log(&cmd, NVME_NSID_NONE, NVME_LOG_LID_PERSISTENT_EVENT,
1238 NVME_CSI_NVM, log, len);
1239 cmd.cdw10 |= NVME_FIELD_ENCODE(lsp,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
1240 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
1241 NVME_LOG_CDW10_LSP_MASK)(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
;
1242 err = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
1243 if (err) {
1244 fprintf(stderrstderr, "Unable to get evtlog lsp=0x%x, ret = 0x%x\n",
1245 lsp, err);
1246 goto free_pevent;
1247 }
1248
1249 lsp = lsp_base + NVME_PEVENT_LOG_EST_CTX_AND_READ;
1250 nvme_init_get_log(&cmd, NVME_NSID_NONE, NVME_LOG_LID_PERSISTENT_EVENT,
1251 NVME_CSI_NVM, log, len);
1252 cmd.cdw10 |= NVME_FIELD_ENCODE(lsp,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
1253 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
1254 NVME_LOG_CDW10_LSP_MASK)(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
;
1255 err = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
1256 if (err) {
1257 fprintf(stderrstderr, "Unable to get evtlog lsp=0x%x, ret = 0x%x\n",
1258 lsp, err);
1259 goto free_pevent;
1260 }
1261
1262 log_len = le64_to_cpu(pevent->tll);
1263 if (log_len % 4)
1264 log_len = (log_len / 4 + 1) * 4;
1265
1266 pevent_log_info = libnvme_alloc_huge(single_len, &mh);
1267 if (!pevent_log_info) {
1268 err = -ENOMEM12;
1269 goto free_pevent;
1270 }
1271
1272 fd = fopen(file, "wb+");
1273 if (!fd) {
1274 fprintf(stderrstderr, "Failed to open %s file to write\n", file);
1275 err = ENOENT2;
1276 goto free_pevent;
1277 }
1278
1279 lsp = lsp_base + NVME_PEVENT_LOG_READ;
1280 log = pevent_log_info;
1281 length = log_len;
1282 while (length > 0) {
1283 lpo = offset;
1284 if (length > single_len) {
1285 len = single_len;
1286 } else {
1287 memset(log, 0, len);
1288 len = length;
1289 }
1290 nvme_init_get_log(&cmd, NVME_NSID_NONE,
1291 NVME_LOG_LID_PERSISTENT_EVENT,
1292 NVME_CSI_NVM, log, len);
1293 cmd.cdw10 |= NVME_FIELD_ENCODE(lsp,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
1294 NVME_LOG_CDW10_LSP_SHIFT,(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
1295 NVME_LOG_CDW10_LSP_MASK)(((__u32)(lsp) & (NVME_LOG_CDW10_LSP_MASK)) << (NVME_LOG_CDW10_LSP_SHIFT
))
;
1296 nvme_init_get_log_lpo(&cmd, lpo);
1297 err = libnvme_get_log(hdl, &cmd, false0, NVME_LOG_PAGE_PDU_SIZE4096);
1298 if (err) {
1299 fprintf(stderrstderr,
1300 "Unable to get evtlog offset=0x%x len 0x%x ret = 0x%x\n",
1301 offset, len, err);
1302 goto close_fd;
1303 }
1304
1305 if (fwrite(log, 1, len, fd) != len) {
1306 fprintf(stderrstderr, "Failed to write evtlog to file\n");
1307 goto close_fd;
1308 }
1309
1310 offset += len;
1311 length -= len;
1312 util_spinner("Parse", (float) (offset) / (float) (log_len));
1313 }
1314
1315 printf("\nDump-evtlog: Success\n");
1316
1317 if (parse) {
1318 libnvme_free_huge(&mh);
1319 pevent_log_info = libnvme_alloc_huge(log_len, &mh);
1320 if (!pevent_log_info) {
1321 fprintf(stderrstderr, "Failed to alloc enough memory 0x%x to parse evtlog\n", log_len);
1322 err = -ENOMEM12;
1323 goto close_fd;
1324 }
1325
1326 fclose(fd);
1327 fd = fopen(file, "rb");
1328 if (!fd) {
1329 fprintf(stderrstderr, "Failed to open %s file to read\n", file);
1330 err = ENOENT2;
1331 goto free_pevent;
1332 }
1333 if (fread(pevent_log_info, 1, log_len, fd) != log_len) {
1334 fprintf(stderrstderr, "Failed to read evtlog to buffer\n");
1335 goto close_fd;
1336 }
1337
1338 err = nvme_parse_evtlog(pevent_log_info, log_len, output);
1339 }
1340
1341close_fd:
1342 fclose(fd);
1343free_pevent:
1344 free(pevent);
1345ret:
1346 return err;
1347}
1348
1349static int sfx_dump_evtlog(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1350{
1351 char *desc = "dump evtlog into file and parse";
1352 const char *file = "evtlog file(required)";
1353 const char *namespace_id = "desired namespace";
1354 const char *storage_medium = "evtlog storage medium\n"
1355 "0: nand(default) 1: nor";
1356 const char *parse = "parse error & warning evtlog from evtlog file";
1357 const char *output = "parse result output file";
1358 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1359 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1360 int err = 0;
1361
1362 struct config {
1363 char *file;
1364 __u32 namespace_id;
1365 __u32 storage_medium;
1366 bool_Bool parse;
1367 char *output;
1368 };
1369 struct config cfg = {
1370 .file = NULL((void*)0),
1371 .namespace_id = NVME_NSID_ALL,
1372 .storage_medium = 0,
1373 .parse = false0,
1374 .output = NULL((void*)0),
1375 };
1376
1377 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"file", 'f', "FILE", CFG_STRING, &cfg.file, 1, file
, 0, }, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"storage_medium", 's', "NUM", CFG_POSITIVE
, &cfg.storage_medium, 1, storage_medium, 0, }, {"parse",
'p', ((void*)0), CFG_FLAG, &cfg.parse, 0, parse, 0, }, {
"output", 'O', "FILE", CFG_STRING, &cfg.output, 1, output
, 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) } }
1378 OPT_FILE("file", 'f', &cfg.file, file),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"file", 'f', "FILE", CFG_STRING, &cfg.file, 1, file
, 0, }, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"storage_medium", 's', "NUM", CFG_POSITIVE
, &cfg.storage_medium, 1, storage_medium, 0, }, {"parse",
'p', ((void*)0), CFG_FLAG, &cfg.parse, 0, parse, 0, }, {
"output", 'O', "FILE", CFG_STRING, &cfg.output, 1, output
, 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) } }
1379 OPT_UINT("namespace_id", 'n', &cfg.namespace_id, namespace_id),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"file", 'f', "FILE", CFG_STRING, &cfg.file, 1, file
, 0, }, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"storage_medium", 's', "NUM", CFG_POSITIVE
, &cfg.storage_medium, 1, storage_medium, 0, }, {"parse",
'p', ((void*)0), CFG_FLAG, &cfg.parse, 0, parse, 0, }, {
"output", 'O', "FILE", CFG_STRING, &cfg.output, 1, output
, 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) } }
1380 OPT_UINT("storage_medium", 's', &cfg.storage_medium, storage_medium),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"file", 'f', "FILE", CFG_STRING, &cfg.file, 1, file
, 0, }, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"storage_medium", 's', "NUM", CFG_POSITIVE
, &cfg.storage_medium, 1, storage_medium, 0, }, {"parse",
'p', ((void*)0), CFG_FLAG, &cfg.parse, 0, parse, 0, }, {
"output", 'O', "FILE", CFG_STRING, &cfg.output, 1, output
, 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) } }
1381 OPT_FLAG("parse", 'p', &cfg.parse, parse),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"file", 'f', "FILE", CFG_STRING, &cfg.file, 1, file
, 0, }, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"storage_medium", 's', "NUM", CFG_POSITIVE
, &cfg.storage_medium, 1, storage_medium, 0, }, {"parse",
'p', ((void*)0), CFG_FLAG, &cfg.parse, 0, parse, 0, }, {
"output", 'O', "FILE", CFG_STRING, &cfg.output, 1, output
, 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) } }
1382 OPT_FILE("output", 'O', &cfg.output, output))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"file", 'f', "FILE", CFG_STRING, &cfg.file, 1, file
, 0, }, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"storage_medium", 's', "NUM", CFG_POSITIVE
, &cfg.storage_medium, 1, storage_medium, 0, }, {"parse",
'p', ((void*)0), CFG_FLAG, &cfg.parse, 0, parse, 0, }, {
"output", 'O', "FILE", CFG_STRING, &cfg.output, 1, output
, 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) } }
;
1383
1384 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1385 if (err)
1386 return err;
1387
1388 if (!cfg.file) {
1389 fprintf(stderrstderr, "file required param\n");
1390 return -EINVAL22;
1391 }
1392
1393 if (cfg.parse && !cfg.output) {
1394 fprintf(stderrstderr, "output file required if evtlog need be parsed\n");
1395 return -EINVAL22;
1396 }
1397
1398 err = nvme_dump_evtlog(hdl, cfg.namespace_id, cfg.storage_medium, cfg.file, cfg.parse, cfg.output);
1399
1400 return 0;
1401}
1402
1403static int nvme_expand_cap(struct libnvme_transport_handle *hdl, __u32 namespace_id, __u64 namespace_size,
1404 __u64 namespace_cap, __u32 lbaf, __u32 units)
1405{
1406 struct dirent **devices;
1407 char dev_name[32] = "";
1408 int i = 0;
1409 int num = 0;
1410 int err = 0;
1411
1412 struct sfx_expand_cap_info {
1413 __u64 namespace_size;
1414 __u64 namespace_cap;
1415 __u8 reserve[10];
1416 __u8 lbaf;
1417 __u8 reserve1[5];
1418 } __packed__attribute__((__packed__));
1419
1420 if (libnvme_transport_handle_is_ctrl(hdl))
1421 snprintf(dev_name, 32, "%sn%u", libnvme_transport_handle_get_name(hdl), namespace_id);
1422 else
1423 strcpy(dev_name, libnvme_transport_handle_get_name(hdl));
1424
1425 num = scandir("/dev", &devices, libnvme_filter_namespace, alphasort);
1426 if (num <= 0) {
1427 err = num;
1428 goto ret;
1429 }
1430
1431 if (strcmp(dev_name, devices[num-1]->d_name)) {
1432 fprintf(stderrstderr, "Expand namespace not the last one\n");
1433 err = EINVAL22;
1434 goto free_devices;
1435 }
1436
1437 if (!units) {
1438 namespace_size = IDEMA_CAP(namespace_size)(((__u64)namespace_size - 50ULL) * 1953504ULL + 97696368ULL) / (1 << (lbaf * 3));
1439 namespace_cap = IDEMA_CAP(namespace_cap)(((__u64)namespace_cap - 50ULL) * 1953504ULL + 97696368ULL) / (1 << (lbaf * 3));
1440 }
1441
1442 struct sfx_expand_cap_info info = {
1443 .namespace_size = namespace_size,
1444 .namespace_cap = namespace_cap,
1445 .lbaf = lbaf,
1446 };
1447
1448 struct libnvme_passthru_cmd cmd = {
1449 .opcode = nvme_admin_ns_mgmt,
1450 .nsid = namespace_id,
1451 .addr = (__u64)(uintptr_t)&info,
1452 .data_len = sizeof(info),
1453 .cdw10 = 0x0e,
1454 };
1455
1456 err = libnvme_exec_admin_passthru(hdl, &cmd);
1457 if (err) {
1458 fprintf(stderrstderr, "Create ns failed\n");
1459 nvme_show_status(err);
1460 goto free_devices;
1461 }
1462
1463free_devices:
1464 for (i = 0; i < num; i++)
1465 free(devices[i]);
1466 free(devices);
1467ret:
1468 return err;
1469}
1470
1471static int sfx_expand_cap(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1472{
1473 char *desc = "expand capacity";
1474 const char *namespace_id = "desired namespace";
1475 const char *namespace_size = "namespace size(required)";
1476 const char *namespace_cap = "namespace capacity(required)";
1477 const char *lbaf = "LBA format to apply\n"
1478 "0: 512(default) 1: 4096";
1479 const char *units = "namespace size/capacity units\n"
1480 "0: GB(default) 1: LBA";
1481 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1482 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1483 int err = 0;
1484
1485 struct config {
1486 __u32 namespace_id;
1487 __u64 namespace_size;
1488 __u64 namespace_cap;
1489 __u32 lbaf;
1490 __u32 units;
1491 };
1492 struct config cfg = {
1493 .namespace_id = NVME_NSID_ALL,
1494 .lbaf = 0,
1495 .units = 0,
1496 };
1497
1498 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"namespace_size", 's', "NUM", CFG_LONG
, &cfg.namespace_size, 1, namespace_size, 0, }, {"namespace_cap"
, 'c', "NUM", CFG_LONG, &cfg.namespace_cap, 1, namespace_cap
, 0, }, {"lbaf", 'l', "NUM", CFG_POSITIVE, &cfg.lbaf, 1, lbaf
, 0, }, {"units", 'u', "NUM", CFG_POSITIVE, &cfg.units, 1
, units, 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) } }
1499 OPT_UINT("namespace_id", 'n', &cfg.namespace_id, namespace_id),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"namespace_size", 's', "NUM", CFG_LONG
, &cfg.namespace_size, 1, namespace_size, 0, }, {"namespace_cap"
, 'c', "NUM", CFG_LONG, &cfg.namespace_cap, 1, namespace_cap
, 0, }, {"lbaf", 'l', "NUM", CFG_POSITIVE, &cfg.lbaf, 1, lbaf
, 0, }, {"units", 'u', "NUM", CFG_POSITIVE, &cfg.units, 1
, units, 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) } }
1500 OPT_LONG("namespace_size", 's', &cfg.namespace_size, namespace_size),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"namespace_size", 's', "NUM", CFG_LONG
, &cfg.namespace_size, 1, namespace_size, 0, }, {"namespace_cap"
, 'c', "NUM", CFG_LONG, &cfg.namespace_cap, 1, namespace_cap
, 0, }, {"lbaf", 'l', "NUM", CFG_POSITIVE, &cfg.lbaf, 1, lbaf
, 0, }, {"units", 'u', "NUM", CFG_POSITIVE, &cfg.units, 1
, units, 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) } }
1501 OPT_LONG("namespace_cap", 'c', &cfg.namespace_cap, namespace_cap),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"namespace_size", 's', "NUM", CFG_LONG
, &cfg.namespace_size, 1, namespace_size, 0, }, {"namespace_cap"
, 'c', "NUM", CFG_LONG, &cfg.namespace_cap, 1, namespace_cap
, 0, }, {"lbaf", 'l', "NUM", CFG_POSITIVE, &cfg.lbaf, 1, lbaf
, 0, }, {"units", 'u', "NUM", CFG_POSITIVE, &cfg.units, 1
, units, 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) } }
1502 OPT_UINT("lbaf", 'l', &cfg.lbaf, lbaf),struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"namespace_size", 's', "NUM", CFG_LONG
, &cfg.namespace_size, 1, namespace_size, 0, }, {"namespace_cap"
, 'c', "NUM", CFG_LONG, &cfg.namespace_cap, 1, namespace_cap
, 0, }, {"lbaf", 'l', "NUM", CFG_POSITIVE, &cfg.lbaf, 1, lbaf
, 0, }, {"units", 'u', "NUM", CFG_POSITIVE, &cfg.units, 1
, units, 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) } }
1503 OPT_UINT("units", 'u', &cfg.units, units))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"namespace_id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id
, 1, namespace_id, 0, }, {"namespace_size", 's', "NUM", CFG_LONG
, &cfg.namespace_size, 1, namespace_size, 0, }, {"namespace_cap"
, 'c', "NUM", CFG_LONG, &cfg.namespace_cap, 1, namespace_cap
, 0, }, {"lbaf", 'l', "NUM", CFG_POSITIVE, &cfg.lbaf, 1, lbaf
, 0, }, {"units", 'u', "NUM", CFG_POSITIVE, &cfg.units, 1
, units, 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) } }
;
1504
1505 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1506 if (err)
1507 return err;
1508
1509 if (cfg.namespace_id == NVME_NSID_ALL) {
1510 if (libnvme_transport_handle_is_ctrl(hdl)) {
1511 fprintf(stderrstderr, "namespace_id or namespace device required\n");
1512 return -EINVAL22;
1513 } else {
1514 cfg.namespace_id = atoi(&libnvme_transport_handle_get_name(hdl)[strlen(libnvme_transport_handle_get_name(hdl)) - 1]);
1515 }
1516 }
1517
1518 if (!cfg.namespace_size) {
1519 fprintf(stderrstderr, "namespace_size required param\n");
1520 return -EINVAL22;
1521 }
1522
1523 if (!cfg.namespace_cap) {
1524 fprintf(stderrstderr, "namespace_cap required param\n");
1525 return -EINVAL22;
1526 }
1527
1528 err = nvme_expand_cap(hdl, cfg.namespace_id, cfg.namespace_size, cfg.namespace_cap, cfg.lbaf, cfg.units);
1529 if (err)
1530 return err;
1531
1532 printf("%s: Success, create nsid:%d\n", acmd->name, cfg.namespace_id);
1533
1534 return 0;
1535}
1536
1537static int sfx_status(int argc, char **argv, struct command *acmd, struct plugin *plugin)
1538{
1539 const char *desc = "Get ScaleFlux specific status information and print it";
1540 const char *json_desc = "Print output in JSON format, otherwise human readable";
1541 __cleanup_nvme_global_ctx__attribute__((cleanup(cleanup_nvme_global_ctx))) struct libnvme_global_ctx *ctx = NULL((void*)0);
1542 __cleanup_nvme_transport_handle__attribute__((cleanup(cleanup_nvme_transport_handle))) struct libnvme_transport_handle *hdl = NULL((void*)0);
1543 struct nvme_id_ctrl id_ctrl = { 0 };
1544 struct extended_health_info_myrtle sfx_smart = { 0 };
1545 struct nvme_smart_log smart_log = { 0 };
1546 struct nvme_additional_smart_log additional_smart_log = { 0 };
1547 struct sfx_freespace_ctx sfx_freespace = { 0 };
1548 unsigned int pcie_correctable, pcie_fatal, pcie_nonfatal;
1549 unsigned long long capacity;
1550 bool_Bool capacity_valid = false0;
1551 bool_Bool pcie_cor_valid, pcie_fatal_valid, pcie_nonfatal_valid;
1552 int err, fd, len, sector_size;
1553 char pci_vid[7], pci_did[7], pci_ssvid[7], link_speed[20], link_width[5], link_string[40];
1554 char path[512], numa_node[5], vendor[10], form_factor[15], temperature[10], io_speed[15];
1555 char chr_dev[8], serial_number[21], model_number[41], firmware_revision[9], pcie_status[9];
1556 struct json_object *root, *dev_stats, *link_stats, *crit_stats;
1557 nvme_print_flags_t flags;
1558 __u64 get_feat_result;
1559 double write_amp;
1560
1561 struct config {
1562 bool_Bool json;
1563 };
1564 struct config cfg = {
1565 .json = false0
1566 };
1567
1568 NVME_ARGS(opts,struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"json-print", 'j', ((void*)0), CFG_FLAG, &cfg.json
, 0, json_desc, 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) } }
1569 OPT_FLAG("json-print", 'j', &cfg.json, json_desc))struct argconfig_commandline_options opts[] = { {"", 0, ((void
*)0), CFG_GROUP_SEPARATOR, ((void*)0), 0, "Options", 0, ((void
*)0)}, {"json-print", 'j', ((void*)0), CFG_FLAG, &cfg.json
, 0, json_desc, 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) } }
;
1570
1571 err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
1572 if (err)
1573 return err;
1574
1575 err = validate_output_format(nvme_args.output_format, &flags);
1576 if (err < 0) {
1577 nvme_show_error("Invalid output format")nvme_show_message(1, "Invalid output format");
1578 return err;
1579 }
1580
1581 //Calculate formatted capacity, not concerned with errors, we may have a char device
1582 memset(&path, 0, 512);
1583 snprintf(path, 512, "/dev/%s", libnvme_transport_handle_get_name(hdl));
1584 fd = open(path, O_RDONLY00 | O_NONBLOCK04000);
1585 if (fd >= 0) {
1586 err = ioctl(fd, BLKSSZGET(((0U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8))
| (((104)) << 0) | ((0) << ((0 +8)+8)))
, &sector_size);
1587 if (!err)
1588 err = ioctl(fd, BLKGETSIZE64(((2U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8))
| (((114)) << 0) | ((((sizeof(size_t)))) << ((0 +
8)+8)))
, &capacity);
1589 capacity_valid = (!err);
1590 }
1591
1592 if (capacity_valid && sector_size == 512)
1593 capacity = IDEMA_CAP2GB(capacity/sector_size)(((__u64)capacity/sector_size - 97696368ULL) / 1953504ULL + 50ULL
)
;
1594 else if (capacity_valid && sector_size == 4096)
1595 capacity = IDEMA_CAP2GB_LDS(capacity/sector_size)(((__u64)capacity/sector_size - 12212046ULL) / 244188ULL + 50ULL
)
;
1596 else
1597 capacity = capacity / (1000 * 1000 * 1000); //B --> GB
1598
1599 memset(&chr_dev, 0, 8);
1600 strcpy(chr_dev, libnvme_transport_handle_get_name(hdl));
1601 for (len = 2; len < 8; len++) {
1602 if (chr_dev[len] == 'n')
1603 chr_dev[len] = '\0';
1604 }
1605
1606 // Populate PCIe VID/DID/SS_VID, link speed/width, and NUMA node from /sys/
1607 snprintf(path, 512, "/sys/class/nvme/%s/device/vendor", chr_dev);
1608 fd = open(path, O_RDONLY00);
1609 if (fd < 0) {
1610 perror("Could not open PCIe VID in /sys/");
1611 return -errno(*__errno_location ());
1612 }
1613 memset(&pci_vid, 0, 7);
1614 len = read(fd, pci_vid, 6);
1615 if (len < 1) {
1616 perror("Could not read PCIe VID in /sys/");
1617 close(fd);
1618 return -errno(*__errno_location ());
1619 }
1620 close(fd);
1621
1622 snprintf(path, 512, "/sys/class/nvme/%s/device/device", chr_dev);
1623 fd = open(path, O_RDONLY00);
1624 if (fd < 0) {
1625 perror("Could not open PCIe DID in /sys/");
1626 return -errno(*__errno_location ());
1627 }
1628 memset(&pci_did, 0, 7);
1629 len = read(fd, pci_did, 6);
1630 if (len < 1) {
1631 perror("Could not read PCIe DID in /sys/");
1632 close(fd);
1633 return -errno(*__errno_location ());
1634 }
1635 close(fd);
1636
1637 if (strncmp("0xcc53", pci_vid, 6) == 0)
1638 strncpy(vendor, "ScaleFlux", 10);
1639 else if (strncmp("0x1dfd", pci_vid, 6) == 0)
1640 strncpy(vendor, "DIGISTOR", 10);
1641 else {
1642 fprintf(stderrstderr, "Please use on a ScaleFlux device\n");
1643 return -1;
1644 }
1645
1646 snprintf(path, 512, "/sys/class/nvme/%s/device/subsystem_vendor", chr_dev);
1647 fd = open(path, O_RDONLY00);
1648 if (fd < 0) {
1649 perror("Could not open PCIe Subsystem Vendor ID in /sys/");
1650 return -errno(*__errno_location ());
1651 }
1652 memset(&pci_ssvid, 0, 7);
1653 len = read(fd, pci_ssvid, 6);
1654 if (len < 1) {
1655 perror("could not read PCIe Subsystem Vendor ID in /sys/");
1656 close(fd);
1657 return -errno(*__errno_location ());
1658 }
1659 close(fd);
1660
1661 snprintf(path, 512, "/sys/class/nvme/%s/device/current_link_speed", chr_dev);
1662 fd = open(path, O_RDONLY00);
1663 if (fd < 0) {
1664 perror("Could not open link speed in /sys/");
1665 return -errno(*__errno_location ());
1666 }
1667 memset(&link_speed, 0, 20);
1668 len = read(fd, link_speed, 20);
1669 if (len < 1) {
1670 perror("Could not read link speed in /sys/");
1671 close(fd);
1672 return -errno(*__errno_location ());
1673 }
1674 close(fd);
1675 // Ending string before "PCIe" and newline
1676 for (len = 0; (len+2) < 20 && link_speed[len+2] != '\0'; ++len) {
1677 if (link_speed[len] == '/' && link_speed[len+1] == 's')
1678 link_speed[len+2] = '\0';
1679 }
1680
1681 snprintf(path, 512, "/sys/class/nvme/%s/device/current_link_width", chr_dev);
1682 fd = open(path, O_RDONLY00);
1683 if (fd < 0) {
1684 perror("Could not open link width in /sys/");
1685 return -errno(*__errno_location ());
1686 }
1687 memset(&link_width, 0, 5);
1688 len = read(fd, link_width, 5);
1689 if (len < 1) {
1690 perror("Could not read link width in /sys/");
1691 close(fd);
1692 return -errno(*__errno_location ());
1693 }
1694 close(fd);
1695 // Ending string before newline
1696 for (len = 0; (len) < 5 ; ++len) {
1697 if (link_width[len] == '\n')
1698 link_width[len] = '\0';
1699 }
1700
1701 snprintf(link_string, 40, "Speed %s, Width x%s", link_speed, link_width);
1702
1703 snprintf(path, 512, "/sys/class/nvme/%s/device/numa_node", chr_dev);
1704 fd = open(path, O_RDONLY00);
1705 if (fd < 0) {
1706 perror("Could not open NUMA node in /sys/");
1707 return -errno(*__errno_location ());
1708 }
1709 memset(&numa_node, 0, 5);
1710 len = read(fd, numa_node, 5);
1711 if (len < 1) {
1712 perror("Could not read NUMA node in /sys/");
1713 close(fd);
1714 return -errno(*__errno_location ());
1715 }
1716 close(fd);
1717
1718 for (len = 0; len < 5; ++len) {
1719 if (numa_node[len] == '\n')
1720 numa_node[len] = '\0';
1721 }
1722
1723 //Populate PCIe AER errors from /sys/
1724 snprintf(path, 512, "/sys/class/nvme/%s/device/aer_dev_correctable", chr_dev);
1725 pcie_cor_valid = true1;
1726 fd = open(path, O_RDONLY00);
1727 if (fd < 0) {
1728 perror("Could not open PCIe AER Correctable errors in /sys/");
1729 pcie_cor_valid = false0;
1730 }
1731
1732 if (pcie_cor_valid) {
1733 len = read(fd, path, 512);
1734 if (len < 1) {
1735 perror("Could not read PCIe AER Correctable errors in /sys/");
1736 pcie_cor_valid = false0;
1737 }
1738 close(fd);
1739 }
1740 if (pcie_cor_valid) {
1741 len = sscanf(path, "%*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d TOTAL_ERR_COR %d", &pcie_correctable);
1742 if (len < 1 || len == EOF(-1)) {
1743 perror("Could not parse PCIe AER Correctable errors in /sys/");
1744 pcie_cor_valid = false0;
1745 }
1746 }
1747
1748 snprintf(path, 512, "/sys/class/nvme/%s/device/aer_dev_nonfatal", chr_dev);
1749 pcie_nonfatal_valid = true1;
1750 fd = open(path, O_RDONLY00);
1751 if (fd < 0) {
1752 perror("Could not open PCIe AER Non-Fatal errors in /sys/");
1753 pcie_nonfatal_valid = false0;
1754 }
1755
1756 if (pcie_nonfatal_valid) {
1757 len = read(fd, path, 512);
1758 if (len < 1) {
1759 perror("Could not read PCIe AER Non-Fatal errors in /sys/");
1760 pcie_nonfatal_valid = false0;
1761 }
1762 close(fd);
1763 }
1764 if (pcie_nonfatal_valid) {
1765 len = sscanf(path, "%*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d TOTAL_ERR_NONFATAL %d", &pcie_nonfatal);
1766 if (len < 1) {
1767 perror("Could not parse PCIe AER Non-Fatal errors in /sys/");
1768 pcie_nonfatal_valid = false0;
1769 }
1770 }
1771 snprintf(path, 512, "/sys/class/nvme/%s/device/aer_dev_fatal", chr_dev);
1772 pcie_fatal_valid = true1;
1773 fd = open(path, O_RDONLY00);
1774 if (fd < 0) {
1775 perror("Could not open PCIe AER Fatal errors in /sys/");
1776 pcie_fatal_valid = false0;
1777 }
1778
1779 if (pcie_fatal_valid) {
1780 len = read(fd, path, 512);
1781 if (len < 1) {
1782 perror("Could not read PCIe AER Fatal errors in /sys/");
1783 pcie_fatal_valid = false0;
1784 }
1785 close(fd);
1786 }
1787 if (pcie_fatal_valid) {
1788 len = sscanf(path, "%*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d %*s %*d TOTAL_ERR_FATAL %d", &pcie_fatal);
1789 if (len < 1) {
1790 perror("Could not parse PCIe AER Fatal errors in /sys/");
1791 close(fd);
1792 pcie_fatal_valid = false0;
1793 }
1794 }
1795
1796 if (pcie_cor_valid && pcie_nonfatal_valid && pcie_fatal_valid)
1797 snprintf(pcie_status, 9, "%s", (pcie_fatal != 0 || pcie_nonfatal != 0 || pcie_correctable != 0) ? "Warning":"Good");
1798 else
1799 snprintf(pcie_status, 9, "%s", "Unknown");
1800
1801 //Populate id-ctrl
1802 err = nvme_identify_ctrl(hdl, &id_ctrl);
1803 if (err) {
1804 fprintf(stderrstderr, "Unable to read nvme_identify_ctrl() error code:%x\n", err);
1805 return err;
1806 }
1807 //Re-format specific fields so they can be safely treated as strings later
1808 serial_number[20] = '\0';
1809 memcpy(serial_number, id_ctrl.sn, 20);
1810 model_number[40] = '\0';
1811 memcpy(model_number, id_ctrl.mn, 40);
1812 firmware_revision[8] = '\0';
1813 memcpy(firmware_revision, id_ctrl.fr, 8);
1814
1815 //Populate SMART log (0x02)
1816 err = nvme_get_log_smart(hdl, NVME_NSID_ALL, &smart_log);
1817 if (err < 0) {
1818 perror("Could not read SMART log (0x02)");
1819 return -errno(*__errno_location ());
1820 } else if (err > 0) {
1821 nvme_show_status(err);
1822 return err;
1823 }
1824
1825 snprintf(temperature, 10, "%li", kelvin_to_celsius(smart_log.temperature[1]<<8 | smart_log.temperature[0]));
1826
1827 //Populate SFX Extended Health log (0xC2) or if PCIe DID ==0x20 (Quince) use 0xD2
1828 if (strncmp("0x0020", pci_did, 6) == 0)
1829 err = nvme_get_log_simple(hdl, SFX_LOG_EXTENDED_HEALTH_ALT, (void *)&sfx_smart,
1830 sizeof(sfx_smart));
1831 else
1832 err = nvme_get_log_simple(hdl, SFX_LOG_EXTENDED_HEALTH, (void *)&sfx_smart,
1833 sizeof(sfx_smart));
1834 if (err < 0) {
1835 perror("Could not read ScaleFlux SMART log");
1836 return -errno(*__errno_location ());
1837 } else if (err > 0) {
1838 nvme_show_status(err);
1839 return err;
1840 }
1841
1842 //Make sure the OPN can be printed safely
1843 sfx_smart.opn[10] = '\0';
1844
1845 switch (sfx_smart.opn[3]) {
1846 case 'P':
1847 snprintf(form_factor, 15, "%s", "AIC");
1848 break;
1849 case 'U':
1850 snprintf(form_factor, 15, "%s", (sfx_smart.opn[4] == '8')?"U.3":"U.2");
1851 break;
1852 case 'E':
1853 snprintf(form_factor, 15, "%s", "E1.S");
1854 break;
1855 default:
1856 snprintf(form_factor, 15, "%s", "Incorrect OPN");
1857 }
1858
1859 //Populate Additional SMART log (0xCA)
1860 err = nvme_get_nsid_log(hdl, NVME_NSID_ALL, false0, 0xca, (void *)&additional_smart_log,
1861 sizeof(struct nvme_additional_smart_log));
1862 if (err < 0) {
1863 perror("Could not read ScaleFlux SMART log");
1864 return -errno(*__errno_location ());
1865 } else if (err > 0) {
1866 nvme_show_status(err);
1867 return err;
1868 }
1869
1870 //OK with the '-nan' if host_bytes_written is zero
1871 write_amp = int48_to_long(additional_smart_log.nand_bytes_written.raw)/(1.0 * int48_to_long(additional_smart_log.host_bytes_written.raw));
1872
1873 //Get SFX freespace information
1874 err = nvme_query_cap(hdl, NVME_NSID_ALL, sizeof(sfx_freespace), &sfx_freespace);
1875 if (err < 0) {
1876 perror("Could not query freespace information (0xD6)");
1877 return -errno(*__errno_location ());
1878 } else if (err > 0) {
1879 nvme_show_status(err);
1880 return err;
1881 }
1882
1883 //Parse IO Speed information
1884 memset(&io_speed, 0, 15);
1885 switch (sfx_smart.io_speed) {
1886 case '1':
1887 if (strncmp("0x0020", pci_did, 6))
1888 strncpy(io_speed, "2.5MB/s", 15);
1889 else
1890 strncpy(io_speed, "10MB/s", 15);
1891 break;
1892 case '2':
1893 if (strncmp("0x0020", pci_did, 6))
1894 strncpy(io_speed, "128KB/s", 15);
1895 else
1896 strncpy(io_speed, "512KB/s", 15);
1897 break;
1898 case '3':
1899 strncpy(io_speed, "Write Reject", 15);
1900 break;
1901 default:
1902 strncpy(io_speed, "Normal", 15);
1903 }
1904
1905 if (sfx_smart.comp_ratio < 100)
1906 sfx_smart.comp_ratio = 100;
1907 else if (sfx_smart.comp_ratio > 800)
1908 sfx_smart.comp_ratio = 800;
1909
1910 //Get status of atomic write feature
1911 err = nvme_get_features(hdl, 0, 0x0A, 0, 0, 0, NULL((void*)0), 0, &get_feat_result);
1912 if (err < 0) {
1913 perror("Could not get feature (0x0A)");
1914 return -errno(*__errno_location ());
1915 } else if (err > 0) {
1916 nvme_show_status(err);
1917 return err;
1918 }
1919
1920 if (flags & JSON || cfg.json) {
1921 root = json_create_object()json_object_new_object();
1922 json_object_add_value_string(root, "ScaleFlux Status", libnvme_transport_handle_get_name(hdl));
1923
1924 dev_stats = json_create_object()json_object_new_object();
1925 link_stats = json_create_object()json_object_new_object();
1926 crit_stats = json_create_object()json_object_new_object();
1927
1928 json_object_add_value_string(dev_stats, "PCIe Vendor ID", pci_vid);
1929 json_object_add_value_string(dev_stats, "PCIe Subsystem Vendor ID", pci_ssvid);
1930 json_object_add_value_string(dev_stats, "Manufacturer", vendor);
1931 json_object_add_value_string(dev_stats, "Model", model_number);
1932 json_object_add_value_string(dev_stats, "Serial Number", serial_number);
1933 json_object_add_value_string(dev_stats, "OPN", (char *)sfx_smart.opn);
1934 json_object_add_value_string(dev_stats, "Drive Type", form_factor);
1935 json_object_add_value_string(dev_stats, "Firmware Revision", firmware_revision);
1936 json_object_add_value_string(dev_stats, "Temperature [C]", temperature);
1937 json_object_add_value_uint(dev_stats, "Power Consumption [mW]", sfx_smart.power_mw_consumption)json_object_object_add(dev_stats, "Power Consumption [mW]", json_object_new_uint64
(sfx_smart.power_mw_consumption))
;
1938 json_object_add_value_uint(dev_stats, "Atomic Write Mode", (get_feat_result))json_object_object_add(dev_stats, "Atomic Write Mode", json_object_new_uint64
((get_feat_result)))
;
1939 json_object_add_value_int(dev_stats, "Percentage Used", smart_log.percent_used)json_object_object_add(dev_stats, "Percentage Used", json_object_new_int
(smart_log.percent_used))
;
1940 json_object_add_value_string(dev_stats, "Data Read", uint128_t_to_si_string(le128_to_cpu(smart_log.data_units_read), 1000 * 512));
1941 json_object_add_value_string(dev_stats, "Data Written", uint128_t_to_si_string(le128_to_cpu(smart_log.data_units_written), 1000 * 512));
1942 json_object_add_value_int(dev_stats, "Correctable Error Count", sfx_smart.pcie_rx_correct_errs)json_object_object_add(dev_stats, "Correctable Error Count", json_object_new_int
(sfx_smart.pcie_rx_correct_errs))
;
1943 json_object_add_value_int(dev_stats, "Uncorrectable Error Count", sfx_smart.pcie_rx_uncorrect_errs)json_object_object_add(dev_stats, "Uncorrectable Error Count"
, json_object_new_int(sfx_smart.pcie_rx_uncorrect_errs))
;
1944 json_object_add_value_string(link_stats, "PCIe Link Width", link_width);
1945 json_object_add_value_string(link_stats, "PCIe Link Speed", link_speed);
1946 if (pcie_fatal_valid)
1947 json_object_add_value_int(link_stats, "PCIe Link Fatal Errors", pcie_fatal)json_object_object_add(link_stats, "PCIe Link Fatal Errors", json_object_new_int
(pcie_fatal))
;
1948 if (pcie_nonfatal_valid)
1949 json_object_add_value_int(link_stats, "PCIe Link Non-Fatal Errors", pcie_nonfatal)json_object_object_add(link_stats, "PCIe Link Non-Fatal Errors"
, json_object_new_int(pcie_nonfatal))
;
1950 if (pcie_cor_valid)
1951 json_object_add_value_int(link_stats, "PCIe Link Correctable Errors", pcie_correctable)json_object_object_add(link_stats, "PCIe Link Correctable Errors"
, json_object_new_int(pcie_correctable))
;
1952 json_object_add_value_string(link_stats, "PCIe Device Status", pcie_status);
1953 json_object_add_value_object(dev_stats, "PCIe Link Status", link_stats)json_object_object_add(dev_stats, "PCIe Link Status", link_stats
)
;
1954 if (sfx_smart.friendly_changecap_support) {
1955 json_object_add_value_int(dev_stats, "Current Formatted Capacity [GB]", sfx_smart.cur_formatted_capability)json_object_object_add(dev_stats, "Current Formatted Capacity [GB]"
, json_object_new_int(sfx_smart.cur_formatted_capability))
;
1956 json_object_add_value_int(dev_stats, "Max Formatted Capacity [GB]", sfx_smart.max_formatted_capability)json_object_object_add(dev_stats, "Max Formatted Capacity [GB]"
, json_object_new_int(sfx_smart.max_formatted_capability))
;
1957 json_object_add_value_int(dev_stats, "Extendible Capacity LBA count", sfx_smart.extendible_cap_lbacount)json_object_object_add(dev_stats, "Extendible Capacity LBA count"
, json_object_new_int(sfx_smart.extendible_cap_lbacount))
;
1958 } else if (capacity_valid)
1959 json_object_add_value_int(dev_stats, "Formatted Capacity [GB]", capacity)json_object_object_add(dev_stats, "Formatted Capacity [GB]",
json_object_new_int(capacity))
;
1960
1961 json_object_add_value_int(dev_stats, "Provisioned Capacity [GB]", IDEMA_CAP2GB(sfx_smart.total_physical_capability))json_object_object_add(dev_stats, "Provisioned Capacity [GB]"
, json_object_new_int((((__u64)sfx_smart.total_physical_capability
- 97696368ULL) / 1953504ULL + 50ULL)))
;
1962 json_object_add_value_int(dev_stats, "Compression Ratio", sfx_smart.comp_ratio)json_object_object_add(dev_stats, "Compression Ratio", json_object_new_int
(sfx_smart.comp_ratio))
;
1963 json_object_add_value_int(dev_stats, "Physical Used Ratio", sfx_smart.physical_usage_ratio)json_object_object_add(dev_stats, "Physical Used Ratio", json_object_new_int
(sfx_smart.physical_usage_ratio))
;
1964 json_object_add_value_int(dev_stats, "Free Physical Space [GB]", IDEMA_CAP2GB(sfx_smart.free_physical_capability))json_object_object_add(dev_stats, "Free Physical Space [GB]",
json_object_new_int((((__u64)sfx_smart.free_physical_capability
- 97696368ULL) / 1953504ULL + 50ULL)))
;
1965 json_object_add_value_int(dev_stats, "Firmware RSA Verification", (sfx_smart.otp_rsa_en))json_object_object_add(dev_stats, "Firmware RSA Verification"
, json_object_new_int((sfx_smart.otp_rsa_en)))
;
1966 json_object_add_value_string(dev_stats, "IO Speed", io_speed);
1967 json_object_add_value_string(dev_stats, "NUMA Node", numa_node);
1968 json_object_add_value_int(dev_stats, "Indirection Unit [kiB]", (4*sfx_freespace.map_unit))json_object_object_add(dev_stats, "Indirection Unit [kiB]", json_object_new_int
((4*sfx_freespace.map_unit)))
;
1969 json_object_add_value_double(dev_stats, "Lifetime WAF", write_amp)json_object_object_add(dev_stats, "Lifetime WAF", util_json_object_new_double
(write_amp))
;
1970
1971 json_object_add_value_int(crit_stats, "Thermal Throttling On", (sfx_smart.temp_throttle_info))json_object_object_add(crit_stats, "Thermal Throttling On", json_object_new_int
((sfx_smart.temp_throttle_info)))
;
1972 json_object_add_value_int(crit_stats, "Backup Capacitor Status Bad", (smart_log.critical_warning & 0x10))json_object_object_add(crit_stats, "Backup Capacitor Status Bad"
, json_object_new_int((smart_log.critical_warning & 0x10)
))
;
1973 json_object_add_value_int(crit_stats, "Bad block exceeds threshold", (smart_log.critical_warning & 0x01))json_object_object_add(crit_stats, "Bad block exceeds threshold"
, json_object_new_int((smart_log.critical_warning & 0x01)
))
;
1974 json_object_add_value_int(crit_stats, "Media Error", (smart_log.critical_warning & 0x04))json_object_object_add(crit_stats, "Media Error", json_object_new_int
((smart_log.critical_warning & 0x04)))
;
1975 json_object_add_value_int(crit_stats, "Read only mode", (smart_log.critical_warning & 0x08))json_object_object_add(crit_stats, "Read only mode", json_object_new_int
((smart_log.critical_warning & 0x08)))
;
1976 json_object_add_value_int(crit_stats, "Power Failure Data Loss", (sfx_smart.sfx_critical_warning & SFX_CRIT_PWR_FAIL_DATA_LOSS))json_object_object_add(crit_stats, "Power Failure Data Loss",
json_object_new_int((sfx_smart.sfx_critical_warning & SFX_CRIT_PWR_FAIL_DATA_LOSS
)))
;
1977 json_object_add_value_int(crit_stats, "Exceed physical capacity limitation", (sfx_smart.sfx_critical_warning & SFX_CRIT_OVER_CAP))json_object_object_add(crit_stats, "Exceed physical capacity limitation"
, json_object_new_int((sfx_smart.sfx_critical_warning & SFX_CRIT_OVER_CAP
)))
;
1978 json_object_add_value_int(crit_stats, "Read/Write lock mode", (sfx_smart.sfx_critical_warning & SFX_CRIT_RW_LOCK))json_object_object_add(crit_stats, "Read/Write lock mode", json_object_new_int
((sfx_smart.sfx_critical_warning & SFX_CRIT_RW_LOCK)))
;
1979
1980 json_object_add_value_object(dev_stats, "Critical Warning(s)", crit_stats)json_object_object_add(dev_stats, "Critical Warning(s)", crit_stats
)
;
1981
1982 json_object_add_value_object(root, "Device stats", dev_stats)json_object_object_add(root, "Device stats", dev_stats);
1983
1984 json_print_object(root, NULL)printf("%s", json_object_to_json_string_ext(root, (1 <<
1) | (1 << 4)))
;
1985 printf("\n");
1986 json_free_object(root)json_object_put(root);
1987
1988 } else {
1989 // Re-using path variable to hold critical warning text
1990 // order is to match sfx-status, done here to include color
1991 memset(path, 0, 512);
1992 len = snprintf(path, 512, FMT_RED"\x1b[31m" "\n%s%s%s%s%s%s%s%s" FMT_RESET"\x1b[0m", \
1993 (sfx_smart.temp_throttle_info) ? "\tThermal Throttling On\n" : "", \
1994 (smart_log.critical_warning & 0x10) ? "\tBackup Capacitor Status Bad\n" : "", \
1995 (smart_log.critical_warning & 0x01) ? "\tBad block exceeds threshold\n" : "", \
1996 (smart_log.critical_warning & 0x04) ? "\tMedia Error\n" : "", \
1997 (smart_log.critical_warning & 0x08) ? "\tRead only mode\n" : "", \
1998 (sfx_smart.sfx_critical_warning & SFX_CRIT_PWR_FAIL_DATA_LOSS) ? "\tPower Failure Data Loss\n" : "", \
1999 (sfx_smart.sfx_critical_warning & SFX_CRIT_OVER_CAP) ? "\tExceed physical capacity limitation\n" : "", \
2000 (sfx_smart.sfx_critical_warning & SFX_CRIT_RW_LOCK) ? "\tRead/Write lock mode\n" : "" \
2001 );
2002 if (len < 11)
2003 strcpy(path, "None");
2004
2005 printf("%-35s%s%s\n", "ScaleFlux Drive:", "/dev/", libnvme_transport_handle_get_name(hdl));
2006 printf("%-35s%s\n", "PCIe Vendor ID:", pci_vid);
2007 printf("%-35s%s\n", "PCIe Subsystem Vendor ID:", pci_ssvid);
2008 printf("%-35s%s\n", "Manufacturer:", vendor);
2009 printf("%-35s%.*s\n", "Model:", 40, model_number);
2010 printf("%-35s%.*s\n", "Serial Number:", 20, serial_number);
2011 printf("%-35s%.*s\n", "OPN:", 32, sfx_smart.opn);
2012 printf("%-35s%s\n", "Drive Type:", form_factor);
2013 printf("%-35s%.*s\n", "Firmware Revision:", 8, firmware_revision);
2014 printf("%-35s%s C\n", "Temperature:", temperature);
2015 printf("%-35s%i mW\n", "Power Consumption:", sfx_smart.power_mw_consumption);
2016 printf("%-35s%s\n", "Atomic Write mode:", (get_feat_result)?"Off":"On");
2017 printf("%-35s%u%%\n", "Percentage Used:", smart_log.percent_used);
2018 printf("%-35s%s\n", "Host Data Read:", uint128_t_to_si_string( le128_to_cpu( \
2019 smart_log.data_units_read), 1000 * 512));
2020 printf("%-35s%s\n", "Host Data Written:", uint128_t_to_si_string(le128_to_cpu( \
2021 smart_log.data_units_written), 1000 * 512));
2022 write_amp = int48_to_long(additional_smart_log.nand_bytes_written.raw)/(1.0 * int48_to_long(additional_smart_log.host_bytes_written.raw));
2023 printf("%-35s%i\n", "Correctable Error Cnt:", sfx_smart.pcie_rx_correct_errs);
2024 printf("%-35s%i\n", "Uncorrectable Error Cnt:", sfx_smart.pcie_rx_uncorrect_errs);
2025 printf("%-35s%s\n", "PCIe Link Status:", link_string);
2026 printf("%-35s%s\n", "PCIe Device Status:", pcie_status);
2027 if (sfx_smart.friendly_changecap_support) {
2028 printf("%-35s%"PRIu64"l" "u"" GB\n", "Current Formatted Capacity:",
2029 (uint64_t)sfx_smart.cur_formatted_capability);
2030 printf("%-35s%"PRIu64"l" "u"" GB\n", "Max Formatted Capacity:",
2031 (uint64_t)sfx_smart.max_formatted_capability);
2032 printf("%-35s%"PRIu64"l" "u""\n", "Extendible Capacity LBA count:",
2033 (uint64_t)sfx_smart.extendible_cap_lbacount);
2034 } else if (capacity_valid) {
2035 printf("%-35s%"PRIu64"l" "u"" GB\n", "Formatted Capacity:", (uint64_t)capacity);
2036 }
2037 printf("%-35s%"PRIu64"l" "u"" GB\n", "Provisioned Capacity:",
2038 (uint64_t)IDEMA_CAP2GB(sfx_smart.total_physical_capability)(((__u64)sfx_smart.total_physical_capability - 97696368ULL) /
1953504ULL + 50ULL)
);
2039 printf("%-35s%u%%\n", "Compression Ratio:", sfx_smart.comp_ratio);
2040 printf("%-35s%u%%\n", "Physical Used Ratio:", sfx_smart.physical_usage_ratio);
2041 printf("%-35s%"PRIu64"l" "u"" GB\n", "Free Physical Space:",
2042 (uint64_t)IDEMA_CAP2GB(sfx_smart.free_physical_capability)(((__u64)sfx_smart.free_physical_capability - 97696368ULL) / 1953504ULL
+ 50ULL)
);
2043 printf("%-35s%s\n", "Firmware Verification:", (sfx_smart.otp_rsa_en) ? "On":"Off");
2044 printf("%-35s%s\n", "IO Speed:", io_speed);
2045 printf("%-35s%s\n", "NUMA Node:", numa_node);
2046 printf("%-35s%"PRIu64"l" "u""K\n", "Indirection Unit:",
2047 (uint64_t)(4*sfx_freespace.map_unit));
2048 printf("%-35s%.2f\n", "Lifetime WAF:", write_amp);
2049 printf("%-35s%s\n", "Critical Warning(s):", path);
2050 }
2051
2052 return 0;
2053}