Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2015 Intel Corporation. All rights reserved.
3 : : * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : :
8 : : #include "spdk/endian.h"
9 : : #include "spdk/log.h"
10 : : #include "spdk/nvme.h"
11 : : #include "spdk/vmd.h"
12 : : #include "spdk/nvme_ocssd.h"
13 : : #include "spdk/nvme_zns.h"
14 : : #include "spdk/env.h"
15 : : #include "spdk/nvme_intel.h"
16 : : #include "spdk/nvmf_spec.h"
17 : : #include "spdk/pci_ids.h"
18 : : #include "spdk/string.h"
19 : : #include "spdk/util.h"
20 : : #include "spdk/uuid.h"
21 : : #include "spdk/sock.h"
22 : :
23 : : #define MAX_DISCOVERY_LOG_ENTRIES ((uint64_t)1000)
24 : :
25 : : #define NUM_CHUNK_INFO_ENTRIES 8
26 : : #define MAX_OCSSD_PU 128
27 : : #define MAX_ZONE_DESC_ENTRIES 8
28 : :
29 : : #define FDP_LOG_PAGE_SIZE 4096
30 : :
31 : : static int outstanding_commands;
32 : :
33 : : struct feature {
34 : : uint32_t result;
35 : : bool valid;
36 : : };
37 : :
38 : : static struct feature features[256] = {};
39 : :
40 : : static struct spdk_nvme_error_information_entry error_page[256];
41 : :
42 : : static struct spdk_nvme_health_information_page health_page;
43 : :
44 : : static struct spdk_nvme_firmware_page firmware_page;
45 : :
46 : : static struct spdk_nvme_ana_page *g_ana_log_page;
47 : :
48 : : static struct spdk_nvme_ana_group_descriptor *g_copied_ana_desc;
49 : :
50 : : static size_t g_ana_log_page_size;
51 : :
52 : : static size_t g_fdp_cfg_log_page_size;
53 : :
54 : : static size_t g_fdp_ruhu_log_page_size;
55 : :
56 : : static size_t g_fdp_events_log_page_size;
57 : :
58 : : static struct spdk_nvme_fdp_stats_log_page g_fdp_stats_log_page;
59 : :
60 : : static struct spdk_nvme_fdp_cfg_log_page *g_fdp_cfg_log_page;
61 : :
62 : : static struct spdk_nvme_fdp_ruhu_log_page *g_fdp_ruhu_log_page;
63 : :
64 : : static struct spdk_nvme_fdp_events_log_page *g_fdp_events_log_page;
65 : :
66 : : static struct spdk_nvme_cmds_and_effect_log_page cmd_effects_log_page;
67 : :
68 : : static struct spdk_nvme_intel_smart_information_page intel_smart_page;
69 : :
70 : : static struct spdk_nvme_intel_temperature_page intel_temperature_page;
71 : :
72 : : static struct spdk_nvme_intel_marketing_description_page intel_md_page;
73 : :
74 : : static struct spdk_nvmf_discovery_log_page *g_discovery_page;
75 : : static size_t g_discovery_page_size;
76 : : static uint64_t g_discovery_page_numrec;
77 : :
78 : : static struct spdk_ocssd_geometry_data geometry_data;
79 : :
80 : : static struct spdk_ocssd_chunk_information_entry *g_ocssd_chunk_info_page;
81 : :
82 : : static int64_t g_zone_report_limit = 8;
83 : :
84 : : static bool g_hex_dump = false;
85 : :
86 : : static int g_shm_id = -1;
87 : :
88 : : static int g_dpdk_mem = 0;
89 : :
90 : : static bool g_dpdk_mem_single_seg = false;
91 : :
92 : : static int g_main_core = 0;
93 : :
94 : : static char g_core_mask[20] = "0x1";
95 : :
96 : : static struct spdk_nvme_transport_id g_trid;
97 : : static char g_hostnqn[SPDK_NVMF_NQN_MAX_LEN + 1];
98 : :
99 : : static int g_controllers_found = 0;
100 : :
101 : : static bool g_vmd = false;
102 : :
103 : : static bool g_ocssd_verbose = false;
104 : :
105 : : static struct spdk_nvme_detach_ctx *g_detach_ctx = NULL;
106 : :
107 : : static const char *g_iova_mode;
108 : :
109 : : static void
110 : 0 : hex_dump(const void *data, size_t size)
111 : : {
112 : 0 : size_t offset = 0, i;
113 : 0 : const uint8_t *bytes = data;
114 : :
115 [ # # ]: 0 : while (size) {
116 [ # # ]: 0 : printf("%08zX:", offset);
117 : :
118 [ # # ]: 0 : for (i = 0; i < 16; i++) {
119 [ # # ]: 0 : if (i == 8) {
120 : 0 : printf("-");
121 : : } else {
122 : 0 : printf(" ");
123 : : }
124 : :
125 [ # # ]: 0 : if (i < size) {
126 [ # # ]: 0 : printf("%02X", bytes[offset + i]);
127 : : } else {
128 [ # # ]: 0 : printf(" ");
129 : : }
130 : : }
131 : :
132 [ # # ]: 0 : printf(" ");
133 : :
134 [ # # ]: 0 : for (i = 0; i < 16; i++) {
135 [ # # ]: 0 : if (i < size) {
136 [ # # # # ]: 0 : if (bytes[offset + i] > 0x20 && bytes[offset + i] < 0x7F) {
137 : 0 : printf("%c", bytes[offset + i]);
138 : : } else {
139 : 0 : printf(".");
140 : : }
141 : : }
142 : : }
143 : :
144 : 0 : printf("\n");
145 : :
146 : 0 : offset += 16;
147 [ # # ]: 0 : if (size > 16) {
148 : 0 : size -= 16;
149 : : } else {
150 : 0 : break;
151 : : }
152 : : }
153 : 0 : }
154 : :
155 : : static void
156 : 332 : get_feature_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
157 : : {
158 : 332 : struct feature *feature = cb_arg;
159 : 332 : int fid = feature - features;
160 : :
161 [ + + - + ]: 332 : if (spdk_nvme_cpl_is_error(cpl)) {
162 [ - + ]: 16 : printf("get_feature(0x%02X) failed\n", fid);
163 : : } else {
164 : 316 : feature->result = cpl->cdw0;
165 : 316 : feature->valid = true;
166 : : }
167 : 332 : outstanding_commands--;
168 : 332 : }
169 : :
170 : : static void
171 : 309 : get_log_page_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
172 : : {
173 [ + - - + ]: 309 : if (spdk_nvme_cpl_is_error(cpl)) {
174 [ # # ]: 0 : printf("get log page failed\n");
175 : : }
176 : 309 : outstanding_commands--;
177 : 309 : }
178 : :
179 : : static void
180 : 0 : get_ocssd_geometry_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
181 : : {
182 [ # # # # ]: 0 : if (spdk_nvme_cpl_is_error(cpl)) {
183 [ # # ]: 0 : printf("get ocssd geometry failed\n");
184 : : }
185 : 0 : outstanding_commands--;
186 : 0 : }
187 : :
188 : : static void
189 : 0 : get_zns_zone_report_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
190 : : {
191 [ # # # # ]: 0 : if (spdk_nvme_cpl_is_error(cpl)) {
192 [ # # ]: 0 : printf("get zns zone report failed\n");
193 : : }
194 : :
195 : 0 : outstanding_commands--;
196 : 0 : }
197 : :
198 : : static int
199 : 332 : get_feature(struct spdk_nvme_ctrlr *ctrlr, uint8_t fid, uint32_t cdw11, uint32_t nsid)
200 : : {
201 : 332 : struct spdk_nvme_cmd cmd = {};
202 : 332 : struct feature *feature = &features[fid];
203 : :
204 : 332 : feature->valid = false;
205 : :
206 : 332 : cmd.opc = SPDK_NVME_OPC_GET_FEATURES;
207 : 332 : cmd.cdw10_bits.get_features.fid = fid;
208 : 332 : cmd.cdw11 = cdw11;
209 : 332 : cmd.nsid = nsid;
210 : :
211 : 332 : return spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, &cmd, NULL, 0, get_feature_completion, feature);
212 : : }
213 : :
214 : : static void
215 : 136 : get_features(struct spdk_nvme_ctrlr *ctrlr, uint8_t *features_to_get, size_t num_features,
216 : : uint32_t nsid)
217 : : {
218 : : size_t i;
219 : : uint32_t cdw11;
220 : :
221 : : /* Submit only one GET FEATURES at a time. There is a known issue #1799
222 : : * with Google Cloud Platform NVMe SSDs that do not handle overlapped
223 : : * GET FEATURES commands correctly.
224 : : */
225 : 136 : outstanding_commands = 0;
226 [ + + ]: 600 : for (i = 0; i < num_features; i++) {
227 : 464 : cdw11 = 0;
228 [ + - ]: 464 : if (!spdk_nvme_ctrlr_is_ocssd_supported(ctrlr) &&
229 [ + + ]: 464 : features_to_get[i] == SPDK_OCSSD_FEAT_MEDIA_FEEDBACK) {
230 : 64 : continue;
231 : : }
232 [ + + ]: 400 : if (features_to_get[i] == SPDK_NVME_FEAT_FDP) {
233 : 72 : const struct spdk_nvme_ctrlr_data *cdata = spdk_nvme_ctrlr_get_data(ctrlr);
234 : 72 : struct spdk_nvme_ns *ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid);
235 : 72 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
236 : :
237 [ + + ]: 72 : if (!cdata->ctratt.bits.fdps) {
238 : 68 : continue;
239 : : } else {
240 : 4 : cdw11 = nsdata->endgid;
241 : : /* Endurance group scope */
242 : 4 : nsid = 0;
243 : : }
244 : : }
245 [ + - ]: 332 : if (get_feature(ctrlr, features_to_get[i], cdw11, nsid) == 0) {
246 : 332 : outstanding_commands++;
247 : : } else {
248 [ # # ]: 0 : printf("get_feature(0x%02X) failed to submit command\n", features_to_get[i]);
249 : : }
250 : :
251 [ + + ]: 10107 : while (outstanding_commands) {
252 : 9775 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
253 : : }
254 : : }
255 : :
256 : 136 : }
257 : :
258 : : static void
259 : 64 : get_ctrlr_features(struct spdk_nvme_ctrlr *ctrlr)
260 : : {
261 : 64 : uint8_t features_to_get[] = {
262 : : SPDK_NVME_FEAT_ARBITRATION,
263 : : SPDK_NVME_FEAT_POWER_MANAGEMENT,
264 : : SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD,
265 : : SPDK_NVME_FEAT_NUMBER_OF_QUEUES,
266 : : SPDK_OCSSD_FEAT_MEDIA_FEEDBACK,
267 : : };
268 : :
269 : 64 : get_features(ctrlr, features_to_get, SPDK_COUNTOF(features_to_get), 0);
270 : 64 : }
271 : :
272 : : static void
273 : 72 : get_ns_features(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
274 : : {
275 : 72 : uint8_t features_to_get[] = {
276 : : SPDK_NVME_FEAT_ERROR_RECOVERY,
277 : : SPDK_NVME_FEAT_FDP,
278 : : };
279 : :
280 : 72 : get_features(ctrlr, features_to_get, SPDK_COUNTOF(features_to_get), nsid);
281 : 72 : }
282 : :
283 : : static int
284 : 64 : get_error_log_page(struct spdk_nvme_ctrlr *ctrlr)
285 : : {
286 : : const struct spdk_nvme_ctrlr_data *cdata;
287 : :
288 : 64 : cdata = spdk_nvme_ctrlr_get_data(ctrlr);
289 : :
290 [ - + ]: 64 : if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_ERROR,
291 : : SPDK_NVME_GLOBAL_NS_TAG, error_page,
292 : 64 : sizeof(*error_page) * (cdata->elpe + 1),
293 : : 0,
294 : : get_log_page_completion, NULL)) {
295 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
296 : 0 : exit(1);
297 : : }
298 : :
299 : 64 : return 0;
300 : : }
301 : :
302 : : static int
303 : 64 : get_health_log_page(struct spdk_nvme_ctrlr *ctrlr)
304 : : {
305 [ - + ]: 64 : if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_HEALTH_INFORMATION,
306 : : SPDK_NVME_GLOBAL_NS_TAG, &health_page, sizeof(health_page), 0, get_log_page_completion, NULL)) {
307 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
308 : 0 : exit(1);
309 : : }
310 : :
311 : 64 : return 0;
312 : : }
313 : :
314 : : static int
315 : 64 : get_firmware_log_page(struct spdk_nvme_ctrlr *ctrlr)
316 : : {
317 [ - + ]: 64 : if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_FIRMWARE_SLOT,
318 : : SPDK_NVME_GLOBAL_NS_TAG, &firmware_page, sizeof(firmware_page), 0, get_log_page_completion, NULL)) {
319 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
320 : 0 : exit(1);
321 : : }
322 : :
323 : 64 : return 0;
324 : : }
325 : :
326 : : static int
327 : 4 : get_ana_log_page(struct spdk_nvme_ctrlr *ctrlr)
328 : : {
329 [ - + ]: 4 : if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_ASYMMETRIC_NAMESPACE_ACCESS,
330 : : SPDK_NVME_GLOBAL_NS_TAG, g_ana_log_page, g_ana_log_page_size, 0,
331 : : get_log_page_completion, NULL)) {
332 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
333 : 0 : exit(1);
334 : : }
335 : :
336 : 4 : return 0;
337 : : }
338 : :
339 : : static int
340 : 64 : get_cmd_effects_log_page(struct spdk_nvme_ctrlr *ctrlr)
341 : : {
342 [ - + ]: 64 : if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_COMMAND_EFFECTS_LOG,
343 : : SPDK_NVME_GLOBAL_NS_TAG, &cmd_effects_log_page, sizeof(cmd_effects_log_page), 0,
344 : : get_log_page_completion, NULL)) {
345 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
346 : 0 : exit(1);
347 : : }
348 : :
349 : 64 : return 0;
350 : : }
351 : :
352 : : static int
353 : 7 : get_intel_smart_log_page(struct spdk_nvme_ctrlr *ctrlr)
354 : : {
355 [ - + ]: 7 : if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_INTEL_LOG_SMART, SPDK_NVME_GLOBAL_NS_TAG,
356 : : &intel_smart_page, sizeof(intel_smart_page), 0, get_log_page_completion, NULL)) {
357 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
358 : 0 : exit(1);
359 : : }
360 : :
361 : 7 : return 0;
362 : : }
363 : :
364 : : static int
365 : 7 : get_intel_temperature_log_page(struct spdk_nvme_ctrlr *ctrlr)
366 : : {
367 [ - + ]: 7 : if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_INTEL_LOG_TEMPERATURE,
368 : : SPDK_NVME_GLOBAL_NS_TAG, &intel_temperature_page, sizeof(intel_temperature_page), 0,
369 : : get_log_page_completion, NULL)) {
370 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
371 : 0 : exit(1);
372 : : }
373 : 7 : return 0;
374 : : }
375 : :
376 : : static int
377 : 7 : get_intel_md_log_page(struct spdk_nvme_ctrlr *ctrlr)
378 : : {
379 [ - + ]: 7 : if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_INTEL_MARKETING_DESCRIPTION,
380 : : SPDK_NVME_GLOBAL_NS_TAG, &intel_md_page, sizeof(intel_md_page), 0,
381 : : get_log_page_completion, NULL)) {
382 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
383 : 0 : exit(1);
384 : : }
385 : 7 : return 0;
386 : : }
387 : :
388 : : static void
389 : 8 : get_discovery_log_page_cb(void *ctx, int rc, const struct spdk_nvme_cpl *cpl,
390 : : struct spdk_nvmf_discovery_log_page *log_page)
391 : : {
392 [ + - + - : 8 : if (rc || spdk_nvme_cpl_is_error(cpl)) {
- + ]
393 [ # # ]: 0 : printf("get discovery log page failed\n");
394 : 0 : exit(1);
395 : : }
396 : :
397 : 8 : g_discovery_page = log_page;
398 : 8 : g_discovery_page_numrec = from_le64(&log_page->numrec);
399 : 8 : g_discovery_page_size = sizeof(struct spdk_nvmf_discovery_log_page);
400 : 8 : g_discovery_page_size += g_discovery_page_numrec *
401 : : sizeof(struct spdk_nvmf_discovery_log_page_entry);
402 : 8 : outstanding_commands--;
403 : 8 : }
404 : :
405 : : static int
406 : 8 : get_discovery_log_page(struct spdk_nvme_ctrlr *ctrlr)
407 : : {
408 : 8 : return spdk_nvme_ctrlr_get_discovery_log_page(ctrlr, get_discovery_log_page_cb, NULL);
409 : : }
410 : :
411 : : static void
412 : 72 : get_log_pages(struct spdk_nvme_ctrlr *ctrlr)
413 : : {
414 : : const struct spdk_nvme_ctrlr_data *cdata;
415 : 72 : outstanding_commands = 0;
416 : 72 : bool is_discovery = spdk_nvme_ctrlr_is_discovery(ctrlr);
417 : 72 : uint32_t nsid, active_ns_count = 0;
418 : :
419 : 72 : cdata = spdk_nvme_ctrlr_get_data(ctrlr);
420 : :
421 [ + + ]: 72 : if (!is_discovery) {
422 : : /*
423 : : * Only attempt to retrieve the following log pages
424 : : * when the NVM subsystem that's being targeted is
425 : : * NOT the Discovery Controller which only fields
426 : : * a Discovery Log Page.
427 : : */
428 [ + - ]: 64 : if (get_error_log_page(ctrlr) == 0) {
429 : 64 : outstanding_commands++;
430 : : } else {
431 [ # # ]: 0 : printf("Get Error Log Page failed\n");
432 : : }
433 : :
434 [ + - ]: 64 : if (get_health_log_page(ctrlr) == 0) {
435 : 64 : outstanding_commands++;
436 : : } else {
437 [ # # ]: 0 : printf("Get Log Page (SMART/health) failed\n");
438 : : }
439 : :
440 [ + - ]: 64 : if (get_firmware_log_page(ctrlr) == 0) {
441 : 64 : outstanding_commands++;
442 : : } else {
443 [ # # ]: 0 : printf("Get Log Page (Firmware Slot Information) failed\n");
444 : : }
445 : : }
446 : :
447 [ + + ]: 72 : if (spdk_nvme_ctrlr_is_log_page_supported(ctrlr, SPDK_NVME_LOG_ASYMMETRIC_NAMESPACE_ACCESS)) {
448 : 4 : for (nsid = spdk_nvme_ctrlr_get_first_active_ns(ctrlr);
449 [ + + ]: 8 : nsid != 0; nsid = spdk_nvme_ctrlr_get_next_active_ns(ctrlr, nsid)) {
450 : 4 : active_ns_count++;
451 : : }
452 : :
453 : : /* We always set RGO (Return Groups Only) to 0 in this tool, an ANA group
454 : : * descriptor is returned only if that ANA group contains namespaces
455 : : * that are attached to the controller processing the command, and
456 : : * namespaces attached to the controller shall be members of an ANA group.
457 : : * Hence the following size should be enough.
458 : : */
459 : 4 : g_ana_log_page_size = sizeof(struct spdk_nvme_ana_page) + cdata->nanagrpid *
460 : 4 : sizeof(struct spdk_nvme_ana_group_descriptor) + active_ns_count *
461 : : sizeof(uint32_t);
462 : 4 : g_ana_log_page = calloc(1, g_ana_log_page_size);
463 [ - + ]: 4 : if (g_ana_log_page == NULL) {
464 : 0 : exit(1);
465 : : }
466 : 4 : g_copied_ana_desc = calloc(1, g_ana_log_page_size);
467 [ - + ]: 4 : if (g_copied_ana_desc == NULL) {
468 : 0 : exit(1);
469 : : }
470 [ + - ]: 4 : if (get_ana_log_page(ctrlr) == 0) {
471 : 4 : outstanding_commands++;
472 : : } else {
473 [ # # ]: 0 : printf("Get Log Page (Asymmetric Namespace Access) failed\n");
474 : : }
475 : : }
476 [ + + ]: 72 : if (cdata->lpa.celp) {
477 [ + - ]: 64 : if (get_cmd_effects_log_page(ctrlr) == 0) {
478 : 64 : outstanding_commands++;
479 : : } else {
480 [ # # ]: 0 : printf("Get Log Page (Commands Supported and Effects) failed\n");
481 : : }
482 : : }
483 : :
484 [ + + ]: 72 : if (cdata->vid == SPDK_PCI_VID_INTEL) {
485 [ + + ]: 15 : if (spdk_nvme_ctrlr_is_log_page_supported(ctrlr, SPDK_NVME_INTEL_LOG_SMART)) {
486 [ + - ]: 7 : if (get_intel_smart_log_page(ctrlr) == 0) {
487 : 7 : outstanding_commands++;
488 : : } else {
489 [ # # ]: 0 : printf("Get Log Page (Intel SMART/health) failed\n");
490 : : }
491 : : }
492 [ + + ]: 15 : if (spdk_nvme_ctrlr_is_log_page_supported(ctrlr, SPDK_NVME_INTEL_LOG_TEMPERATURE)) {
493 [ + - ]: 7 : if (get_intel_temperature_log_page(ctrlr) == 0) {
494 : 7 : outstanding_commands++;
495 : : } else {
496 [ # # ]: 0 : printf("Get Log Page (Intel temperature) failed\n");
497 : : }
498 : : }
499 [ + + ]: 15 : if (spdk_nvme_ctrlr_is_log_page_supported(ctrlr, SPDK_NVME_INTEL_MARKETING_DESCRIPTION)) {
500 [ + - ]: 7 : if (get_intel_md_log_page(ctrlr) == 0) {
501 : 7 : outstanding_commands++;
502 : : } else {
503 [ # # ]: 0 : printf("Get Log Page (Intel Marketing Description) failed\n");
504 : : }
505 : : }
506 : :
507 : : }
508 : :
509 [ + + + - ]: 72 : if (is_discovery && (get_discovery_log_page(ctrlr) == 0)) {
510 : 8 : outstanding_commands++;
511 : : }
512 : :
513 [ + + ]: 27630 : while (outstanding_commands) {
514 : 27558 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
515 : : }
516 : 72 : }
517 : :
518 : : static int
519 : 4 : get_fdp_cfg_log_page(struct spdk_nvme_ns *ns)
520 : : {
521 : 4 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
522 : 4 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
523 : :
524 : 4 : outstanding_commands = 0;
525 : :
526 : 4 : g_fdp_cfg_log_page_size = sizeof(struct spdk_nvme_fdp_cfg_log_page);
527 : 4 : g_fdp_cfg_log_page = calloc(1, g_fdp_cfg_log_page_size);
528 [ - + ]: 4 : if (!g_fdp_cfg_log_page) {
529 [ # # ]: 0 : printf("FDP config log page allocation failed!\n");
530 : 0 : return -1;
531 : : }
532 : :
533 : : /* Fetch the FDP configurations log page header */
534 [ + - ]: 4 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_CONFIGURATIONS, 0,
535 [ - + ]: 4 : g_fdp_cfg_log_page, g_fdp_cfg_log_page_size, 0, 0, (nsdata->endgid << 16),
536 : : 0, get_log_page_completion, NULL) == 0) {
537 : 4 : outstanding_commands++;
538 : : } else {
539 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP config) failed\n");
540 : 0 : free(g_fdp_cfg_log_page);
541 : 0 : return -1;
542 : : }
543 : :
544 [ + + ]: 25 : while (outstanding_commands) {
545 : 21 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
546 : : }
547 : :
548 : 4 : g_fdp_cfg_log_page_size = g_fdp_cfg_log_page->size;
549 : 4 : g_fdp_cfg_log_page = realloc(g_fdp_cfg_log_page, g_fdp_cfg_log_page_size);
550 [ - + ]: 4 : if (!g_fdp_cfg_log_page) {
551 [ # # ]: 0 : printf("FDP config log page reallocation failed!\n");
552 : 0 : return -1;
553 : : }
554 : :
555 : : /* Fetch the FDP configurations log page */
556 [ + - ]: 4 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_CONFIGURATIONS, 0,
557 [ - + ]: 4 : g_fdp_cfg_log_page, g_fdp_cfg_log_page_size, 0, 0, (nsdata->endgid << 16),
558 : : 0, get_log_page_completion, NULL) == 0) {
559 : 4 : outstanding_commands++;
560 : : } else {
561 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP config) failed\n");
562 : 0 : free(g_fdp_cfg_log_page);
563 : 0 : return -1;
564 : : }
565 : :
566 [ + + ]: 26 : while (outstanding_commands) {
567 : 22 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
568 : : }
569 : :
570 : 4 : return 0;
571 : : }
572 : :
573 : : static int
574 : 4 : get_fdp_ruhu_log_page(struct spdk_nvme_ns *ns)
575 : : {
576 : 4 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
577 : 4 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
578 : :
579 : 4 : outstanding_commands = 0;
580 : :
581 : 4 : g_fdp_ruhu_log_page_size = sizeof(struct spdk_nvme_fdp_ruhu_log_page);
582 : 4 : g_fdp_ruhu_log_page = calloc(1, g_fdp_ruhu_log_page_size);
583 [ - + ]: 4 : if (!g_fdp_ruhu_log_page) {
584 [ # # ]: 0 : printf("FDP RUH usage log page allocation failed!\n");
585 : 0 : return -1;
586 : : }
587 : :
588 : : /* Fetch the reclaim unit handle usage log page header */
589 [ + - ]: 4 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_RECLAIM_UNIT_HANDLE_USAGE, 0,
590 [ - + ]: 4 : g_fdp_ruhu_log_page, g_fdp_ruhu_log_page_size, 0, 0, (nsdata->endgid << 16),
591 : : 0, get_log_page_completion, NULL) == 0) {
592 : 4 : outstanding_commands++;
593 : : } else {
594 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page_ext(RUH usage) failed\n");
595 : 0 : free(g_fdp_ruhu_log_page);
596 : 0 : return -1;
597 : : }
598 : :
599 [ + + ]: 17 : while (outstanding_commands) {
600 : 13 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
601 : : }
602 : :
603 : 4 : g_fdp_ruhu_log_page_size += g_fdp_ruhu_log_page->nruh *
604 : : sizeof(struct spdk_nvme_fdp_ruhu_descriptor);
605 : 4 : g_fdp_ruhu_log_page = realloc(g_fdp_ruhu_log_page, g_fdp_ruhu_log_page_size);
606 [ - + ]: 4 : if (!g_fdp_ruhu_log_page) {
607 [ # # ]: 0 : printf("FDP RUH usage log page reallocation failed!\n");
608 : 0 : return -1;
609 : : }
610 : :
611 : : /* Fetch the reclaim unit handle usage log page */
612 [ + - ]: 4 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_RECLAIM_UNIT_HANDLE_USAGE, 0,
613 [ - + ]: 4 : g_fdp_ruhu_log_page, g_fdp_ruhu_log_page_size, 0, 0, (nsdata->endgid << 16),
614 : : 0, get_log_page_completion, NULL) == 0) {
615 : 4 : outstanding_commands++;
616 : : } else {
617 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page_ext(RUH usage) failed\n");
618 : 0 : free(g_fdp_ruhu_log_page);
619 : 0 : return -1;
620 : : }
621 : :
622 [ + + ]: 25 : while (outstanding_commands) {
623 : 21 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
624 : : }
625 : :
626 : 4 : return 0;
627 : : }
628 : :
629 : : static int
630 : 4 : get_fdp_stats_log_page(struct spdk_nvme_ns *ns)
631 : : {
632 : 4 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
633 : 4 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
634 : :
635 : 4 : outstanding_commands = 0;
636 : :
637 [ + - ]: 4 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_STATISTICS, 0,
638 [ - + ]: 4 : &g_fdp_stats_log_page, 64, 0, 0, (nsdata->endgid << 16), 0,
639 : : get_log_page_completion, NULL) == 0) {
640 : 4 : outstanding_commands++;
641 : : } else {
642 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP stats) failed\n");
643 : 0 : return -1;
644 : : }
645 : :
646 [ + + ]: 23 : while (outstanding_commands) {
647 : 19 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
648 : : }
649 : :
650 : 4 : return 0;
651 : : }
652 : :
653 : : static int
654 : 4 : get_fdp_events_log_page(struct spdk_nvme_ns *ns)
655 : : {
656 : 4 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
657 : 4 : const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
658 : :
659 : 4 : outstanding_commands = 0;
660 : :
661 : 4 : g_fdp_events_log_page_size = sizeof(struct spdk_nvme_fdp_events_log_page);
662 : 4 : g_fdp_events_log_page = calloc(1, g_fdp_events_log_page_size);
663 [ - + ]: 4 : if (!g_fdp_events_log_page) {
664 [ # # ]: 0 : printf("FDP events log page allocation failed!\n");
665 : 0 : return -1;
666 : : }
667 : :
668 : : /* Fetch the FDP events log page header */
669 [ + - ]: 4 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_EVENTS, 0,
670 : : g_fdp_events_log_page, g_fdp_events_log_page_size, 0,
671 [ - + ]: 4 : (SPDK_NVME_FDP_REPORT_HOST_EVENTS << 8), (nsdata->endgid << 16),
672 : : 0, get_log_page_completion, NULL) == 0) {
673 : 4 : outstanding_commands++;
674 : : } else {
675 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP events) failed\n");
676 : 0 : free(g_fdp_events_log_page);
677 : 0 : return -1;
678 : : }
679 : :
680 [ + + ]: 25 : while (outstanding_commands) {
681 : 21 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
682 : : }
683 : :
684 : 4 : g_fdp_events_log_page_size += g_fdp_events_log_page->nevents *
685 : : sizeof(struct spdk_nvme_fdp_event);
686 : 4 : g_fdp_events_log_page = realloc(g_fdp_events_log_page, g_fdp_events_log_page_size);
687 [ - + ]: 4 : if (!g_fdp_events_log_page) {
688 [ # # ]: 0 : printf("FDP events log page reallocation failed!\n");
689 : 0 : return -1;
690 : : }
691 : :
692 : : /* Only fetch FDP events log page for host events */
693 [ + - ]: 4 : if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_EVENTS, 0,
694 : : g_fdp_events_log_page, g_fdp_events_log_page_size, 0,
695 [ - + ]: 4 : (SPDK_NVME_FDP_REPORT_HOST_EVENTS << 8), (nsdata->endgid << 16),
696 : : 0, get_log_page_completion, NULL) == 0) {
697 : 4 : outstanding_commands++;
698 : : } else {
699 [ # # ]: 0 : printf("spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP events) failed\n");
700 : 0 : free(g_fdp_events_log_page);
701 : 0 : return -1;
702 : : }
703 : :
704 [ + + ]: 23 : while (outstanding_commands) {
705 : 19 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
706 : : }
707 : :
708 : 4 : return 0;
709 : : }
710 : :
711 : : static int
712 : 0 : get_ocssd_chunk_info_log_page(struct spdk_nvme_ns *ns)
713 : : {
714 : 0 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
715 : 0 : int nsid = spdk_nvme_ns_get_id(ns);
716 : 0 : uint32_t num_entry = geometry_data.num_grp * geometry_data.num_pu * geometry_data.num_chk;
717 : 0 : uint32_t xfer_size = spdk_nvme_ns_get_max_io_xfer_size(ns);
718 : 0 : uint32_t buf_size = 0;
719 : 0 : uint64_t buf_offset = 0;
720 : 0 : outstanding_commands = 0;
721 : :
722 [ # # ]: 0 : assert(num_entry != 0);
723 [ # # # # ]: 0 : if (!g_ocssd_verbose) {
724 : 0 : num_entry = spdk_min(num_entry, NUM_CHUNK_INFO_ENTRIES);
725 : : }
726 : :
727 : 0 : g_ocssd_chunk_info_page = calloc(num_entry, sizeof(struct spdk_ocssd_chunk_information_entry));
728 [ # # ]: 0 : assert(g_ocssd_chunk_info_page != NULL);
729 : :
730 : 0 : buf_size = num_entry * sizeof(struct spdk_ocssd_chunk_information_entry);
731 [ # # ]: 0 : while (buf_size > 0) {
732 : 0 : xfer_size = spdk_min(buf_size, xfer_size);
733 [ # # ]: 0 : if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_OCSSD_LOG_CHUNK_INFO,
734 : 0 : nsid, (void *) g_ocssd_chunk_info_page + buf_offset,
735 : : xfer_size, buf_offset, get_log_page_completion, NULL) == 0) {
736 : 0 : outstanding_commands++;
737 : : } else {
738 [ # # ]: 0 : printf("get_ocssd_chunk_info_log_page() failed\n");
739 : 0 : return -1;
740 : : }
741 : :
742 : 0 : buf_size -= xfer_size;
743 : 0 : buf_offset += xfer_size;
744 : : }
745 : :
746 [ # # ]: 0 : while (outstanding_commands) {
747 : 0 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
748 : : }
749 : :
750 : 0 : return 0;
751 : : }
752 : :
753 : : static void
754 : 0 : get_ocssd_geometry(struct spdk_nvme_ns *ns, struct spdk_ocssd_geometry_data *geometry_data)
755 : : {
756 : 0 : struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
757 : 0 : int nsid = spdk_nvme_ns_get_id(ns);
758 : 0 : outstanding_commands = 0;
759 : :
760 [ # # ]: 0 : if (spdk_nvme_ocssd_ctrlr_cmd_geometry(ctrlr, nsid, geometry_data,
761 : : sizeof(*geometry_data), get_ocssd_geometry_completion, NULL)) {
762 [ # # ]: 0 : printf("Get OpenChannel SSD geometry failed\n");
763 : 0 : exit(1);
764 : : } else {
765 : 0 : outstanding_commands++;
766 : : }
767 : :
768 [ # # ]: 0 : while (outstanding_commands) {
769 : 0 : spdk_nvme_ctrlr_process_admin_completions(ctrlr);
770 : : }
771 : 0 : }
772 : :
773 : : static void
774 : 27 : print_hex_be(const void *v, size_t size)
775 : : {
776 : 27 : const uint8_t *buf = v;
777 : :
778 [ + + ]: 371 : while (size--) {
779 [ - + ]: 344 : printf("%02X", *buf++);
780 : : }
781 : 27 : }
782 : :
783 : : static void
784 : 0 : print_uint128_hex(uint64_t *v)
785 : : {
786 : 0 : unsigned long long lo = v[0], hi = v[1];
787 [ # # ]: 0 : if (hi) {
788 [ # # ]: 0 : printf("0x%llX%016llX", hi, lo);
789 : : } else {
790 [ # # ]: 0 : printf("0x%llX", lo);
791 : : }
792 : 0 : }
793 : :
794 : : static void
795 : 612 : print_uint128_dec(uint64_t *v)
796 : : {
797 : 612 : unsigned long long lo = v[0], hi = v[1];
798 [ - + ]: 612 : if (hi) {
799 : : /* can't handle large (>64-bit) decimal values for now, so fall back to hex */
800 : 0 : print_uint128_hex(v);
801 : : } else {
802 [ - + ]: 612 : printf("%llu", (unsigned long long)lo);
803 : : }
804 : 612 : }
805 : :
806 : : /* The len should be <= 8. */
807 : : static void
808 : 99 : print_uint_var_dec(uint8_t *array, unsigned int len)
809 : : {
810 : 99 : uint64_t result = 0;
811 : 99 : int i = len;
812 : :
813 [ + + ]: 607 : while (i > 0) {
814 [ - + ]: 508 : result += (uint64_t)array[i - 1] << (8 * (i - 1));
815 : 508 : i--;
816 : : }
817 [ - + ]: 99 : printf("%" PRIu64, result);
818 : 99 : }
819 : :
820 : : /* Print ASCII string as defined by the NVMe spec */
821 : : static void
822 : 276 : print_ascii_string(const void *buf, size_t size)
823 : : {
824 : 276 : const uint8_t *str = buf;
825 : :
826 : : /* Trim trailing spaces */
827 [ + - + + ]: 3068 : while (size > 0 && str[size - 1] == ' ') {
828 : 2792 : size--;
829 : : }
830 : :
831 [ + + ]: 2860 : while (size--) {
832 [ + + + - ]: 2584 : if (*str >= 0x20 && *str <= 0x7E) {
833 : 2344 : printf("%c", *str);
834 : : } else {
835 : 240 : printf(".");
836 : : }
837 : 2584 : str++;
838 : : }
839 : 276 : }
840 : :
841 : : /* Underline a "line" with the given marker, e.g. print_uline("=", printf(...)); */
842 : : static void
843 : 0 : print_uline(char marker, int line_len)
844 : : {
845 [ # # ]: 0 : for (int i = 1; i < line_len; ++i) {
846 : 0 : putchar(marker);
847 : : }
848 : 0 : putchar('\n');
849 : 0 : }
850 : :
851 : : static void
852 : 4 : print_fdp_cfg_log_page(void)
853 : : {
854 : : uint32_t i, j;
855 : : struct spdk_nvme_fdp_cfg_descriptor *cfg_desc;
856 : 4 : void *log = g_fdp_cfg_log_page->cfg_desc;
857 : :
858 [ - + ]: 4 : printf("FDP configurations log page\n");
859 [ - + ]: 4 : printf("===========================\n");
860 [ - + - + ]: 4 : if (g_hex_dump) {
861 : 0 : hex_dump(g_fdp_cfg_log_page, FDP_LOG_PAGE_SIZE);
862 : 0 : printf("\n");
863 : : }
864 : :
865 [ - + ]: 4 : printf("Number of FDP configurations: %u\n", g_fdp_cfg_log_page->ncfg + 1);
866 [ - + ]: 4 : printf("Version: %u\n", g_fdp_cfg_log_page->version);
867 [ - + ]: 4 : printf("Size: %u\n", g_fdp_cfg_log_page->size);
868 : :
869 [ + + ]: 8 : for (i = 0; i <= g_fdp_cfg_log_page->ncfg; i++) {
870 : 4 : cfg_desc = log;
871 [ - + ]: 4 : printf("FDP Configuration Descriptor: %u\n", i);
872 [ - + ]: 4 : printf(" Descriptor Size: %u\n", cfg_desc->ds);
873 [ - + ]: 4 : printf(" Reclaim Group Identifier format: %u\n", cfg_desc->fdpa.bits.rgif);
874 [ - + ]: 4 : printf(" FDP Volatile Write Cache: %s\n",
875 [ - + ]: 4 : cfg_desc->fdpa.bits.fdpvwc ? "Present" : "Not Present");
876 [ - + ]: 4 : printf(" FDP Configuration: %s\n",
877 [ + - ]: 4 : cfg_desc->fdpa.bits.fdpcv ? "Valid" : "Invalid");
878 [ - + ]: 4 : printf(" Vendor Specific Size: %u\n", cfg_desc->vss);
879 [ - + ]: 4 : printf(" Number of Reclaim Groups: %u\n", cfg_desc->nrg);
880 [ - + ]: 4 : printf(" Number of Recalim Unit Handles: %u\n", cfg_desc->nruh);
881 [ - + ]: 4 : printf(" Max Placement Identifiers: %u\n", cfg_desc->maxpids + 1);
882 [ - + ]: 4 : printf(" Number of Namespaces Suppprted: %u\n", cfg_desc->nns);
883 [ - + ]: 4 : printf(" Reclaim unit Nominal Size: %" PRIx64 " bytes\n", cfg_desc->runs);
884 [ - + ]: 4 : printf(" Estimated Reclaim Unit Time Limit: ");
885 [ - + ]: 4 : if (cfg_desc->erutl) {
886 [ # # ]: 0 : printf("%u seconds\n", cfg_desc->erutl);
887 : : } else {
888 [ - + ]: 4 : printf("Not Reported\n");
889 : : }
890 [ + + ]: 36 : for (j = 0; j < cfg_desc->nruh; j++) {
891 [ - + ]: 32 : printf(" RUH Desc #%03d: RUH Type: %s\n", j,
892 [ - + ]: 32 : cfg_desc->ruh_desc[j].ruht == SPDK_NVME_FDP_RUHT_INITIALLY_ISOLATED ? "Initially Isolated" :
893 [ # # ]: 0 : cfg_desc->ruh_desc[j].ruht == SPDK_NVME_FDP_RUHT_PERSISTENTLY_ISOLATED ? "Persistently Isolated" :
894 : : "Reserved");
895 : : }
896 : 4 : log += cfg_desc->ds;
897 : : }
898 : :
899 : 4 : free(g_fdp_cfg_log_page);
900 : 4 : printf("\n");
901 : 4 : }
902 : :
903 : : static void
904 : 4 : print_fdp_ruhu_log_page(void)
905 : : {
906 : : uint32_t i;
907 : : struct spdk_nvme_fdp_ruhu_descriptor *ruhu_desc;
908 : :
909 [ - + ]: 4 : printf("FDP reclaim unit handle usage log page\n");
910 [ - + ]: 4 : printf("======================================\n");
911 [ - + - + ]: 4 : if (g_hex_dump) {
912 : 0 : hex_dump(g_fdp_ruhu_log_page, FDP_LOG_PAGE_SIZE);
913 : 0 : printf("\n");
914 : : }
915 : :
916 [ - + ]: 4 : printf("Number of Reclaim Unit Handles: %u\n", g_fdp_ruhu_log_page->nruh);
917 : :
918 [ + + ]: 36 : for (i = 0; i < g_fdp_ruhu_log_page->nruh; i++) {
919 : 32 : ruhu_desc = &g_fdp_ruhu_log_page->ruhu_desc[i];
920 : :
921 [ - + ]: 32 : printf(" RUH Usage Desc #%03d: RUH Attributes: %s\n", i,
922 [ + + ]: 32 : ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_UNUSED ? "Unused" :
923 [ + - ]: 8 : ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_HOST_SPECIFIED ? "Host Specified" :
924 [ + - ]: 4 : ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_CTRLR_SPECIFIED ? "Controller Specified" :
925 : : "Reserved");
926 : : }
927 : :
928 : 4 : free(g_fdp_ruhu_log_page);
929 : 4 : printf("\n");
930 : 4 : }
931 : :
932 : : static void
933 : 4 : print_fdp_stats_log_page(void)
934 : : {
935 [ - + ]: 4 : printf("FDP statistics log page\n");
936 [ - + ]: 4 : printf("=======================\n");
937 [ - + - + ]: 4 : if (g_hex_dump) {
938 : 0 : hex_dump(&g_fdp_stats_log_page, 64);
939 : 0 : printf("\n");
940 : : }
941 : :
942 [ - + ]: 4 : printf("Host bytes with metadata written: ");
943 : 4 : print_uint128_dec(g_fdp_stats_log_page.hbmw);
944 : 4 : printf("\n");
945 [ - + ]: 4 : printf("Media bytes with metadata written: ");
946 : 4 : print_uint128_dec(g_fdp_stats_log_page.mbmw);
947 : 4 : printf("\n");
948 [ - + ]: 4 : printf("Media bytes erased: ");
949 : 4 : print_uint128_dec(g_fdp_stats_log_page.mbe);
950 [ - + ]: 4 : printf("\n\n");
951 : 4 : }
952 : :
953 : : static void
954 : 4 : print_fdp_events_log_page(void)
955 : : {
956 : : uint32_t i;
957 : : struct spdk_nvme_fdp_event *event;
958 : : struct spdk_nvme_fdp_event_media_reallocated *media_reallocated;
959 : :
960 [ - + ]: 4 : printf("FDP events log page\n");
961 [ - + ]: 4 : printf("===================\n");
962 [ - + - + ]: 4 : if (g_hex_dump) {
963 : 0 : hex_dump(g_fdp_events_log_page, FDP_LOG_PAGE_SIZE);
964 : 0 : printf("\n");
965 : : }
966 : :
967 [ - + ]: 4 : printf("Number of FDP events: %u\n", g_fdp_events_log_page->nevents);
968 : :
969 [ - + ]: 4 : for (i = 0; i < g_fdp_events_log_page->nevents; i++) {
970 : 0 : event = &g_fdp_events_log_page->event[i];
971 : :
972 [ # # ]: 0 : printf("FDP Event #%u:\n", i);
973 [ # # ]: 0 : printf(" Event Type: %s\n",
974 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_RU_NOT_WRITTEN_CAPACITY ? "RU Not Written to Capacity" :
975 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_RU_TIME_LIMIT_EXCEEDED ? "RU Time Limit Exceeded" :
976 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_CTRLR_RESET_MODIFY_RUH ? "Ctrlr Reset Modified RUH's" :
977 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_INVALID_PLACEMENT_ID ? "Invalid Placement Identifier" :
978 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED ? "Media Reallocated" :
979 [ # # ]: 0 : event->etype == SPDK_NVME_FDP_EVENT_IMPLICIT_MODIFIED_RUH ? "Implicitly modified RUH" :
980 : : "Reserved");
981 [ # # ]: 0 : printf(" Placement Identifier: %s\n",
982 [ # # ]: 0 : event->fdpef.bits.piv ? "Valid" : "Invalid");
983 [ # # ]: 0 : printf(" NSID: %s\n",
984 [ # # ]: 0 : event->fdpef.bits.nsidv ? "Valid" : "Invalid");
985 [ # # ]: 0 : printf(" Location: %s\n",
986 [ # # ]: 0 : event->fdpef.bits.lv ? "Valid" : "Invalid");
987 [ # # ]: 0 : if (event->fdpef.bits.piv) {
988 [ # # ]: 0 : printf(" Placement Identifier: %u\n", event->pid);
989 : : } else {
990 [ # # ]: 0 : printf(" Placement Identifier: Reserved\n");
991 : : }
992 [ # # ]: 0 : printf(" Event Timestamp: %" PRIx64 "\n", event->timestamp);
993 [ # # ]: 0 : if (event->fdpef.bits.nsidv) {
994 [ # # ]: 0 : printf(" Namespace Identifier: %u\n", event->nsid);
995 : : } else {
996 [ # # ]: 0 : printf(" Namespace Identifier: Ignore\n");
997 : : }
998 : :
999 [ # # ]: 0 : if (event->etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED) {
1000 : 0 : media_reallocated = (struct spdk_nvme_fdp_event_media_reallocated *)&event->event_type_specific;
1001 : :
1002 [ # # ]: 0 : printf(" LBA: %s\n",
1003 [ # # ]: 0 : media_reallocated->sef.bits.lbav ? "Valid" : "Invalid");
1004 [ # # ]: 0 : printf(" Number of LBA's Moved: %u\n", media_reallocated->nlbam);
1005 [ # # ]: 0 : if (media_reallocated->sef.bits.lbav) {
1006 [ # # ]: 0 : printf(" Logical Block Address: %u\n", event->nsid);
1007 : : } else {
1008 [ # # ]: 0 : printf(" Logical Block Address: Ignore\n");
1009 : : }
1010 : : }
1011 : :
1012 [ # # ]: 0 : if (event->fdpef.bits.lv) {
1013 [ # # ]: 0 : printf(" Reclaim Group Identifier: %u\n", event->rgid);
1014 : : } else {
1015 [ # # ]: 0 : printf(" Reclaim Group Identifier: Ignore\n");
1016 : : }
1017 [ # # ]: 0 : if (event->fdpef.bits.lv) {
1018 [ # # ]: 0 : printf(" Reclaim Unit Handle Identifier: %u\n", event->ruhid);
1019 : : } else {
1020 [ # # ]: 0 : printf(" Reclaim Unit Handle Identifier: Ignore\n");
1021 : : }
1022 : : }
1023 : :
1024 : 4 : free(g_fdp_events_log_page);
1025 : 4 : printf("\n");
1026 : 4 : }
1027 : :
1028 : : static void
1029 : 0 : print_ocssd_chunk_info(struct spdk_ocssd_chunk_information_entry *chk_info, int chk_num)
1030 : : {
1031 : : int i;
1032 : : char *cs_str, *ct_str;
1033 : :
1034 [ # # ]: 0 : printf("OCSSD Chunk Info Glance\n");
1035 [ # # ]: 0 : printf("======================\n");
1036 : :
1037 [ # # ]: 0 : for (i = 0; i < chk_num; i++) {
1038 [ # # ]: 0 : cs_str = chk_info[i].cs.free ? "Free" :
1039 [ # # ]: 0 : chk_info[i].cs.closed ? "Closed" :
1040 [ # # ]: 0 : chk_info[i].cs.open ? "Open" :
1041 [ # # ]: 0 : chk_info[i].cs.offline ? "Offline" : "Unknown";
1042 [ # # ]: 0 : ct_str = chk_info[i].ct.seq_write ? "Sequential Write" :
1043 [ # # ]: 0 : chk_info[i].ct.rnd_write ? "Random Write" : "Unknown";
1044 : :
1045 [ # # ]: 0 : printf("------------\n");
1046 [ # # ]: 0 : printf("Chunk index: %d\n", i);
1047 [ # # ]: 0 : printf("Chunk state: %s(0x%x)\n", cs_str, *(uint8_t *) & (chk_info[i].cs));
1048 [ # # ]: 0 : printf("Chunk type (write mode): %s\n", ct_str);
1049 [ # # # # ]: 0 : printf("Chunk type (size_deviate): %s\n", chk_info[i].ct.size_deviate ? "Yes" : "No");
1050 [ # # ]: 0 : printf("Wear-level Index: %d\n", chk_info[i].wli);
1051 [ # # ]: 0 : printf("Starting LBA: %" PRIu64 "\n", chk_info[i].slba);
1052 [ # # ]: 0 : printf("Number of blocks in chunk: %" PRIu64 "\n", chk_info[i].cnlb);
1053 [ # # ]: 0 : printf("Write Pointer: %" PRIu64 "\n", chk_info[i].wp);
1054 : : }
1055 : 0 : }
1056 : :
1057 : : static void
1058 : 0 : print_ocssd_chunk_info_verbose(struct spdk_ocssd_chunk_information_entry *chk_info)
1059 : : {
1060 : : uint32_t pu, chk, i;
1061 : : uint32_t cnt_free, cnt_closed, cnt_open, cnt_offline;
1062 : 0 : uint32_t max_pu = spdk_min(MAX_OCSSD_PU, (geometry_data.num_grp * geometry_data.num_pu));
1063 : 0 : char cs_str[MAX_OCSSD_PU + 1], cs;
1064 : :
1065 [ # # ]: 0 : assert(chk_info != NULL);
1066 [ # # ]: 0 : printf("OCSSD Chunk Info Verbose\n");
1067 [ # # ]: 0 : printf("======================\n");
1068 : :
1069 [ # # ]: 0 : printf("%4s %-*s %3s %3s %3s %3s\n", "band", max_pu, "chunk state", "fr", "cl", "op", "of");
1070 [ # # ]: 0 : for (chk = 0; chk < geometry_data.num_chk; chk++) {
1071 : 0 : cnt_free = cnt_closed = cnt_open = cnt_offline = 0;
1072 [ # # ]: 0 : for (pu = 0; pu < max_pu; pu++) {
1073 : 0 : i = (pu * geometry_data.num_chk) + chk;
1074 [ # # ]: 0 : if (chk_info[i].cs.free) {
1075 : 0 : cnt_free++;
1076 : 0 : cs = 'f';
1077 [ # # ]: 0 : } else if (chk_info[i].cs.closed) {
1078 : 0 : cnt_closed++;
1079 : 0 : cs = 'c';
1080 [ # # ]: 0 : } else if (chk_info[i].cs.open) {
1081 : 0 : cnt_open++;
1082 : 0 : cs = 'o';
1083 [ # # ]: 0 : } else if (chk_info[i].cs.offline) {
1084 : 0 : cnt_offline++;
1085 : 0 : cs = 'l';
1086 : : } else {
1087 : 0 : cs = '.';
1088 : : }
1089 : 0 : cs_str[pu] = cs;
1090 : : }
1091 : 0 : cs_str[pu] = 0;
1092 [ # # ]: 0 : printf("%4d %s %3d %3d %3d %3d\n", chk, cs_str, cnt_free, cnt_closed, cnt_open, cnt_offline);
1093 : : }
1094 : 0 : }
1095 : :
1096 : : static void
1097 : 0 : print_ocssd_geometry(struct spdk_ocssd_geometry_data *geometry_data)
1098 : : {
1099 [ # # ]: 0 : printf("Namespace OCSSD Geometry\n");
1100 [ # # ]: 0 : printf("=======================\n");
1101 : :
1102 [ # # ]: 0 : if (geometry_data->mjr < 2) {
1103 [ # # ]: 0 : printf("Open-Channel Spec version is less than 2.0\n");
1104 [ # # ]: 0 : printf("OC version: maj:%d\n", geometry_data->mjr);
1105 : 0 : return;
1106 : : }
1107 : :
1108 [ # # ]: 0 : printf("OC version: maj:%d min:%d\n", geometry_data->mjr, geometry_data->mnr);
1109 [ # # ]: 0 : printf("LBA format:\n");
1110 [ # # ]: 0 : printf(" Group bits: %d\n", geometry_data->lbaf.grp_len);
1111 [ # # ]: 0 : printf(" PU bits: %d\n", geometry_data->lbaf.pu_len);
1112 [ # # ]: 0 : printf(" Chunk bits: %d\n", geometry_data->lbaf.chk_len);
1113 [ # # ]: 0 : printf(" Logical block bits: %d\n", geometry_data->lbaf.lbk_len);
1114 : :
1115 [ # # ]: 0 : printf("Media and Controller Capabilities:\n");
1116 [ # # ]: 0 : printf(" Namespace supports Vector Chunk Copy: %s\n",
1117 [ # # ]: 0 : geometry_data->mccap.vec_chk_cpy ? "Supported" : "Not Supported");
1118 [ # # ]: 0 : printf(" Namespace supports multiple resets a free chunk: %s\n",
1119 [ # # ]: 0 : geometry_data->mccap.multi_reset ? "Supported" : "Not Supported");
1120 : :
1121 [ # # ]: 0 : printf("Wear-level Index Delta Threshold: %d\n", geometry_data->wit);
1122 [ # # ]: 0 : printf("Groups (channels): %d\n", geometry_data->num_grp);
1123 [ # # ]: 0 : printf("PUs (LUNs) per group: %d\n", geometry_data->num_pu);
1124 [ # # ]: 0 : printf("Chunks per LUN: %d\n", geometry_data->num_chk);
1125 [ # # ]: 0 : printf("Logical blks per chunk: %d\n", geometry_data->clba);
1126 [ # # ]: 0 : printf("MIN write size: %d\n", geometry_data->ws_min);
1127 [ # # ]: 0 : printf("OPT write size: %d\n", geometry_data->ws_opt);
1128 [ # # ]: 0 : printf("Cache min write size: %d\n", geometry_data->mw_cunits);
1129 [ # # ]: 0 : printf("Max open chunks: %d\n", geometry_data->maxoc);
1130 [ # # ]: 0 : printf("Max open chunks per PU: %d\n", geometry_data->maxocpu);
1131 : 0 : printf("\n");
1132 : : }
1133 : :
1134 : : static void
1135 : 0 : print_zns_zone(uint8_t *report, uint32_t index, uint32_t zdes)
1136 : : {
1137 : : struct spdk_nvme_zns_zone_desc *desc;
1138 : : uint32_t i, zds, zrs, zd_index;
1139 : :
1140 : 0 : zrs = sizeof(struct spdk_nvme_zns_zone_report);
1141 : 0 : zds = sizeof(struct spdk_nvme_zns_zone_desc);
1142 : 0 : zd_index = zrs + index * (zds + zdes);
1143 : :
1144 : 0 : desc = (struct spdk_nvme_zns_zone_desc *)(report + zd_index);
1145 : :
1146 [ # # ]: 0 : printf("ZSLBA: 0x%016"PRIx64" ZCAP: 0x%016"PRIx64" WP: 0x%016"PRIx64" ZS: ", desc->zslba,
1147 : : desc->zcap, desc->wp);
1148 [ # # # # : 0 : switch (desc->zs) {
# # # # ]
1149 : 0 : case SPDK_NVME_ZONE_STATE_EMPTY:
1150 [ # # ]: 0 : printf("Empty");
1151 : 0 : break;
1152 : 0 : case SPDK_NVME_ZONE_STATE_IOPEN:
1153 [ # # ]: 0 : printf("Implicit open");
1154 : 0 : break;
1155 : 0 : case SPDK_NVME_ZONE_STATE_EOPEN:
1156 [ # # ]: 0 : printf("Explicit open");
1157 : 0 : break;
1158 : 0 : case SPDK_NVME_ZONE_STATE_CLOSED:
1159 [ # # ]: 0 : printf("Closed");
1160 : 0 : break;
1161 : 0 : case SPDK_NVME_ZONE_STATE_RONLY:
1162 [ # # ]: 0 : printf("Read only");
1163 : 0 : break;
1164 : 0 : case SPDK_NVME_ZONE_STATE_FULL:
1165 [ # # ]: 0 : printf("Full");
1166 : 0 : break;
1167 : 0 : case SPDK_NVME_ZONE_STATE_OFFLINE:
1168 [ # # ]: 0 : printf("Offline");
1169 : 0 : break;
1170 : 0 : default:
1171 [ # # ]: 0 : printf("Reserved");
1172 : : }
1173 [ # # # # ]: 0 : printf(" ZT: %s ZA: %x\n", (desc->zt == SPDK_NVME_ZONE_TYPE_SEQWR) ? "SWR" : "Reserved",
1174 [ # # ]: 0 : desc->za.raw);
1175 : :
1176 [ # # ]: 0 : if (!desc->za.bits.zdev) {
1177 : 0 : return;
1178 : : }
1179 : :
1180 [ # # ]: 0 : for (i = 0; i < zdes; i += 8) {
1181 [ # # ]: 0 : printf("zone_desc_ext[%d] : 0x%"PRIx64"\n", i,
1182 : 0 : *(uint64_t *)(report + zd_index + zds + i));
1183 : : }
1184 : : }
1185 : :
1186 : : static void
1187 : 0 : get_and_print_zns_zone_report(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
1188 : : {
1189 : : const struct spdk_nvme_ns_data *nsdata;
1190 : : const struct spdk_nvme_zns_ns_data *nsdata_zns;
1191 : : uint8_t *report_buf;
1192 : : size_t report_bufsize;
1193 : 0 : uint64_t zone_size_lba = spdk_nvme_zns_ns_get_zone_size_sectors(ns);
1194 : 0 : uint64_t total_zones = spdk_nvme_zns_ns_get_num_zones(ns);
1195 : : uint64_t max_zones_per_buf, zones_to_print, i;
1196 : 0 : uint64_t nr_zones = 0;
1197 : 0 : uint64_t handled_zones = 0;
1198 : 0 : uint64_t slba = 0;
1199 : 0 : size_t zdes = 0;
1200 : : uint32_t zds, zrs, format_index;
1201 : 0 : int rc = 0;
1202 : :
1203 : 0 : outstanding_commands = 0;
1204 : :
1205 : 0 : nsdata = spdk_nvme_ns_get_data(ns);
1206 : 0 : nsdata_zns = spdk_nvme_zns_ns_get_data(ns);
1207 : :
1208 : 0 : zrs = sizeof(struct spdk_nvme_zns_zone_report);
1209 : 0 : zds = sizeof(struct spdk_nvme_zns_zone_desc);
1210 : :
1211 : 0 : format_index = spdk_nvme_ns_get_format_index(nsdata);
1212 : 0 : zdes = nsdata_zns->lbafe[format_index].zdes * 64;
1213 [ # # ]: 0 : zones_to_print = g_zone_report_limit ? spdk_min(total_zones, (uint64_t)g_zone_report_limit) : \
1214 : : total_zones;
1215 : :
1216 [ # # ]: 0 : report_bufsize = spdk_min(zrs + zones_to_print * (zds + zdes),
1217 : : spdk_nvme_ns_get_max_io_xfer_size(ns));
1218 : 0 : report_buf = calloc(1, report_bufsize);
1219 [ # # ]: 0 : if (!report_buf) {
1220 [ # # ]: 0 : printf("Zone report allocation failed!\n");
1221 : 0 : exit(1);
1222 : : }
1223 : :
1224 [ # # ]: 0 : print_uline('=', printf("NVMe ZNS Zone Report (first %zu of %zu)\n", zones_to_print, total_zones));
1225 : :
1226 [ # # ]: 0 : while (handled_zones < zones_to_print) {
1227 [ # # ]: 0 : memset(report_buf, 0, report_bufsize);
1228 : :
1229 [ # # ]: 0 : if (zdes) {
1230 [ # # ]: 0 : max_zones_per_buf = (report_bufsize - zrs) / (zds + zdes);
1231 : 0 : rc = spdk_nvme_zns_ext_report_zones(ns, qpair, report_buf, report_bufsize,
1232 : : slba, SPDK_NVME_ZRA_LIST_ALL, true,
1233 : : get_zns_zone_report_completion, NULL);
1234 : : } else {
1235 [ # # ]: 0 : max_zones_per_buf = (report_bufsize - zrs) / zds;
1236 : 0 : rc = spdk_nvme_zns_report_zones(ns, qpair, report_buf, report_bufsize,
1237 : : slba, SPDK_NVME_ZRA_LIST_ALL, true,
1238 : : get_zns_zone_report_completion, NULL);
1239 : : }
1240 : :
1241 [ # # ]: 0 : if (rc) {
1242 [ # # # # ]: 0 : fprintf(stderr, "Report zones failed\n");
1243 : 0 : exit(1);
1244 : : } else {
1245 : 0 : outstanding_commands++;
1246 : : }
1247 : :
1248 [ # # ]: 0 : while (outstanding_commands) {
1249 : 0 : spdk_nvme_qpair_process_completions(qpair, 0);
1250 : : }
1251 : :
1252 : 0 : nr_zones = report_buf[0];
1253 [ # # ]: 0 : if (nr_zones > max_zones_per_buf) {
1254 [ # # # # ]: 0 : fprintf(stderr, "nr_zones too big\n");
1255 : 0 : exit(1);
1256 : : }
1257 : :
1258 [ # # ]: 0 : if (!nr_zones) {
1259 : 0 : break;
1260 : : }
1261 : :
1262 [ # # # # ]: 0 : for (i = 0; i < nr_zones && handled_zones < zones_to_print; i++) {
1263 : 0 : print_zns_zone(report_buf, i, zdes);
1264 : 0 : slba += zone_size_lba;
1265 : 0 : handled_zones++;
1266 : : }
1267 : 0 : printf("\n");
1268 : : }
1269 : :
1270 : 0 : free(report_buf);
1271 : 0 : }
1272 : :
1273 : : static void
1274 : 0 : print_zns_ns_data(const struct spdk_nvme_zns_ns_data *nsdata_zns)
1275 : : {
1276 [ # # ]: 0 : printf("ZNS Specific Namespace Data\n");
1277 [ # # ]: 0 : printf("===========================\n");
1278 [ # # ]: 0 : printf("Variable Zone Capacity: %s\n",
1279 [ # # ]: 0 : nsdata_zns->zoc.variable_zone_capacity ? "Yes" : "No");
1280 [ # # ]: 0 : printf("Zone Active Excursions: %s\n",
1281 [ # # ]: 0 : nsdata_zns->zoc.zone_active_excursions ? "Yes" : "No");
1282 [ # # ]: 0 : printf("Read Across Zone Boundaries: %s\n",
1283 [ # # ]: 0 : nsdata_zns->ozcs.read_across_zone_boundaries ? "Yes" : "No");
1284 [ # # ]: 0 : if (nsdata_zns->mar == 0xffffffff) {
1285 [ # # ]: 0 : printf("Max Active Resources: No Limit\n");
1286 : : } else {
1287 : 0 : printf("Max Active Resources: %"PRIu32"\n",
1288 [ # # ]: 0 : nsdata_zns->mar + 1);
1289 : : }
1290 [ # # ]: 0 : if (nsdata_zns->mor == 0xffffffff) {
1291 [ # # ]: 0 : printf("Max Open Resources: No Limit\n");
1292 : : } else {
1293 : 0 : printf("Max Open Resources: %"PRIu32"\n",
1294 [ # # ]: 0 : nsdata_zns->mor + 1);
1295 : : }
1296 [ # # ]: 0 : if (nsdata_zns->rrl == 0) {
1297 [ # # ]: 0 : printf("Reset Recommended Limit: Not Reported\n");
1298 : : } else {
1299 : 0 : printf("Reset Recommended Limit: %"PRIu32" seconds\n",
1300 [ # # ]: 0 : nsdata_zns->rrl);
1301 : : }
1302 [ # # ]: 0 : if (nsdata_zns->rrl1 == 0) {
1303 [ # # ]: 0 : printf("Reset Recommended Limit 1: Not Reported\n");
1304 : : } else {
1305 : 0 : printf("Reset Recommended Limit 1: %"PRIu32" seconds\n",
1306 [ # # ]: 0 : nsdata_zns->rrl1);
1307 : : }
1308 [ # # ]: 0 : if (nsdata_zns->rrl2 == 0) {
1309 [ # # ]: 0 : printf("Reset Recommended Limit 2: Not Reported\n");
1310 : : } else {
1311 : 0 : printf("Reset Recommended Limit 2: %"PRIu32" seconds\n",
1312 [ # # ]: 0 : nsdata_zns->rrl2);
1313 : : }
1314 [ # # ]: 0 : if (nsdata_zns->rrl3 == 0) {
1315 [ # # ]: 0 : printf("Reset Recommended Limit 3: Not Reported\n");
1316 : : } else {
1317 : 0 : printf("Reset Recommended Limit 3: %"PRIu32" seconds\n",
1318 [ # # ]: 0 : nsdata_zns->rrl3);
1319 : : }
1320 [ # # ]: 0 : if (nsdata_zns->frl == 0) {
1321 [ # # ]: 0 : printf("Finish Recommended Limit: Not Reported\n");
1322 : : } else {
1323 : 0 : printf("Finish Recommended Limit: %"PRIu32" seconds\n",
1324 [ # # ]: 0 : nsdata_zns->frl);
1325 : : }
1326 [ # # ]: 0 : if (nsdata_zns->frl1 == 0) {
1327 [ # # ]: 0 : printf("Finish Recommended Limit 1: Not Reported\n");
1328 : : } else {
1329 : 0 : printf("Finish Recommended Limit 1: %"PRIu32" seconds\n",
1330 [ # # ]: 0 : nsdata_zns->frl1);
1331 : : }
1332 [ # # ]: 0 : if (nsdata_zns->frl2 == 0) {
1333 [ # # ]: 0 : printf("Finish Recommended Limit 2: Not Reported\n");
1334 : : } else {
1335 : 0 : printf("Finish Recommended Limit 2: %"PRIu32" seconds\n",
1336 [ # # ]: 0 : nsdata_zns->frl2);
1337 : : }
1338 [ # # ]: 0 : if (nsdata_zns->frl3 == 0) {
1339 [ # # ]: 0 : printf("Finish Recommended Limit 3: Not Reported\n");
1340 : : } else {
1341 : 0 : printf("Finish Recommended Limit 3: %"PRIu32" seconds\n",
1342 [ # # ]: 0 : nsdata_zns->frl3);
1343 : : }
1344 : 0 : printf("\n");
1345 : 0 : }
1346 : :
1347 : : static const char *
1348 : 408 : pi_format_string(uint32_t pif)
1349 : : {
1350 [ + - - - : 408 : switch (pif) {
- ]
1351 : 408 : case 0:
1352 : 408 : return "16b Guard PI";
1353 : 0 : case 1:
1354 : 0 : return "32b Guard PI";
1355 : 0 : case 2:
1356 : 0 : return "64b Guard PI";
1357 : 0 : case 3:
1358 : 0 : return "Reserved";
1359 : 0 : default:
1360 : 0 : return "Unknown";
1361 : : }
1362 : : }
1363 : :
1364 : : static void
1365 : 51 : print_nvm_ns_data(const struct spdk_nvme_nvm_ns_data *nsdata_nvm,
1366 : : const struct spdk_nvme_ns_data *nsdata)
1367 : : {
1368 : : uint32_t i;
1369 : :
1370 [ - + ]: 51 : printf("NVM Specific Namespace Data\n");
1371 [ - + ]: 51 : printf("===========================\n");
1372 [ - + ]: 51 : printf("Logical Block Storage Tag Mask: %"PRIx64"\n", nsdata_nvm->lbstm);
1373 [ - + ]: 51 : printf("Protection Information Capabilities:\n");
1374 [ - + ]: 51 : printf(" 16b Guard Protection Information Storage Tag Support: %s\n",
1375 [ - + ]: 51 : nsdata_nvm->pic._16bpists != 0 ? "Yes" : "No");
1376 [ - + ]: 51 : printf(" 16b Guard Protection Information Storage Tag Mask: %s\n",
1377 [ - + ]: 51 : nsdata_nvm->pic._16bpistm != 0 ? "LBSTM must be all 1s" : "Any bit in LBSTM can be 0");
1378 [ - + ]: 51 : printf(" Storage Tag Check Read Support: %s\n",
1379 [ - + ]: 51 : nsdata_nvm->pic.stcrs != 0 ? "Yes" : "No");
1380 : :
1381 [ + + ]: 459 : for (i = 0; i <= nsdata->nlbaf; i++) {
1382 : 512 : printf("Extended LBA Format #%02d: Storage Tag Size: %-2d, Protection Information Format: %s\n",
1383 [ - + ]: 408 : i, nsdata_nvm->elbaf[i].sts, pi_format_string(nsdata_nvm->elbaf[i].pif));
1384 : : }
1385 : 51 : }
1386 : :
1387 : : static const char *
1388 : 72 : csi_name(enum spdk_nvme_csi csi)
1389 : : {
1390 [ + - - - ]: 72 : switch (csi) {
1391 : 72 : case SPDK_NVME_CSI_NVM:
1392 : 72 : return "NVM";
1393 : 0 : case SPDK_NVME_CSI_KV:
1394 : 0 : return "KV";
1395 : 0 : case SPDK_NVME_CSI_ZNS:
1396 : 0 : return "ZNS";
1397 : 0 : default:
1398 [ # # # # ]: 0 : if (csi >= 0x30 && csi <= 0x3f) {
1399 : 0 : return "Vendor specific";
1400 : : }
1401 : 0 : return "Unknown";
1402 : : }
1403 : : }
1404 : :
1405 : : static void
1406 : 72 : print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
1407 : : {
1408 : : const struct spdk_nvme_ctrlr_data *cdata;
1409 : : const struct spdk_nvme_ns_data *nsdata;
1410 : : const struct spdk_nvme_zns_ns_data *nsdata_zns;
1411 : : const struct spdk_nvme_nvm_ns_data *nsdata_nvm;
1412 : : const struct spdk_uuid *uuid;
1413 : : uint32_t i;
1414 : : uint32_t flags;
1415 : 36 : char uuid_str[SPDK_UUID_STRING_LEN];
1416 : : uint32_t blocksize, format_index;
1417 : : enum spdk_nvme_dealloc_logical_block_read_value dlfeat_read_value;
1418 : :
1419 : 72 : cdata = spdk_nvme_ctrlr_get_data(ctrlr);
1420 : 72 : nsdata = spdk_nvme_ns_get_data(ns);
1421 : 72 : nsdata_zns = spdk_nvme_zns_ns_get_data(ns);
1422 : 72 : nsdata_nvm = spdk_nvme_nvm_ns_get_data(ns);
1423 : 72 : flags = spdk_nvme_ns_get_flags(ns);
1424 : :
1425 [ - + ]: 72 : printf("Namespace ID:%d\n", spdk_nvme_ns_get_id(ns));
1426 : :
1427 [ - + - + ]: 72 : if (g_hex_dump) {
1428 : 0 : hex_dump(nsdata, sizeof(*nsdata));
1429 : 0 : printf("\n");
1430 : : }
1431 : :
1432 : : /* This function is only called for active namespaces. */
1433 [ - + ]: 72 : assert(spdk_nvme_ns_is_active(ns));
1434 : :
1435 [ + + + + ]: 72 : if (features[SPDK_NVME_FEAT_ERROR_RECOVERY].valid) {
1436 : 68 : unsigned tler = features[SPDK_NVME_FEAT_ERROR_RECOVERY].result & 0xFFFF;
1437 [ - + ]: 68 : printf("Error Recovery Timeout: ");
1438 [ + - ]: 68 : if (tler == 0) {
1439 [ - + ]: 68 : printf("Unlimited\n");
1440 : : } else {
1441 [ # # ]: 0 : printf("%u milliseconds\n", tler * 100);
1442 : : }
1443 : : }
1444 : :
1445 [ - + ]: 72 : printf("Command Set Identifier: %s (%02Xh)\n",
1446 : 72 : csi_name(spdk_nvme_ns_get_csi(ns)), spdk_nvme_ns_get_csi(ns));
1447 [ - + ]: 72 : printf("Deallocate: %s\n",
1448 [ + - ]: 72 : (flags & SPDK_NVME_NS_DEALLOCATE_SUPPORTED) ? "Supported" : "Not Supported");
1449 [ - + ]: 72 : printf("Deallocated/Unwritten Error: %s\n",
1450 [ + + ]: 72 : nsdata->nsfeat.dealloc_or_unwritten_error ? "Supported" : "Not Supported");
1451 : 72 : dlfeat_read_value = spdk_nvme_ns_get_dealloc_logical_block_read_value(ns);
1452 [ + + - + ]: 87 : printf("Deallocated Read Value: %s\n",
1453 : : dlfeat_read_value == SPDK_NVME_DEALLOC_READ_00 ? "All 0x00" :
1454 [ - + ]: 15 : dlfeat_read_value == SPDK_NVME_DEALLOC_READ_FF ? "All 0xFF" :
1455 : : "Unknown");
1456 [ - + ]: 72 : printf("Deallocate in Write Zeroes: %s\n",
1457 [ - + ]: 72 : nsdata->dlfeat.bits.write_zero_deallocate ? "Supported" : "Not Supported");
1458 [ - + ]: 72 : printf("Deallocated Guard Field: %s\n",
1459 [ - + ]: 72 : nsdata->dlfeat.bits.guard_value ? "CRC for Read Value" : "0xFFFF");
1460 [ - + ]: 72 : printf("Flush: %s\n",
1461 [ + + ]: 72 : (flags & SPDK_NVME_NS_FLUSH_SUPPORTED) ? "Supported" : "Not Supported");
1462 [ - + ]: 72 : printf("Reservation: %s\n",
1463 [ + + ]: 72 : (flags & SPDK_NVME_NS_RESERVATION_SUPPORTED) ? "Supported" : "Not Supported");
1464 [ - + ]: 72 : if (flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) {
1465 [ # # ]: 0 : printf("End-to-End Data Protection: Supported\n");
1466 [ # # ]: 0 : printf("Protection Type: Type%d\n", nsdata->dps.pit);
1467 [ # # ]: 0 : printf("Protection Information Transferred as: %s\n",
1468 [ # # ]: 0 : nsdata->dps.md_start ? "First 8/16 Bytes" : "Last 8/16 Bytes");
1469 : : }
1470 : 72 : format_index = spdk_nvme_ns_get_format_index(nsdata);
1471 [ + + ]: 72 : if (nsdata->lbaf[format_index].ms > 0) {
1472 [ - + ]: 4 : printf("Metadata Transferred as: %s\n",
1473 [ - + ]: 4 : nsdata->flbas.extended ? "Extended Data LBA" : "Separate Metadata Buffer");
1474 : : }
1475 [ - + ]: 72 : printf("Namespace Sharing Capabilities: %s\n",
1476 [ + + ]: 72 : nsdata->nmic.can_share ? "Multiple Controllers" : "Private");
1477 [ - + ]: 72 : blocksize = 1 << nsdata->lbaf[format_index].lbads;
1478 : 72 : printf("Size (in LBAs): %lld (%lldGiB)\n",
1479 [ - + ]: 72 : (long long)nsdata->nsze,
1480 : 72 : (long long)nsdata->nsze * blocksize / 1024 / 1024 / 1024);
1481 : 72 : printf("Capacity (in LBAs): %lld (%lldGiB)\n",
1482 [ - + ]: 72 : (long long)nsdata->ncap,
1483 : 72 : (long long)nsdata->ncap * blocksize / 1024 / 1024 / 1024);
1484 : 72 : printf("Utilization (in LBAs): %lld (%lldGiB)\n",
1485 [ - + ]: 72 : (long long)nsdata->nuse,
1486 : 72 : (long long)nsdata->nuse * blocksize / 1024 / 1024 / 1024);
1487 [ + + ]: 72 : if (nsdata->noiob) {
1488 [ - + ]: 2 : printf("Optimal I/O Boundary: %u blocks\n", nsdata->noiob);
1489 : : }
1490 [ + + ]: 72 : if (!spdk_mem_all_zero(nsdata->nguid, sizeof(nsdata->nguid))) {
1491 [ - + ]: 16 : printf("NGUID: ");
1492 : 16 : print_hex_be(nsdata->nguid, sizeof(nsdata->nguid));
1493 : 16 : printf("\n");
1494 : : }
1495 [ + + ]: 72 : if (!spdk_mem_all_zero(&nsdata->eui64, sizeof(nsdata->eui64))) {
1496 [ - + ]: 11 : printf("EUI64: ");
1497 : 11 : print_hex_be(&nsdata->eui64, sizeof(nsdata->eui64));
1498 : 11 : printf("\n");
1499 : : }
1500 : 72 : uuid = spdk_nvme_ns_get_uuid(ns);
1501 [ + + ]: 72 : if (uuid) {
1502 : 14 : spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), uuid);
1503 [ - + ]: 14 : printf("UUID: %s\n", uuid_str);
1504 : : }
1505 [ - + ]: 72 : printf("Thin Provisioning: %s\n",
1506 [ - + ]: 72 : nsdata->nsfeat.thin_prov ? "Supported" : "Not Supported");
1507 [ - + ]: 72 : printf("Per-NS Atomic Units: %s\n",
1508 [ + + ]: 72 : nsdata->nsfeat.ns_atomic_write_unit ? "Yes" : "No");
1509 [ + + ]: 72 : if (nsdata->nsfeat.ns_atomic_write_unit) {
1510 [ - + ]: 14 : if (nsdata->nawun) {
1511 [ # # ]: 0 : printf(" Atomic Write Unit (Normal): %d\n", nsdata->nawun + 1);
1512 : : }
1513 : :
1514 [ - + ]: 14 : if (nsdata->nawupf) {
1515 [ # # ]: 0 : printf(" Atomic Write Unit (PFail): %d\n", nsdata->nawupf + 1);
1516 : : }
1517 : :
1518 [ - + ]: 14 : if (nsdata->npwg) {
1519 [ # # ]: 0 : printf(" Preferred Write Granularity: %d\n", nsdata->npwg + 1);
1520 : : }
1521 : :
1522 [ - + ]: 14 : if (nsdata->nacwu) {
1523 [ # # ]: 0 : printf(" Atomic Compare & Write Unit: %d\n", nsdata->nacwu + 1);
1524 : : }
1525 : :
1526 [ - + ]: 14 : printf(" Atomic Boundary Size (Normal): %d\n", nsdata->nabsn);
1527 [ - + ]: 14 : printf(" Atomic Boundary Size (PFail): %d\n", nsdata->nabspf);
1528 [ - + ]: 14 : printf(" Atomic Boundary Offset: %d\n", nsdata->nabo);
1529 : : }
1530 : :
1531 [ + + ]: 72 : if (cdata->oncs.copy) {
1532 [ - + ]: 61 : printf("Maximum Single Source Range Length: %d\n", nsdata->mssrl);
1533 [ - + ]: 61 : printf("Maximum Copy Length: %d\n", nsdata->mcl);
1534 [ - + ]: 61 : printf("Maximum Source Range Count: %d\n", nsdata->msrc + 1);
1535 : : }
1536 : :
1537 [ - + ]: 72 : printf("NGUID/EUI64 Never Reused: %s\n",
1538 [ - + ]: 72 : nsdata->nsfeat.guid_never_reused ? "Yes" : "No");
1539 : :
1540 [ + + ]: 72 : if (cdata->cmic.ana_reporting) {
1541 [ - + ]: 4 : printf("ANA group ID: %u\n", nsdata->anagrpid);
1542 : : }
1543 : :
1544 [ - + ]: 72 : printf("Namespace Write Protected: %s\n",
1545 [ - + ]: 72 : nsdata->nsattr.write_protected ? "Yes" : "No");
1546 : :
1547 [ - + ]: 72 : if (cdata->ctratt.bits.nvm_sets) {
1548 [ # # ]: 0 : printf("NVM set ID: %u\n", nsdata->nvmsetid);
1549 : : }
1550 : :
1551 [ + + ]: 72 : if (cdata->ctratt.bits.endurance_groups) {
1552 [ - + ]: 4 : printf("Endurance group ID: %u\n", nsdata->endgid);
1553 : : }
1554 : :
1555 [ - + ]: 72 : printf("Number of LBA Formats: %d\n", nsdata->nlbaf + 1);
1556 [ - + ]: 72 : printf("Current LBA Format: LBA Format #%02d\n",
1557 : : format_index);
1558 [ + + ]: 513 : for (i = 0; i <= nsdata->nlbaf; i++) {
1559 : 561 : printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d\n",
1560 [ - + - + ]: 441 : i, 1 << nsdata->lbaf[i].lbads, nsdata->lbaf[i].ms);
1561 [ - + ]: 441 : if (spdk_nvme_ns_get_csi(ns) == SPDK_NVME_CSI_ZNS) {
1562 : 0 : printf("LBA Format Extension #%02d: Zone Size (in LBAs): 0x%"PRIx64" Zone Descriptor Extension Size: %d bytes\n",
1563 [ # # # # ]: 0 : i, nsdata_zns->lbafe[i].zsze, nsdata_zns->lbafe[i].zdes << 6);
1564 : : }
1565 : :
1566 : : }
1567 : 72 : printf("\n");
1568 : :
1569 [ + + ]: 72 : if (cdata->ctratt.bits.fdps) {
1570 : : union spdk_nvme_feat_fdp_cdw12 fdp_res;
1571 : :
1572 [ - + + - ]: 4 : if (features[SPDK_NVME_FEAT_FDP].valid) {
1573 : 4 : fdp_res.raw = features[SPDK_NVME_FEAT_FDP].result;
1574 : :
1575 [ - + ]: 4 : printf("Get Feature FDP:\n");
1576 [ - + ]: 4 : printf("================\n");
1577 [ - + ]: 4 : printf(" Enabled: %s\n",
1578 [ + - ]: 4 : fdp_res.bits.fdpe ? "Yes" : "No");
1579 [ - + ]: 4 : printf(" FDP configuration index: %u\n\n", fdp_res.bits.fdpci);
1580 : :
1581 [ + - + - ]: 4 : if (fdp_res.bits.fdpe && !get_fdp_cfg_log_page(ns)) {
1582 : 4 : print_fdp_cfg_log_page();
1583 : : }
1584 [ + - + - ]: 4 : if (fdp_res.bits.fdpe && !get_fdp_ruhu_log_page(ns)) {
1585 : 4 : print_fdp_ruhu_log_page();
1586 : : }
1587 [ + - + - ]: 4 : if (fdp_res.bits.fdpe && !get_fdp_stats_log_page(ns)) {
1588 : 4 : print_fdp_stats_log_page();
1589 : : }
1590 [ + - + - ]: 4 : if (fdp_res.bits.fdpe && !get_fdp_events_log_page(ns)) {
1591 : 4 : print_fdp_events_log_page();
1592 : : }
1593 : : }
1594 : : }
1595 : :
1596 [ - + ]: 72 : if (spdk_nvme_ctrlr_is_ocssd_supported(ctrlr)) {
1597 : 0 : get_ocssd_geometry(ns, &geometry_data);
1598 : 0 : print_ocssd_geometry(&geometry_data);
1599 : 0 : get_ocssd_chunk_info_log_page(ns);
1600 [ # # # # ]: 0 : if (g_ocssd_verbose) {
1601 : 0 : print_ocssd_chunk_info_verbose(g_ocssd_chunk_info_page);
1602 : : } else {
1603 : 0 : print_ocssd_chunk_info(g_ocssd_chunk_info_page, NUM_CHUNK_INFO_ENTRIES);
1604 : : }
1605 [ - + ]: 72 : } else if (spdk_nvme_ns_get_csi(ns) == SPDK_NVME_CSI_ZNS) {
1606 : 0 : struct spdk_nvme_qpair *qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
1607 [ # # ]: 0 : if (qpair == NULL) {
1608 [ # # ]: 0 : printf("ERROR: spdk_nvme_ctrlr_alloc_io_qpair() failed\n");
1609 : 0 : exit(1);
1610 : : }
1611 : 0 : print_zns_ns_data(nsdata_zns);
1612 : 0 : get_and_print_zns_zone_report(ns, qpair);
1613 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
1614 [ + + ]: 72 : } else if (nsdata_nvm != NULL) {
1615 : 51 : print_nvm_ns_data(nsdata_nvm, nsdata);
1616 : : }
1617 : 72 : }
1618 : :
1619 : : static const char *
1620 : 919 : admin_opc_name(uint8_t opc)
1621 : : {
1622 [ + + + + : 919 : switch (opc) {
+ + + + +
+ + + + -
+ + + + +
- - + + -
- - + ]
1623 : 50 : case SPDK_NVME_OPC_DELETE_IO_SQ:
1624 : 50 : return "Delete I/O Submission Queue";
1625 : 50 : case SPDK_NVME_OPC_CREATE_IO_SQ:
1626 : 50 : return "Create I/O Submission Queue";
1627 : 64 : case SPDK_NVME_OPC_GET_LOG_PAGE:
1628 : 64 : return "Get Log Page";
1629 : 50 : case SPDK_NVME_OPC_DELETE_IO_CQ:
1630 : 50 : return "Delete I/O Completion Queue";
1631 : 50 : case SPDK_NVME_OPC_CREATE_IO_CQ:
1632 : 50 : return "Create I/O Completion Queue";
1633 : 64 : case SPDK_NVME_OPC_IDENTIFY:
1634 : 64 : return "Identify";
1635 : 64 : case SPDK_NVME_OPC_ABORT:
1636 : 64 : return "Abort";
1637 : 64 : case SPDK_NVME_OPC_SET_FEATURES:
1638 : 64 : return "Set Features";
1639 : 64 : case SPDK_NVME_OPC_GET_FEATURES:
1640 : 64 : return "Get Features";
1641 : 64 : case SPDK_NVME_OPC_ASYNC_EVENT_REQUEST:
1642 : 64 : return "Asynchronous Event Request";
1643 : 6 : case SPDK_NVME_OPC_NS_MANAGEMENT:
1644 : 6 : return "Namespace Management";
1645 : 7 : case SPDK_NVME_OPC_FIRMWARE_COMMIT:
1646 : 7 : return "Firmware Commit";
1647 : 7 : case SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD:
1648 : 7 : return "Firmware Image Download";
1649 : 0 : case SPDK_NVME_OPC_DEVICE_SELF_TEST:
1650 : 0 : return "Device Self-test";
1651 : 49 : case SPDK_NVME_OPC_NS_ATTACHMENT:
1652 : 49 : return "Namespace Attachment";
1653 : 14 : case SPDK_NVME_OPC_KEEP_ALIVE:
1654 : 14 : return "Keep Alive";
1655 : 43 : case SPDK_NVME_OPC_DIRECTIVE_SEND:
1656 : 43 : return "Directive Send";
1657 : 43 : case SPDK_NVME_OPC_DIRECTIVE_RECEIVE:
1658 : 43 : return "Directive Receive";
1659 : 43 : case SPDK_NVME_OPC_VIRTUALIZATION_MANAGEMENT:
1660 : 43 : return "Virtualization Management";
1661 : 0 : case SPDK_NVME_OPC_NVME_MI_SEND:
1662 : 0 : return "NVMe-MI Send";
1663 : 0 : case SPDK_NVME_OPC_NVME_MI_RECEIVE:
1664 : 0 : return "NVMe-MI Receive";
1665 : 43 : case SPDK_NVME_OPC_DOORBELL_BUFFER_CONFIG:
1666 : 43 : return "Doorbell Buffer Config";
1667 : 50 : case SPDK_NVME_OPC_FORMAT_NVM:
1668 : 50 : return "Format NVM";
1669 : 0 : case SPDK_NVME_OPC_SECURITY_SEND:
1670 : 0 : return "Security Send";
1671 : 0 : case SPDK_NVME_OPC_SECURITY_RECEIVE:
1672 : 0 : return "Security Receive";
1673 : 0 : case SPDK_NVME_OPC_SANITIZE:
1674 : 0 : return "Sanitize";
1675 : 30 : default:
1676 [ + - ]: 30 : if (opc >= 0xC0) {
1677 : 30 : return "Vendor specific";
1678 : : }
1679 : 0 : return "Unknown";
1680 : : }
1681 : : }
1682 : :
1683 : : static const char *
1684 : 556 : io_opc_name(uint8_t opc)
1685 : : {
1686 [ + + + + : 556 : switch (opc) {
+ + + - -
- - + + ]
1687 : 64 : case SPDK_NVME_OPC_FLUSH:
1688 : 64 : return "Flush";
1689 : 64 : case SPDK_NVME_OPC_WRITE:
1690 : 64 : return "Write";
1691 : 64 : case SPDK_NVME_OPC_READ:
1692 : 64 : return "Read";
1693 : 7 : case SPDK_NVME_OPC_WRITE_UNCORRECTABLE:
1694 : 7 : return "Write Uncorrectable";
1695 : 54 : case SPDK_NVME_OPC_COMPARE:
1696 : 54 : return "Compare";
1697 : 57 : case SPDK_NVME_OPC_WRITE_ZEROES:
1698 : 57 : return "Write Zeroes";
1699 : 64 : case SPDK_NVME_OPC_DATASET_MANAGEMENT:
1700 : 64 : return "Dataset Management";
1701 : 0 : case SPDK_NVME_OPC_RESERVATION_REGISTER:
1702 : 0 : return "Reservation Register";
1703 : 0 : case SPDK_NVME_OPC_RESERVATION_REPORT:
1704 : 0 : return "Reservation Report";
1705 : 0 : case SPDK_NVME_OPC_RESERVATION_ACQUIRE:
1706 : 0 : return "Reservation Acquire";
1707 : 0 : case SPDK_NVME_OPC_RESERVATION_RELEASE:
1708 : 0 : return "Reservation Release";
1709 : 53 : case SPDK_NVME_OPC_COPY:
1710 : 53 : return "Copy";
1711 : 129 : default:
1712 [ - + ]: 129 : if (opc >= 0x80) {
1713 : 0 : return "Vendor specific";
1714 : : }
1715 : 129 : return "Unknown";
1716 : : }
1717 : : }
1718 : :
1719 : : static void
1720 : 72 : print_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport_id *trid,
1721 : : const struct spdk_nvme_ctrlr_opts *opts)
1722 : : {
1723 : : const struct spdk_nvme_ctrlr_data *cdata;
1724 : : union spdk_nvme_cap_register cap;
1725 : : union spdk_nvme_vs_register vs;
1726 : 28 : uint8_t str[512];
1727 : : uint32_t i, j;
1728 : : struct spdk_nvme_error_information_entry *error_entry;
1729 : 28 : struct spdk_pci_addr pci_addr;
1730 : : struct spdk_pci_device *pci_dev;
1731 : : struct spdk_pci_id pci_id;
1732 : : uint32_t nsid;
1733 : : uint8_t *orig_desc;
1734 : : struct spdk_nvme_ana_group_descriptor *copied_desc;
1735 : : uint32_t desc_size, copy_len;
1736 : :
1737 : :
1738 : 72 : cap = spdk_nvme_ctrlr_get_regs_cap(ctrlr);
1739 : 72 : vs = spdk_nvme_ctrlr_get_regs_vs(ctrlr);
1740 : :
1741 [ + + ]: 72 : if (!spdk_nvme_ctrlr_is_discovery(ctrlr)) {
1742 : : /*
1743 : : * Discovery Controller only supports the
1744 : : * IDENTIFY and GET_LOG_PAGE cmd set, so only
1745 : : * attempt GET_FEATURES when NOT targeting a
1746 : : * Discovery Controller.
1747 : : */
1748 : 64 : get_ctrlr_features(ctrlr);
1749 : : }
1750 : 72 : get_log_pages(ctrlr);
1751 : :
1752 : 72 : cdata = spdk_nvme_ctrlr_get_data(ctrlr);
1753 : :
1754 [ - + ]: 72 : printf("=====================================================\n");
1755 [ + + ]: 72 : if (trid->trtype != SPDK_NVME_TRANSPORT_PCIE) {
1756 : 22 : printf("NVMe over Fabrics controller at %s:%s: %s\n",
1757 [ - + ]: 22 : trid->traddr, trid->trsvcid, trid->subnqn);
1758 : : } else {
1759 [ - + ]: 50 : if (spdk_pci_addr_parse(&pci_addr, trid->traddr) != 0) {
1760 : 0 : return;
1761 : : }
1762 : :
1763 : 50 : pci_dev = spdk_nvme_ctrlr_get_pci_device(ctrlr);
1764 [ - + ]: 50 : if (!pci_dev) {
1765 : 0 : return;
1766 : : }
1767 : :
1768 : 50 : pci_id = spdk_pci_device_get_id(pci_dev);
1769 : :
1770 : 50 : printf("NVMe Controller at %04x:%02x:%02x.%x [%04x:%04x]\n",
1771 : 50 : pci_addr.domain, pci_addr.bus,
1772 : 50 : pci_addr.dev, pci_addr.func,
1773 [ - + ]: 50 : pci_id.vendor_id, pci_id.device_id);
1774 : : }
1775 [ - + ]: 72 : printf("=====================================================\n");
1776 : :
1777 [ - + - + ]: 72 : if (g_hex_dump) {
1778 : 0 : hex_dump(cdata, sizeof(*cdata));
1779 : 0 : printf("\n");
1780 : : }
1781 : :
1782 [ - + ]: 72 : printf("Controller Capabilities/Features\n");
1783 [ - + ]: 72 : printf("================================\n");
1784 [ - + ]: 72 : printf("Vendor ID: %04x\n", cdata->vid);
1785 [ - + ]: 72 : printf("Subsystem Vendor ID: %04x\n", cdata->ssvid);
1786 [ - + ]: 72 : printf("Serial Number: ");
1787 : 72 : print_ascii_string(cdata->sn, sizeof(cdata->sn));
1788 : 72 : printf("\n");
1789 [ - + ]: 72 : printf("Model Number: ");
1790 : 72 : print_ascii_string(cdata->mn, sizeof(cdata->mn));
1791 : 72 : printf("\n");
1792 [ - + ]: 72 : printf("Firmware Version: ");
1793 : 72 : print_ascii_string(cdata->fr, sizeof(cdata->fr));
1794 : 72 : printf("\n");
1795 [ - + ]: 72 : printf("Recommended Arb Burst: %d\n", cdata->rab);
1796 : 72 : printf("IEEE OUI Identifier: %02x %02x %02x\n",
1797 [ - + ]: 72 : cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]);
1798 [ - + ]: 72 : printf("Multi-path I/O\n");
1799 [ + + - + ]: 72 : printf(" May have multiple subsystem ports: %s\n", cdata->cmic.multi_port ? "Yes" : "No");
1800 [ + + - + ]: 72 : printf(" May have multiple controllers: %s\n", cdata->cmic.multi_ctrlr ? "Yes" : "No");
1801 [ - + - + ]: 72 : printf(" Associated with SR-IOV VF: %s\n", cdata->cmic.sr_iov ? "Yes" : "No");
1802 [ - + ]: 72 : printf("Max Data Transfer Size: ");
1803 [ + + ]: 72 : if (cdata->mdts == 0) {
1804 [ - + ]: 7 : printf("Unlimited\n");
1805 : : } else {
1806 [ - + - + ]: 65 : printf("%" PRIu64 "\n", (uint64_t)1 << (12 + cap.bits.mpsmin + cdata->mdts));
1807 : : }
1808 [ - + ]: 72 : printf("Max Number of Namespaces: %d\n", cdata->nn);
1809 [ - + ]: 72 : printf("Max Number of I/O Queues: %d\n", opts->num_io_queues);
1810 [ - + ]: 72 : printf("NVMe Specification Version (VS): %u.%u", vs.bits.mjr, vs.bits.mnr);
1811 [ - + ]: 72 : if (vs.bits.ter) {
1812 [ # # ]: 0 : printf(".%u", vs.bits.ter);
1813 : : }
1814 : 72 : printf("\n");
1815 [ + + ]: 72 : if (cdata->ver.raw != 0) {
1816 [ - + ]: 71 : printf("NVMe Specification Version (Identify): %u.%u", cdata->ver.bits.mjr, cdata->ver.bits.mnr);
1817 [ - + ]: 71 : if (cdata->ver.bits.ter) {
1818 [ # # ]: 0 : printf(".%u", cdata->ver.bits.ter);
1819 : : }
1820 : 71 : printf("\n");
1821 : : }
1822 : :
1823 [ - + ]: 72 : printf("Maximum Queue Entries: %u\n", cap.bits.mqes + 1);
1824 [ + + - + ]: 72 : printf("Contiguous Queues Required: %s\n", cap.bits.cqr ? "Yes" : "No");
1825 [ - + ]: 72 : printf("Arbitration Mechanisms Supported\n");
1826 [ - + ]: 72 : printf(" Weighted Round Robin: %s\n",
1827 [ + + ]: 72 : cap.bits.ams & SPDK_NVME_CAP_AMS_WRR ? "Supported" : "Not Supported");
1828 [ - + ]: 72 : printf(" Vendor Specific: %s\n",
1829 [ - + ]: 72 : cap.bits.ams & SPDK_NVME_CAP_AMS_VS ? "Supported" : "Not Supported");
1830 [ - + ]: 72 : printf("Reset Timeout: %" PRIu64 " ms\n", (uint64_t)500 * cap.bits.to);
1831 : 72 : printf("Doorbell Stride: %" PRIu64 " bytes\n",
1832 [ - + - + ]: 72 : (uint64_t)1 << (2 + cap.bits.dstrd));
1833 [ - + ]: 72 : printf("NVM Subsystem Reset: %s\n",
1834 [ - + ]: 72 : cap.bits.nssrs ? "Supported" : "Not Supported");
1835 [ - + ]: 72 : printf("Command Sets Supported\n");
1836 [ - + ]: 72 : printf(" NVM Command Set: %s\n",
1837 [ + - ]: 72 : cap.bits.css & SPDK_NVME_CAP_CSS_NVM ? "Supported" : "Not Supported");
1838 [ - + ]: 72 : printf("Boot Partition: %s\n",
1839 [ - + ]: 72 : cap.bits.bps ? "Supported" : "Not Supported");
1840 : 72 : printf("Memory Page Size Minimum: %" PRIu64 " bytes\n",
1841 [ - + - + ]: 72 : (uint64_t)1 << (12 + cap.bits.mpsmin));
1842 : 72 : printf("Memory Page Size Maximum: %" PRIu64 " bytes\n",
1843 [ - + - + ]: 72 : (uint64_t)1 << (12 + cap.bits.mpsmax));
1844 [ - + ]: 72 : printf("Persistent Memory Region: %s\n",
1845 [ + + ]: 72 : cap.bits.pmrs ? "Supported" : "Not Supported");
1846 : :
1847 [ - + ]: 72 : printf("Optional Asynchronous Events Supported\n");
1848 [ - + ]: 72 : printf(" Namespace Attribute Notices: %s\n",
1849 [ + + ]: 72 : cdata->oaes.ns_attribute_notices ? "Supported" : "Not Supported");
1850 [ - + ]: 72 : printf(" Firmware Activation Notices: %s\n",
1851 [ + + ]: 72 : cdata->oaes.fw_activation_notices ? "Supported" : "Not Supported");
1852 [ - + ]: 72 : printf(" ANA Change Notices: %s\n",
1853 [ + + ]: 72 : cdata->oaes.ana_change_notices ? "Supported" : "Not Supported");
1854 [ - + ]: 72 : printf(" PLE Aggregate Log Change Notices: %s\n",
1855 [ - + ]: 72 : cdata->oaes.pleal_change_notices ? "Supported" : "Not Supported");
1856 [ - + ]: 72 : printf(" LBA Status Info Alert Notices: %s\n",
1857 [ - + ]: 72 : cdata->oaes.lba_sia_notices ? "Supported" : "Not Supported");
1858 [ - + ]: 72 : printf(" EGE Aggregate Log Change Notices: %s\n",
1859 [ - + ]: 72 : cdata->oaes.egealp_change_notices ? "Supported" : "Not Supported");
1860 [ - + ]: 72 : printf(" Normal NVM Subsystem Shutdown event: %s\n",
1861 [ - + ]: 72 : cdata->oaes.nnvm_sse ? "Supported" : "Not Supported");
1862 [ - + ]: 72 : printf(" Zone Descriptor Change Notices: %s\n",
1863 [ - + ]: 72 : cdata->oaes.zdes_change_notices ? "Supported" : "Not Supported");
1864 [ - + ]: 72 : printf(" Discovery Log Change Notices: %s\n",
1865 [ + + ]: 72 : cdata->oaes.discovery_log_change_notices ? "Supported" : "Not Supported");
1866 : :
1867 [ - + ]: 72 : printf("Controller Attributes\n");
1868 [ - + ]: 72 : printf(" 128-bit Host Identifier: %s\n",
1869 [ + + ]: 72 : cdata->ctratt.bits.host_id_exhid_supported ? "Supported" : "Not Supported");
1870 [ - + ]: 72 : printf(" Non-Operational Permissive Mode: %s\n",
1871 [ - + ]: 72 : cdata->ctratt.bits.non_operational_power_state_permissive_mode ? "Supported" : "Not Supported");
1872 [ - + ]: 72 : printf(" NVM Sets: %s\n",
1873 [ - + ]: 72 : cdata->ctratt.bits.nvm_sets ? "Supported" : "Not Supported");
1874 [ - + ]: 72 : printf(" Read Recovery Levels: %s\n",
1875 [ - + ]: 72 : cdata->ctratt.bits.read_recovery_levels ? "Supported" : "Not Supported");
1876 [ - + ]: 72 : printf(" Endurance Groups: %s\n",
1877 [ + + ]: 72 : cdata->ctratt.bits.endurance_groups ? "Supported" : "Not Supported");
1878 [ - + ]: 72 : printf(" Predictable Latency Mode: %s\n",
1879 [ - + ]: 72 : cdata->ctratt.bits.predictable_latency_mode ? "Supported" : "Not Supported");
1880 [ - + ]: 72 : printf(" Traffic Based Keep ALive: %s\n",
1881 [ + + ]: 72 : cdata->ctratt.bits.tbkas ? "Supported" : "Not Supported");
1882 [ - + ]: 72 : printf(" Namespace Granularity: %s\n",
1883 [ - + ]: 72 : cdata->ctratt.bits.namespace_granularity ? "Supported" : "Not Supported");
1884 [ - + ]: 72 : printf(" SQ Associations: %s\n",
1885 [ - + ]: 72 : cdata->ctratt.bits.sq_associations ? "Supported" : "Not Supported");
1886 [ - + ]: 72 : printf(" UUID List: %s\n",
1887 [ - + ]: 72 : cdata->ctratt.bits.uuid_list ? "Supported" : "Not Supported");
1888 [ - + ]: 72 : printf(" Multi-Domain Subsystem: %s\n",
1889 [ - + ]: 72 : cdata->ctratt.bits.mds ? "Supported" : "Not Supported");
1890 [ - + ]: 72 : printf(" Fixed Capacity Management: %s\n",
1891 [ - + ]: 72 : cdata->ctratt.bits.fixed_capacity_management ? "Supported" : "Not Supported");
1892 [ - + ]: 72 : printf(" Variable Capacity Management: %s\n",
1893 [ - + ]: 72 : cdata->ctratt.bits.variable_capacity_management ? "Supported" : "Not Supported");
1894 [ - + ]: 72 : printf(" Delete Endurance Group: %s\n",
1895 [ - + ]: 72 : cdata->ctratt.bits.delete_endurance_group ? "Supported" : "Not Supported");
1896 [ - + ]: 72 : printf(" Delete NVM Set: %s\n",
1897 [ - + ]: 72 : cdata->ctratt.bits.delete_nvm_set ? "Supported" : "Not Supported");
1898 [ - + ]: 72 : printf(" Extended LBA Formats Supported: %s\n",
1899 [ + + ]: 72 : cdata->ctratt.bits.elbas ? "Supported" : "Not Supported");
1900 [ - + ]: 72 : printf(" Flexible Data Placement Supported: %s\n",
1901 [ + + ]: 72 : cdata->ctratt.bits.fdps ? "Supported" : "Not Supported");
1902 : 72 : printf("\n");
1903 : :
1904 [ - + ]: 72 : printf("Controller Memory Buffer Support\n");
1905 [ - + ]: 72 : printf("================================\n");
1906 [ + + ]: 72 : if (cap.bits.cmbs != 0) {
1907 : : union spdk_nvme_cmbsz_register cmbsz;
1908 : : uint64_t size;
1909 : :
1910 : 8 : cmbsz = spdk_nvme_ctrlr_get_regs_cmbsz(ctrlr);
1911 : 8 : size = cmbsz.bits.sz;
1912 : :
1913 : : /* Convert the size to bytes by multiplying by the granularity.
1914 : : By spec, szu is at most 6 and sz is 20 bits, so size requires
1915 : : at most 56 bits. */
1916 [ # # ]: 8 : size *= (0x1000 << (cmbsz.bits.szu * 4));
1917 : :
1918 [ # # ]: 8 : printf("Supported: Yes\n");
1919 [ # # ]: 8 : printf("Total Size: %" PRIu64 " bytes\n", size);
1920 [ # # ]: 8 : printf("Submission Queues in CMB: %s\n",
1921 [ + - ]: 8 : cmbsz.bits.sqs ? "Supported" : "Not Supported");
1922 [ # # ]: 8 : printf("Completion Queues in CMB: %s\n",
1923 [ - + ]: 8 : cmbsz.bits.cqs ? "Supported" : "Not Supported");
1924 [ # # ]: 8 : printf("Read data and metadata in CMB %s\n",
1925 [ + - ]: 8 : cmbsz.bits.rds ? "Supported" : "Not Supported");
1926 [ # # ]: 8 : printf("Write data and metadata in CMB: %s\n",
1927 [ + - ]: 8 : cmbsz.bits.wds ? "Supported" : "Not Supported");
1928 : : } else {
1929 [ - + ]: 64 : printf("Supported: No\n");
1930 : : }
1931 : 72 : printf("\n");
1932 : :
1933 [ - + ]: 72 : printf("Persistent Memory Region Support\n");
1934 [ - + ]: 72 : printf("================================\n");
1935 [ + + ]: 72 : if (cap.bits.pmrs != 0) {
1936 : : union spdk_nvme_pmrcap_register pmrcap;
1937 : : uint64_t pmrsz;
1938 : :
1939 : 8 : pmrcap = spdk_nvme_ctrlr_get_regs_pmrcap(ctrlr);
1940 : 8 : pmrsz = spdk_nvme_ctrlr_get_pmrsz(ctrlr);
1941 : :
1942 [ # # ]: 8 : printf("Supported: Yes\n");
1943 [ # # ]: 8 : printf("Total Size: %" PRIu64 " bytes\n", pmrsz);
1944 [ # # ]: 8 : printf("Read data and metadata in PMR %s\n",
1945 [ + - ]: 8 : pmrcap.bits.rds ? "Supported" : "Not Supported");
1946 [ # # ]: 8 : printf("Write data and metadata in PMR: %s\n",
1947 [ + - ]: 8 : pmrcap.bits.wds ? "Supported" : "Not Supported");
1948 : : } else {
1949 [ - + ]: 64 : printf("Supported: No\n");
1950 : : }
1951 : 72 : printf("\n");
1952 : :
1953 [ - + ]: 72 : printf("Admin Command Set Attributes\n");
1954 [ - + ]: 72 : printf("============================\n");
1955 [ - + ]: 72 : printf("Security Send/Receive: %s\n",
1956 [ + + ]: 72 : cdata->oacs.security ? "Supported" : "Not Supported");
1957 [ - + ]: 72 : printf("Format NVM: %s\n",
1958 [ + + ]: 72 : cdata->oacs.format ? "Supported" : "Not Supported");
1959 [ - + ]: 72 : printf("Firmware Activate/Download: %s\n",
1960 [ + + ]: 72 : cdata->oacs.firmware ? "Supported" : "Not Supported");
1961 [ - + ]: 72 : printf("Namespace Management: %s\n",
1962 [ + + ]: 72 : cdata->oacs.ns_manage ? "Supported" : "Not Supported");
1963 [ - + ]: 72 : printf("Device Self-Test: %s\n",
1964 [ - + ]: 72 : cdata->oacs.device_self_test ? "Supported" : "Not Supported");
1965 [ - + ]: 72 : printf("Directives: %s\n",
1966 [ + + ]: 72 : cdata->oacs.directives ? "Supported" : "Not Supported");
1967 [ - + ]: 72 : printf("NVMe-MI: %s\n",
1968 [ - + ]: 72 : cdata->oacs.nvme_mi ? "Supported" : "Not Supported");
1969 [ - + ]: 72 : printf("Virtualization Management: %s\n",
1970 [ - + ]: 72 : cdata->oacs.virtualization_management ? "Supported" : "Not Supported");
1971 [ - + ]: 72 : printf("Doorbell Buffer Config: %s\n",
1972 [ + + ]: 72 : cdata->oacs.doorbell_buffer_config ? "Supported" : "Not Supported");
1973 [ - + ]: 72 : printf("Get LBA Status Capability: %s\n",
1974 [ - + ]: 72 : cdata->oacs.get_lba_status ? "Supported" : "Not Supported");
1975 [ - + ]: 72 : printf("Command & Feature Lockdown Capability: %s\n",
1976 [ - + ]: 72 : cdata->oacs.command_feature_lockdown ? "Supported" : "Not Supported");
1977 [ - + ]: 72 : printf("Abort Command Limit: %d\n", cdata->acl + 1);
1978 [ - + ]: 72 : printf("Async Event Request Limit: %d\n", cdata->aerl + 1);
1979 [ - + ]: 72 : printf("Number of Firmware Slots: ");
1980 [ + + ]: 72 : if (cdata->oacs.firmware != 0) {
1981 [ - + ]: 7 : printf("%d\n", cdata->frmw.num_slots);
1982 : : } else {
1983 [ - + ]: 65 : printf("N/A\n");
1984 : : }
1985 [ - + ]: 72 : printf("Firmware Slot 1 Read-Only: ");
1986 [ + + ]: 72 : if (cdata->oacs.firmware != 0) {
1987 [ - + - + ]: 7 : printf("%s\n", cdata->frmw.slot1_ro ? "Yes" : "No");
1988 : : } else {
1989 [ - + ]: 65 : printf("N/A\n");
1990 : : }
1991 [ - + ]: 72 : printf("Firmware Activation Without Reset: ");
1992 [ + + ]: 72 : if (cdata->oacs.firmware != 0) {
1993 [ + + - + ]: 7 : printf("%s\n", cdata->frmw.activation_without_reset ? "Yes" : "No");
1994 : : } else {
1995 [ - + ]: 65 : printf("N/A\n");
1996 : : }
1997 [ - + ]: 72 : printf("Multiple Update Detection Support: ");
1998 [ + + ]: 72 : if (cdata->oacs.firmware != 0) {
1999 [ - + - + ]: 7 : printf("%s\n", cdata->frmw.multiple_update_detection ? "Yes" : "No");
2000 : : } else {
2001 [ - + ]: 65 : printf("N/A\n");
2002 : : }
2003 [ + - ]: 72 : if (cdata->fwug == 0x00) {
2004 [ - + ]: 72 : printf("Firmware Update Granularity: No Information Provided\n");
2005 [ # # ]: 0 : } else if (cdata->fwug == 0xFF) {
2006 [ # # ]: 0 : printf("Firmware Update Granularity: No Restriction\n");
2007 : : } else {
2008 : 0 : printf("Firmware Update Granularity: %u KiB\n",
2009 [ # # ]: 0 : cdata->fwug * 4);
2010 : : }
2011 [ - + ]: 72 : printf("Per-Namespace SMART Log: %s\n",
2012 [ + + ]: 72 : cdata->lpa.ns_smart ? "Yes" : "No");
2013 [ + + ]: 72 : if (cdata->cmic.ana_reporting == 0) {
2014 [ - + ]: 68 : printf("Asymmetric Namespace Access Log Page: Not Supported\n");
2015 : : } else {
2016 [ - + ]: 4 : printf("Asymmetric Namespace Access Log Page: Supported\n");
2017 [ - + ]: 4 : printf("ANA Transition Time : %u sec\n", cdata->anatt);
2018 : 4 : printf("\n");
2019 [ - + ]: 4 : printf("Asymmetric Namespace Access Capabilities\n");
2020 [ - + ]: 4 : printf(" ANA Optimized State : %s\n",
2021 [ + - ]: 4 : cdata->anacap.ana_optimized_state ? "Supported" : "Not Supported");
2022 [ - + ]: 4 : printf(" ANA Non-Optimized State : %s\n",
2023 [ + - ]: 4 : cdata->anacap.ana_non_optimized_state ? "Supported" : "Not Supported");
2024 [ - + ]: 4 : printf(" ANA Inaccessible State : %s\n",
2025 [ + - ]: 4 : cdata->anacap.ana_inaccessible_state ? "Supported" : "Not Supported");
2026 [ - + ]: 4 : printf(" ANA Persistent Loss State : %s\n",
2027 [ + - ]: 4 : cdata->anacap.ana_persistent_loss_state ? "Supported" : "Not Supported");
2028 [ - + ]: 4 : printf(" ANA Change State : %s\n",
2029 [ + - ]: 4 : cdata->anacap.ana_change_state ? "Supported" : "Not Supported");
2030 [ - + ]: 4 : printf(" ANAGRPID is not changed : %s\n",
2031 [ - + ]: 4 : cdata->anacap.no_change_anagrpid ? "Yes" : "No");
2032 [ - + ]: 4 : printf(" Non-Zero ANAGRPID for NS Mgmt Cmd : %s\n",
2033 [ - + ]: 4 : cdata->anacap.non_zero_anagrpid ? "Supported" : "Not Supported");
2034 : 4 : printf("\n");
2035 [ - + ]: 4 : printf("ANA Group Identifier Maximum : %u\n", cdata->anagrpmax);
2036 [ - + ]: 4 : printf("Number of ANA Group Identifiers : %u\n", cdata->nanagrpid);
2037 [ - + ]: 4 : printf("Max Number of Allowed Namespaces : %u\n", cdata->mnan);
2038 : : }
2039 [ - + ]: 72 : printf("Subsystem NQN: %s\n", cdata->subnqn);
2040 [ - + ]: 72 : printf("Command Effects Log Page: %s\n",
2041 [ + + ]: 72 : cdata->lpa.celp ? "Supported" : "Not Supported");
2042 [ - + ]: 72 : printf("Get Log Page Extended Data: %s\n",
2043 [ + + ]: 72 : cdata->lpa.edlp ? "Supported" : "Not Supported");
2044 [ - + ]: 72 : printf("Telemetry Log Pages: %s\n",
2045 [ + + ]: 72 : cdata->lpa.telemetry ? "Supported" : "Not Supported");
2046 [ - + ]: 72 : printf("Persistent Event Log Pages: %s\n",
2047 [ - + ]: 72 : cdata->lpa.pelp ? "Supported" : "Not Supported");
2048 [ - + ]: 72 : printf("Supported Log Pages Log Page: %s\n",
2049 [ - + ]: 72 : cdata->lpa.lplp ? "Supported" : "May Support");
2050 [ - + ]: 72 : printf("Commands Supported & Effects Log Page: %s\n",
2051 [ - + ]: 72 : cdata->lpa.lplp ? "Supported" : "Not Supported");
2052 [ - + ]: 72 : printf("Feature Identifiers & Effects Log Page:%s\n",
2053 [ - + ]: 72 : cdata->lpa.lplp ? "Supported" : "May Support");
2054 [ - + ]: 72 : printf("NVMe-MI Commands & Effects Log Page: %s\n",
2055 [ - + ]: 72 : cdata->lpa.lplp ? "Supported" : "May Support");
2056 [ - + ]: 72 : printf("Data Area 4 for Telemetry Log: %s\n",
2057 [ - + ]: 72 : cdata->lpa.da4_telemetry ? "Supported" : "Not Supported");
2058 [ - + ]: 72 : printf("Error Log Page Entries Supported: %d\n", cdata->elpe + 1);
2059 [ + + ]: 72 : if (cdata->kas == 0) {
2060 [ - + ]: 58 : printf("Keep Alive: Not Supported\n");
2061 : : } else {
2062 [ - + ]: 14 : printf("Keep Alive: Supported\n");
2063 : 14 : printf("Keep Alive Granularity: %u ms\n",
2064 [ - + ]: 14 : cdata->kas * 100);
2065 : : }
2066 : 72 : printf("\n");
2067 : :
2068 [ - + ]: 72 : printf("NVM Command Set Attributes\n");
2069 [ - + ]: 72 : printf("==========================\n");
2070 [ - + ]: 72 : printf("Submission Queue Entry Size\n");
2071 [ - + - + ]: 72 : printf(" Max: %d\n", 1 << cdata->sqes.max);
2072 [ - + - + ]: 72 : printf(" Min: %d\n", 1 << cdata->sqes.min);
2073 [ - + ]: 72 : printf("Completion Queue Entry Size\n");
2074 [ - + - + ]: 72 : printf(" Max: %d\n", 1 << cdata->cqes.max);
2075 [ - + - + ]: 72 : printf(" Min: %d\n", 1 << cdata->cqes.min);
2076 [ - + ]: 72 : printf("Number of Namespaces: %d\n", cdata->nn);
2077 [ - + ]: 72 : printf("Compare Command: %s\n",
2078 [ + + ]: 72 : cdata->oncs.compare ? "Supported" : "Not Supported");
2079 [ - + ]: 72 : printf("Write Uncorrectable Command: %s\n",
2080 [ + + ]: 72 : cdata->oncs.write_unc ? "Supported" : "Not Supported");
2081 [ - + ]: 72 : printf("Dataset Management Command: %s\n",
2082 [ + + ]: 72 : cdata->oncs.dsm ? "Supported" : "Not Supported");
2083 [ - + ]: 72 : printf("Write Zeroes Command: %s\n",
2084 [ + + ]: 72 : cdata->oncs.write_zeroes ? "Supported" : "Not Supported");
2085 [ - + ]: 72 : printf("Set Features Save Field: %s\n",
2086 [ + + ]: 72 : cdata->oncs.set_features_save ? "Supported" : "Not Supported");
2087 [ - + ]: 72 : printf("Reservations: %s\n",
2088 [ + + ]: 72 : cdata->oncs.reservations ? "Supported" : "Not Supported");
2089 [ - + ]: 72 : printf("Timestamp: %s\n",
2090 [ + + ]: 72 : cdata->oncs.timestamp ? "Supported" : "Not Supported");
2091 [ - + ]: 72 : printf("Copy: %s\n",
2092 [ + + ]: 72 : cdata->oncs.copy ? "Supported" : "Not Supported");
2093 [ - + ]: 72 : printf("Volatile Write Cache: %s\n",
2094 [ + + ]: 72 : cdata->vwc.present ? "Present" : "Not Present");
2095 [ - + ]: 72 : printf("Atomic Write Unit (Normal): %d\n", cdata->awun + 1);
2096 [ - + ]: 72 : printf("Atomic Write Unit (PFail): %d\n", cdata->awupf + 1);
2097 [ - + ]: 72 : printf("Atomic Compare & Write Unit: %d\n", cdata->acwu + 1);
2098 [ - + ]: 72 : printf("Fused Compare & Write: %s\n",
2099 [ + + ]: 72 : cdata->fuses.compare_and_write ? "Supported" : "Not Supported");
2100 [ - + ]: 72 : printf("Scatter-Gather List\n");
2101 [ - + ]: 72 : printf(" SGL Command Set: %s\n",
2102 [ + + ]: 72 : cdata->sgls.supported == SPDK_NVME_SGLS_SUPPORTED ? "Supported" :
2103 [ + + ]: 9 : cdata->sgls.supported == SPDK_NVME_SGLS_SUPPORTED_DWORD_ALIGNED ? "Supported (Dword aligned)" :
2104 : : "Not Supported");
2105 [ - + ]: 72 : printf(" SGL Keyed: %s\n",
2106 [ + + ]: 72 : cdata->sgls.keyed_sgl ? "Supported" : "Not Supported");
2107 [ - + ]: 72 : printf(" SGL Bit Bucket Descriptor: %s\n",
2108 [ - + ]: 72 : cdata->sgls.bit_bucket_descriptor ? "Supported" : "Not Supported");
2109 [ - + ]: 72 : printf(" SGL Metadata Pointer: %s\n",
2110 [ - + ]: 72 : cdata->sgls.metadata_pointer ? "Supported" : "Not Supported");
2111 [ - + ]: 72 : printf(" Oversized SGL: %s\n",
2112 [ - + ]: 72 : cdata->sgls.oversized_sgl ? "Supported" : "Not Supported");
2113 [ - + ]: 72 : printf(" SGL Metadata Address: %s\n",
2114 [ - + ]: 72 : cdata->sgls.metadata_address ? "Supported" : "Not Supported");
2115 [ - + ]: 72 : printf(" SGL Offset: %s\n",
2116 [ + + ]: 72 : cdata->sgls.sgl_offset ? "Supported" : "Not Supported");
2117 [ - + ]: 72 : printf(" Transport SGL Data Block: %s\n",
2118 [ - + ]: 72 : cdata->sgls.transport_sgl ? "Supported" : "Not Supported");
2119 [ - + ]: 72 : printf("Replay Protected Memory Block:");
2120 [ - + ]: 72 : if (cdata->rpmbs.num_rpmb_units > 0) {
2121 [ # # ]: 0 : printf(" Supported\n");
2122 [ # # ]: 0 : printf(" Number of RPMB Units: %d\n", cdata->rpmbs.num_rpmb_units);
2123 [ # # # # ]: 0 : printf(" Authentication Method: %s\n", cdata->rpmbs.auth_method == 0 ? "HMAC SHA-256" : "Unknown");
2124 [ # # ]: 0 : printf(" Total Size (in 128KB units) = %d\n", cdata->rpmbs.total_size + 1);
2125 [ # # ]: 0 : printf(" Access Size (in 512B units) = %d\n", cdata->rpmbs.access_size + 1);
2126 : : } else {
2127 [ - + ]: 72 : printf(" Not Supported\n");
2128 : : }
2129 [ - + ]: 72 : if (cdata->crdt[0]) {
2130 [ # # ]: 0 : printf("Command Retry Delay Time 1: %u milliseconds\n", cdata->crdt[0] * 100);
2131 : : }
2132 [ - + ]: 72 : if (cdata->crdt[1]) {
2133 [ # # ]: 0 : printf("Command Retry Delay Time 2: %u milliseconds\n", cdata->crdt[1] * 100);
2134 : : }
2135 [ - + ]: 72 : if (cdata->crdt[2]) {
2136 [ # # ]: 0 : printf("Command Retry Delay Time 3: %u milliseconds\n", cdata->crdt[2] * 100);
2137 : : }
2138 : 72 : printf("\n");
2139 : :
2140 [ - + ]: 72 : printf("Firmware Slot Information\n");
2141 [ - + ]: 72 : printf("=========================\n");
2142 [ - + - + ]: 72 : if (g_hex_dump) {
2143 : 0 : hex_dump(&firmware_page, sizeof(firmware_page));
2144 : 0 : printf("\n");
2145 : : }
2146 [ - + ]: 72 : printf("Active slot: %u\n", firmware_page.afi.active_slot);
2147 [ - + ]: 72 : if (firmware_page.afi.next_reset_slot) {
2148 [ # # ]: 0 : printf("Next controller reset slot: %u\n", firmware_page.afi.next_reset_slot);
2149 : : }
2150 [ + + ]: 576 : for (i = 0; i < 7; i++) {
2151 [ + + ]: 504 : if (!spdk_mem_all_zero(firmware_page.revision[i], sizeof(firmware_page.revision[i]))) {
2152 [ - + ]: 60 : printf("Slot %u Firmware Revision: ", i + 1);
2153 : 60 : print_ascii_string(firmware_page.revision[i], sizeof(firmware_page.revision[i]));
2154 : 60 : printf("\n");
2155 : : }
2156 : : }
2157 : 72 : printf("\n");
2158 : :
2159 [ + + ]: 72 : if (g_ana_log_page) {
2160 [ - + ]: 4 : printf("Asymmetric Namespace Access\n");
2161 [ - + ]: 4 : printf("===========================\n");
2162 [ - + - + ]: 4 : if (g_hex_dump) {
2163 : 0 : hex_dump(g_ana_log_page, g_ana_log_page_size);
2164 : 0 : printf("\n");
2165 : : }
2166 : :
2167 [ - + ]: 4 : printf("Change Count : %" PRIx64 "\n", g_ana_log_page->change_count);
2168 [ - + ]: 4 : printf("Number of ANA Group Descriptors : %u\n", g_ana_log_page->num_ana_group_desc);
2169 : :
2170 : 4 : copied_desc = g_copied_ana_desc;
2171 : 4 : orig_desc = (uint8_t *)g_ana_log_page + sizeof(struct spdk_nvme_ana_page);
2172 : 4 : copy_len = g_ana_log_page_size - sizeof(struct spdk_nvme_ana_page);
2173 : :
2174 [ + + ]: 8 : for (i = 0; i < g_ana_log_page->num_ana_group_desc; i++) {
2175 [ - + - + ]: 4 : memcpy(copied_desc, orig_desc, copy_len);
2176 : :
2177 [ - + ]: 4 : printf("ANA Group Descriptor : %u\n", i);
2178 [ - + ]: 4 : printf(" ANA Group ID : %u\n", copied_desc->ana_group_id);
2179 [ - + ]: 4 : printf(" Number of NSID Values : %u\n", copied_desc->num_of_nsid);
2180 [ - + ]: 4 : printf(" Change Count : %" PRIx64 "\n", copied_desc->change_count);
2181 [ - + ]: 4 : printf(" ANA State : %u\n", copied_desc->ana_state);
2182 [ + + ]: 8 : for (j = 0; j < copied_desc->num_of_nsid; j++) {
2183 [ - + ]: 4 : printf(" Namespace Identifier : %u\n", copied_desc->nsid[j]);
2184 : : }
2185 : :
2186 : 4 : desc_size = sizeof(struct spdk_nvme_ana_group_descriptor) +
2187 : 4 : copied_desc->num_of_nsid * sizeof(uint32_t);
2188 : 4 : orig_desc += desc_size;
2189 : 4 : copy_len -= desc_size;
2190 : : }
2191 : 4 : free(g_ana_log_page);
2192 : 4 : free(g_copied_ana_desc);
2193 : : }
2194 : :
2195 : 72 : printf("\n");
2196 : :
2197 [ + + ]: 72 : if (cdata->lpa.celp) {
2198 [ - + ]: 64 : printf("Commands Supported and Effects\n");
2199 [ - + ]: 64 : printf("==============================\n");
2200 : :
2201 [ - + - + ]: 64 : if (g_hex_dump) {
2202 : 0 : hex_dump(&cmd_effects_log_page, sizeof(cmd_effects_log_page));
2203 : 0 : printf("\n");
2204 : : }
2205 : :
2206 [ - + ]: 64 : printf("Admin Commands\n");
2207 [ - + ]: 64 : printf("--------------\n");
2208 [ + + ]: 16448 : for (i = 0; i < SPDK_COUNTOF(cmd_effects_log_page.admin_cmds_supported); i++) {
2209 : 16384 : struct spdk_nvme_cmds_and_effect_entry *cmd = &cmd_effects_log_page.admin_cmds_supported[i];
2210 [ + + ]: 16384 : if (cmd->csupp) {
2211 [ - + ]: 4595 : printf("%30s (%02Xh): Supported %s%s%s%s%s\n",
2212 : : admin_opc_name(i), i,
2213 [ + + ]: 919 : cmd->lbcc ? "LBA-Change " : "",
2214 [ + + ]: 919 : cmd->ncc ? "NS-Cap-Change " : "",
2215 [ + + ]: 919 : cmd->nic ? "NS-Inventory-Change " : "",
2216 [ + + ]: 919 : cmd->ccc ? "Ctrlr-Cap-Change " : "",
2217 [ + + + + : 919 : cmd->cse == 0 ? "" : cmd->cse == 1 ? "Per-NS-Exclusive" : cmd->cse == 2 ? "All-NS-Exclusive" : "");
+ - ]
2218 : : }
2219 : : }
2220 : :
2221 [ - + ]: 64 : printf("I/O Commands\n");
2222 [ - + ]: 64 : printf("------------\n");
2223 [ + + ]: 16448 : for (i = 0; i < SPDK_COUNTOF(cmd_effects_log_page.io_cmds_supported); i++) {
2224 : 16384 : struct spdk_nvme_cmds_and_effect_entry *cmd = &cmd_effects_log_page.io_cmds_supported[i];
2225 [ + + ]: 16384 : if (cmd->csupp) {
2226 [ - + ]: 2780 : printf("%30s (%02Xh): Supported %s%s%s%s%s\n",
2227 : : io_opc_name(i), i,
2228 [ + + ]: 556 : cmd->lbcc ? "LBA-Change " : "",
2229 [ - + ]: 556 : cmd->ncc ? "NS-Cap-Change " : "",
2230 [ - + ]: 556 : cmd->nic ? "NS-Inventory-Change " : "",
2231 [ - + ]: 556 : cmd->ccc ? "Ctrlr-Cap-Change " : "",
2232 [ - + - - : 556 : cmd->cse == 0 ? "" : cmd->cse == 1 ? "Per-NS-Exclusive" : cmd->cse == 2 ? "All-NS-Exclusive" : "");
- - ]
2233 : : }
2234 : : }
2235 : 64 : printf("\n");
2236 : : }
2237 : :
2238 [ - + ]: 72 : printf("Error Log\n");
2239 [ - + ]: 72 : printf("=========\n");
2240 [ + + ]: 2871 : for (i = 0; i <= cdata->elpe; i++) {
2241 : 2799 : error_entry = &error_page[i];
2242 [ + + ]: 2799 : if (error_entry->error_count == 0) {
2243 : 2467 : continue;
2244 : : }
2245 [ + + ]: 332 : if (i != 0) {
2246 [ - + ]: 322 : printf("-----------\n");
2247 : : }
2248 : :
2249 [ - + ]: 332 : printf("Entry: %u\n", i);
2250 [ - + ]: 332 : printf("Error Count: 0x%"PRIx64"\n", error_entry->error_count);
2251 [ - + ]: 332 : printf("Submission Queue Id: 0x%x\n", error_entry->sqid);
2252 [ - + ]: 332 : printf("Command Id: 0x%x\n", error_entry->cid);
2253 [ - + ]: 332 : printf("Phase Bit: %x\n", error_entry->status.p);
2254 [ - + ]: 332 : printf("Status Code: 0x%x\n", error_entry->status.sc);
2255 [ - + ]: 332 : printf("Status Code Type: 0x%x\n", error_entry->status.sct);
2256 [ - + ]: 332 : printf("Do Not Retry: %x\n", error_entry->status.dnr);
2257 [ - + ]: 332 : printf("Error Location: 0x%x\n", error_entry->error_location);
2258 [ - + ]: 332 : printf("LBA: 0x%"PRIx64"\n", error_entry->lba);
2259 [ - + ]: 332 : printf("Namespace: 0x%x\n", error_entry->nsid);
2260 [ - + ]: 332 : printf("Vendor Log Page: 0x%x\n", error_entry->vendor_specific);
2261 : :
2262 : : }
2263 : 72 : printf("\n");
2264 : :
2265 [ + + + + ]: 72 : if (features[SPDK_NVME_FEAT_ARBITRATION].valid) {
2266 : 60 : uint32_t arb = features[SPDK_NVME_FEAT_ARBITRATION].result;
2267 : : unsigned ab, lpw, mpw, hpw;
2268 : :
2269 : 60 : ab = arb & 0x7;
2270 : 60 : lpw = ((arb >> 8) & 0xFF) + 1;
2271 : 60 : mpw = ((arb >> 16) & 0xFF) + 1;
2272 : 60 : hpw = ((arb >> 24) & 0xFF) + 1;
2273 : :
2274 [ - + ]: 60 : printf("Arbitration\n");
2275 [ - + ]: 60 : printf("===========\n");
2276 [ - + ]: 60 : printf("Arbitration Burst: ");
2277 [ + + ]: 60 : if (ab == 0x7) {
2278 [ - + ]: 43 : printf("no limit\n");
2279 : : } else {
2280 [ - + - + ]: 17 : printf("%u\n", 1u << ab);
2281 : : }
2282 : :
2283 [ + + ]: 60 : if (cap.bits.ams & SPDK_NVME_CAP_AMS_WRR) {
2284 [ - + ]: 6 : printf("Low Priority Weight: %u\n", lpw);
2285 [ - + ]: 6 : printf("Medium Priority Weight: %u\n", mpw);
2286 [ - + ]: 6 : printf("High Priority Weight: %u\n", hpw);
2287 : : }
2288 : 60 : printf("\n");
2289 : : }
2290 : :
2291 [ + + + + ]: 72 : if (features[SPDK_NVME_FEAT_POWER_MANAGEMENT].valid) {
2292 : 60 : unsigned ps = features[SPDK_NVME_FEAT_POWER_MANAGEMENT].result & 0x1F;
2293 [ - + ]: 60 : printf("Power Management\n");
2294 [ - + ]: 60 : printf("================\n");
2295 [ - + ]: 60 : printf("Number of Power States: %u\n", cdata->npss + 1);
2296 [ - + ]: 60 : printf("Current Power State: Power State #%u\n", ps);
2297 [ + + ]: 120 : for (i = 0; i <= cdata->npss; i++) {
2298 : 60 : const struct spdk_nvme_power_state psd = cdata->psd[i];
2299 [ - + ]: 60 : printf("Power State #%u:\n", i);
2300 [ - + ]: 60 : if (psd.mps) {
2301 : : /* MP scale is 0.0001 W */
2302 : 0 : printf(" Max Power: %u.%04u W\n",
2303 : 0 : psd.mp / 10000,
2304 [ # # ]: 0 : psd.mp % 10000);
2305 : : } else {
2306 : : /* MP scale is 0.01 W */
2307 : 60 : printf(" Max Power: %3u.%02u W\n",
2308 : 60 : psd.mp / 100,
2309 [ - + ]: 60 : psd.mp % 100);
2310 : : }
2311 [ - + ]: 60 : printf(" Non-Operational State: %s\n",
2312 [ - + ]: 60 : psd.nops ? "Non-Operation" : "Operational");
2313 [ - + ]: 60 : printf(" Entry Latency: ");
2314 [ + + ]: 60 : if (psd.enlat) {
2315 [ - + ]: 43 : printf("%u microseconds\n", psd.enlat);
2316 : : } else {
2317 [ - + ]: 17 : printf("Not Reported\n");
2318 : : }
2319 [ - + ]: 60 : printf(" Exit Latency: ");
2320 [ + + ]: 60 : if (psd.exlat) {
2321 [ - + ]: 43 : printf("%u microseconds\n", psd.exlat);
2322 : : } else {
2323 [ - + ]: 17 : printf("Not Reported\n");
2324 : : }
2325 [ - + ]: 60 : printf(" Relative Read Throughput: %u\n", psd.rrt);
2326 [ - + ]: 60 : printf(" Relative Read Latency: %u\n", psd.rrl);
2327 [ - + ]: 60 : printf(" Relative Write Throughput: %u\n", psd.rwt);
2328 [ - + ]: 60 : printf(" Relative Write Latency: %u\n", psd.rwl);
2329 [ - + ]: 60 : printf(" Idle Power: ");
2330 [ - - + ]: 60 : switch (psd.ips) {
2331 : 0 : case 1:
2332 : : /* Idle Power scale is 0.0001 W */
2333 [ # # ]: 0 : printf("%u.%04u W\n", psd.idlp / 10000, psd.idlp % 10000);
2334 : 0 : break;
2335 : 0 : case 2:
2336 : : /* Idle Power scale is 0.01 W */
2337 [ # # ]: 0 : printf("%u.%02u W\n", psd.idlp / 100, psd.idlp % 100);
2338 : 0 : break;
2339 : 60 : default:
2340 [ - + ]: 60 : printf(" Not Reported\n");
2341 : : }
2342 [ - + ]: 60 : printf(" Active Power: ");
2343 [ - - + ]: 60 : switch (psd.aps) {
2344 : 0 : case 1:
2345 : : /* Active Power scale is 0.0001 W */
2346 [ # # ]: 0 : printf("%u.%04u W\n", psd.actp / 10000, psd.actp % 10000);
2347 : 0 : break;
2348 : 0 : case 2:
2349 : : /* Active Power scale is 0.01 W */
2350 [ # # ]: 0 : printf("%u.%02u W\n", psd.actp / 100, psd.actp % 100);
2351 : 0 : break;
2352 : 60 : default:
2353 [ - + ]: 60 : printf(" Not Reported\n");
2354 : : }
2355 : : }
2356 [ - + ]: 60 : printf("Non-Operational Permissive Mode: %s\n",
2357 [ - + ]: 60 : cdata->ctratt.bits.non_operational_power_state_permissive_mode ? "Supported" : "Not Supported");
2358 : 60 : printf("\n");
2359 : : }
2360 : :
2361 [ + + + + ]: 72 : if (features[SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD].valid) {
2362 [ - + ]: 60 : printf("Health Information\n");
2363 [ - + ]: 60 : printf("==================\n");
2364 : :
2365 [ - + - + ]: 60 : if (g_hex_dump) {
2366 : 0 : hex_dump(&health_page, sizeof(health_page));
2367 : 0 : printf("\n");
2368 : : }
2369 : :
2370 [ - + ]: 60 : printf("Critical Warnings:\n");
2371 [ - + ]: 60 : printf(" Available Spare Space: %s\n",
2372 [ - + ]: 60 : health_page.critical_warning.bits.available_spare ? "WARNING" : "OK");
2373 [ - + ]: 60 : printf(" Temperature: %s\n",
2374 [ - + ]: 60 : health_page.critical_warning.bits.temperature ? "WARNING" : "OK");
2375 [ - + ]: 60 : printf(" Device Reliability: %s\n",
2376 [ - + ]: 60 : health_page.critical_warning.bits.device_reliability ? "WARNING" : "OK");
2377 [ - + ]: 60 : printf(" Read Only: %s\n",
2378 [ - + ]: 60 : health_page.critical_warning.bits.read_only ? "Yes" : "No");
2379 [ - + ]: 60 : printf(" Volatile Memory Backup: %s\n",
2380 [ - + ]: 60 : health_page.critical_warning.bits.volatile_memory_backup ? "WARNING" : "OK");
2381 : 60 : printf("Current Temperature: %u Kelvin (%d Celsius)\n",
2382 : 60 : health_page.temperature,
2383 [ - + ]: 60 : (int)health_page.temperature - 273);
2384 : 60 : printf("Temperature Threshold: %u Kelvin (%d Celsius)\n",
2385 : : features[SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD].result,
2386 [ - + ]: 60 : (int)features[SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD].result - 273);
2387 [ - + ]: 60 : printf("Available Spare: %u%%\n", health_page.available_spare);
2388 [ - + ]: 60 : printf("Available Spare Threshold: %u%%\n", health_page.available_spare_threshold);
2389 [ - + ]: 60 : printf("Life Percentage Used: %u%%\n", health_page.percentage_used);
2390 [ - + ]: 60 : printf("Data Units Read: ");
2391 : 60 : print_uint128_dec(health_page.data_units_read);
2392 : 60 : printf("\n");
2393 [ - + ]: 60 : printf("Data Units Written: ");
2394 : 60 : print_uint128_dec(health_page.data_units_written);
2395 : 60 : printf("\n");
2396 [ - + ]: 60 : printf("Host Read Commands: ");
2397 : 60 : print_uint128_dec(health_page.host_read_commands);
2398 : 60 : printf("\n");
2399 [ - + ]: 60 : printf("Host Write Commands: ");
2400 : 60 : print_uint128_dec(health_page.host_write_commands);
2401 : 60 : printf("\n");
2402 [ - + ]: 60 : printf("Controller Busy Time: ");
2403 : 60 : print_uint128_dec(health_page.controller_busy_time);
2404 [ - + ]: 60 : printf(" minutes\n");
2405 [ - + ]: 60 : printf("Power Cycles: ");
2406 : 60 : print_uint128_dec(health_page.power_cycles);
2407 : 60 : printf("\n");
2408 [ - + ]: 60 : printf("Power On Hours: ");
2409 : 60 : print_uint128_dec(health_page.power_on_hours);
2410 [ - + ]: 60 : printf(" hours\n");
2411 [ - + ]: 60 : printf("Unsafe Shutdowns: ");
2412 : 60 : print_uint128_dec(health_page.unsafe_shutdowns);
2413 : 60 : printf("\n");
2414 [ - + ]: 60 : printf("Unrecoverable Media Errors: ");
2415 : 60 : print_uint128_dec(health_page.media_errors);
2416 : 60 : printf("\n");
2417 [ - + ]: 60 : printf("Lifetime Error Log Entries: ");
2418 : 60 : print_uint128_dec(health_page.num_error_info_log_entries);
2419 : 60 : printf("\n");
2420 [ - + ]: 60 : printf("Warning Temperature Time: %u minutes\n", health_page.warning_temp_time);
2421 [ - + ]: 60 : printf("Critical Temperature Time: %u minutes\n", health_page.critical_temp_time);
2422 [ + + ]: 540 : for (i = 0; i < 8; i++) {
2423 [ - + ]: 480 : if (health_page.temp_sensor[i] != 0) {
2424 : 0 : printf("Temperature Sensor %d: %u Kelvin (%d Celsius)\n",
2425 [ # # ]: 0 : i + 1, health_page.temp_sensor[i],
2426 : 0 : (int)health_page.temp_sensor[i] - 273);
2427 : : }
2428 : : }
2429 : 60 : printf("\n");
2430 : : }
2431 : :
2432 [ + + + + ]: 72 : if (features[SPDK_NVME_FEAT_NUMBER_OF_QUEUES].valid) {
2433 : 64 : uint32_t result = features[SPDK_NVME_FEAT_NUMBER_OF_QUEUES].result;
2434 : :
2435 [ - + ]: 64 : printf("Number of Queues\n");
2436 [ - + ]: 64 : printf("================\n");
2437 [ - + ]: 64 : printf("Number of I/O Submission Queues: %u\n", (result & 0xFFFF) + 1);
2438 [ - + ]: 64 : printf("Number of I/O Completion Queues: %u\n", (result & 0xFFFF0000 >> 16) + 1);
2439 : 64 : printf("\n");
2440 : : }
2441 : :
2442 [ - + - + ]: 72 : if (features[SPDK_OCSSD_FEAT_MEDIA_FEEDBACK].valid) {
2443 : 0 : uint32_t result = features[SPDK_OCSSD_FEAT_MEDIA_FEEDBACK].result;
2444 : :
2445 [ # # ]: 0 : printf("OCSSD Media Feedback\n");
2446 [ # # ]: 0 : printf("=======================\n");
2447 [ # # ]: 0 : printf("High ECC status: %u\n", (result & 0x1));
2448 [ # # ]: 0 : printf("Vector High ECC status: %u\n", (result & 0x2 >> 1));
2449 : 0 : printf("\n");
2450 : : }
2451 : :
2452 [ - + ]: 72 : if (cdata->hctma.bits.supported) {
2453 [ # # ]: 0 : printf("Host Controlled Thermal Management\n");
2454 [ # # ]: 0 : printf("==================================\n");
2455 [ # # ]: 0 : printf("Minimum Thermal Management Temperature: ");
2456 [ # # ]: 0 : if (cdata->mntmt) {
2457 [ # # ]: 0 : printf("%u Kelvin (%d Celsius)\n", cdata->mntmt, (int)cdata->mntmt - 273);
2458 : : } else {
2459 [ # # ]: 0 : printf("Not Reported\n");
2460 : : }
2461 [ # # ]: 0 : printf("Maximum Thermal Management Temperature: ");
2462 [ # # ]: 0 : if (cdata->mxtmt) {
2463 [ # # ]: 0 : printf("%u Kelvin (%d Celsius)\n", cdata->mxtmt, (int)cdata->mxtmt - 273);
2464 : : } else {
2465 [ # # ]: 0 : printf("Not Reported\n");
2466 : : }
2467 : 0 : printf("\n");
2468 : : }
2469 : :
2470 [ + + ]: 72 : if (spdk_nvme_ctrlr_is_log_page_supported(ctrlr, SPDK_NVME_INTEL_LOG_SMART)) {
2471 : 7 : size_t i = 0;
2472 : :
2473 [ - + ]: 7 : printf("Intel Health Information\n");
2474 [ - + ]: 7 : printf("==================\n");
2475 : 7 : for (i = 0;
2476 [ + + ]: 98 : i < SPDK_COUNTOF(intel_smart_page.attributes); i++) {
2477 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_PROGRAM_FAIL_COUNT) {
2478 [ - + ]: 6 : printf("Program Fail Count:\n");
2479 : 6 : printf(" Normalized Value : %d\n",
2480 [ - + ]: 6 : intel_smart_page.attributes[i].normalized_value);
2481 [ - + ]: 6 : printf(" Current Raw Value: ");
2482 : 6 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2483 : 6 : printf("\n");
2484 : : }
2485 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_ERASE_FAIL_COUNT) {
2486 [ - + ]: 6 : printf("Erase Fail Count:\n");
2487 : 6 : printf(" Normalized Value : %d\n",
2488 [ - + ]: 6 : intel_smart_page.attributes[i].normalized_value);
2489 [ - + ]: 6 : printf(" Current Raw Value: ");
2490 : 6 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2491 : 6 : printf("\n");
2492 : : }
2493 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_WEAR_LEVELING_COUNT) {
2494 [ - + ]: 6 : printf("Wear Leveling Count:\n");
2495 : 6 : printf(" Normalized Value : %d\n",
2496 [ - + ]: 6 : intel_smart_page.attributes[i].normalized_value);
2497 [ - + ]: 6 : printf(" Current Raw Value:\n");
2498 [ - + ]: 6 : printf(" Min: ");
2499 : 6 : print_uint_var_dec(&intel_smart_page.attributes[i].raw_value[0], 2);
2500 : 6 : printf("\n");
2501 [ - + ]: 6 : printf(" Max: ");
2502 : 6 : print_uint_var_dec(&intel_smart_page.attributes[i].raw_value[2], 2);
2503 : 6 : printf("\n");
2504 [ - + ]: 6 : printf(" Avg: ");
2505 : 6 : print_uint_var_dec(&intel_smart_page.attributes[i].raw_value[4], 2);
2506 : 6 : printf("\n");
2507 : : }
2508 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_E2E_ERROR_COUNT) {
2509 [ - + ]: 7 : printf("End to End Error Detection Count:\n");
2510 : 7 : printf(" Normalized Value : %d\n",
2511 [ - + ]: 7 : intel_smart_page.attributes[i].normalized_value);
2512 [ - + ]: 7 : printf(" Current Raw Value: ");
2513 : 7 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2514 : 7 : printf("\n");
2515 : : }
2516 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_CRC_ERROR_COUNT) {
2517 [ - + ]: 7 : printf("CRC Error Count:\n");
2518 : 7 : printf(" Normalized Value : %d\n",
2519 [ - + ]: 7 : intel_smart_page.attributes[i].normalized_value);
2520 [ - + ]: 7 : printf(" Current Raw Value: ");
2521 : 7 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2522 : 7 : printf("\n");
2523 : : }
2524 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_MEDIA_WEAR) {
2525 [ - + ]: 7 : printf("Timed Workload, Media Wear:\n");
2526 : 7 : printf(" Normalized Value : %d\n",
2527 [ - + ]: 7 : intel_smart_page.attributes[i].normalized_value);
2528 [ - + ]: 7 : printf(" Current Raw Value: ");
2529 : 7 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2530 : 7 : printf("\n");
2531 : : }
2532 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_HOST_READ_PERCENTAGE) {
2533 [ - + ]: 7 : printf("Timed Workload, Host Read/Write Ratio:\n");
2534 : 7 : printf(" Normalized Value : %d\n",
2535 [ - + ]: 7 : intel_smart_page.attributes[i].normalized_value);
2536 [ - + ]: 7 : printf(" Current Raw Value: ");
2537 : 7 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2538 [ - + ]: 7 : printf("%%");
2539 : 7 : printf("\n");
2540 : : }
2541 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_TIMER) {
2542 [ - + ]: 7 : printf("Timed Workload, Timer:\n");
2543 : 7 : printf(" Normalized Value : %d\n",
2544 [ - + ]: 7 : intel_smart_page.attributes[i].normalized_value);
2545 [ - + ]: 7 : printf(" Current Raw Value: ");
2546 : 7 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2547 : 7 : printf("\n");
2548 : : }
2549 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_THERMAL_THROTTLE_STATUS) {
2550 [ - + ]: 7 : printf("Thermal Throttle Status:\n");
2551 : 7 : printf(" Normalized Value : %d\n",
2552 [ - + ]: 7 : intel_smart_page.attributes[i].normalized_value);
2553 [ - + ]: 7 : printf(" Current Raw Value:\n");
2554 [ - + ]: 7 : printf(" Percentage: %d%%\n", intel_smart_page.attributes[i].raw_value[0]);
2555 [ - + ]: 7 : printf(" Throttling Event Count: ");
2556 : 7 : print_uint_var_dec(&intel_smart_page.attributes[i].raw_value[1], 4);
2557 : 7 : printf("\n");
2558 : : }
2559 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_RETRY_BUFFER_OVERFLOW_COUNTER) {
2560 [ - + ]: 7 : printf("Retry Buffer Overflow Counter:\n");
2561 : 7 : printf(" Normalized Value : %d\n",
2562 [ - + ]: 7 : intel_smart_page.attributes[i].normalized_value);
2563 [ - + ]: 7 : printf(" Current Raw Value: ");
2564 : 7 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2565 : 7 : printf("\n");
2566 : : }
2567 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_PLL_LOCK_LOSS_COUNT) {
2568 [ - + ]: 7 : printf("PLL Lock Loss Count:\n");
2569 : 7 : printf(" Normalized Value : %d\n",
2570 [ - + ]: 7 : intel_smart_page.attributes[i].normalized_value);
2571 [ - + ]: 7 : printf(" Current Raw Value: ");
2572 : 7 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2573 : 7 : printf("\n");
2574 : : }
2575 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_NAND_BYTES_WRITTEN) {
2576 [ - + ]: 6 : printf("NAND Bytes Written:\n");
2577 : 6 : printf(" Normalized Value : %d\n",
2578 [ - + ]: 6 : intel_smart_page.attributes[i].normalized_value);
2579 [ - + ]: 6 : printf(" Current Raw Value: ");
2580 : 6 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2581 : 6 : printf("\n");
2582 : : }
2583 [ + + ]: 91 : if (intel_smart_page.attributes[i].code == SPDK_NVME_INTEL_SMART_HOST_BYTES_WRITTEN) {
2584 [ - + ]: 7 : printf("Host Bytes Written:\n");
2585 : 7 : printf(" Normalized Value : %d\n",
2586 [ - + ]: 7 : intel_smart_page.attributes[i].normalized_value);
2587 [ - + ]: 7 : printf(" Current Raw Value: ");
2588 : 7 : print_uint_var_dec(intel_smart_page.attributes[i].raw_value, 6);
2589 : 7 : printf("\n");
2590 : : }
2591 : : }
2592 : 7 : printf("\n");
2593 : : }
2594 : :
2595 [ + + ]: 72 : if (spdk_nvme_ctrlr_is_log_page_supported(ctrlr, SPDK_NVME_INTEL_LOG_TEMPERATURE)) {
2596 [ - + ]: 7 : printf("Intel Temperature Information\n");
2597 [ - + ]: 7 : printf("==================\n");
2598 [ - + ]: 7 : printf("Current Temperature: %" PRIu64 "\n", intel_temperature_page.current_temperature);
2599 [ - + ]: 7 : printf("Overtemp shutdown Flag for last critical component temperature: %" PRIu64 "\n",
2600 : : intel_temperature_page.shutdown_flag_last);
2601 [ - + ]: 7 : printf("Overtemp shutdown Flag for life critical component temperature: %" PRIu64 "\n",
2602 : : intel_temperature_page.shutdown_flag_life);
2603 [ - + ]: 7 : printf("Highest temperature: %" PRIu64 "\n", intel_temperature_page.highest_temperature);
2604 [ - + ]: 7 : printf("Lowest temperature: %" PRIu64 "\n", intel_temperature_page.lowest_temperature);
2605 [ - + ]: 7 : printf("Specified Maximum Operating Temperature: %" PRIu64 "\n",
2606 : : intel_temperature_page.specified_max_op_temperature);
2607 [ - + ]: 7 : printf("Specified Minimum Operating Temperature: %" PRIu64 "\n",
2608 : : intel_temperature_page.specified_min_op_temperature);
2609 [ - + ]: 7 : printf("Estimated offset: %" PRId64 "\n", (int64_t)intel_temperature_page.estimated_offset);
2610 : 7 : printf("\n");
2611 : 7 : printf("\n");
2612 : :
2613 : : }
2614 : :
2615 [ + + ]: 72 : if (spdk_nvme_ctrlr_is_log_page_supported(ctrlr, SPDK_NVME_INTEL_MARKETING_DESCRIPTION)) {
2616 [ - + ]: 7 : printf("Intel Marketing Information\n");
2617 [ - + ]: 7 : printf("==================\n");
2618 [ - + ]: 7 : snprintf(str, sizeof(intel_md_page.marketing_product), "%s", intel_md_page.marketing_product);
2619 [ - + ]: 7 : printf("Marketing Product Information: %s\n", str);
2620 : 7 : printf("\n");
2621 : 7 : printf("\n");
2622 : : }
2623 : :
2624 [ + + ]: 72 : if (spdk_nvme_zns_ctrlr_get_data(ctrlr)) {
2625 [ - + ]: 47 : printf("ZNS Specific Controller Data\n");
2626 [ - + ]: 47 : printf("============================\n");
2627 : 47 : printf("Zone Append Size Limit: %u\n",
2628 [ - + ]: 47 : spdk_nvme_zns_ctrlr_get_data(ctrlr)->zasl);
2629 : 47 : printf("\n");
2630 : 47 : printf("\n");
2631 : : }
2632 : :
2633 [ - + ]: 72 : printf("Active Namespaces\n");
2634 [ - + ]: 72 : printf("=================\n");
2635 : 72 : for (nsid = spdk_nvme_ctrlr_get_first_active_ns(ctrlr);
2636 [ + + ]: 144 : nsid != 0; nsid = spdk_nvme_ctrlr_get_next_active_ns(ctrlr, nsid)) {
2637 : 72 : get_ns_features(ctrlr, nsid);
2638 : 72 : print_namespace(ctrlr, spdk_nvme_ctrlr_get_ns(ctrlr, nsid));
2639 : : }
2640 : :
2641 [ + + ]: 72 : if (g_discovery_page) {
2642 [ - + ]: 8 : printf("Discovery Log Page\n");
2643 [ - + ]: 8 : printf("==================\n");
2644 : :
2645 [ - + - + ]: 8 : if (g_hex_dump) {
2646 : 0 : hex_dump(g_discovery_page, g_discovery_page_size);
2647 : 0 : printf("\n");
2648 : : }
2649 : :
2650 [ - + ]: 8 : printf("Generation Counter: %" PRIu64 "\n",
2651 : 8 : from_le64(&g_discovery_page->genctr));
2652 [ - + ]: 8 : printf("Number of Records: %" PRIu64 "\n",
2653 : 8 : from_le64(&g_discovery_page->numrec));
2654 [ - + ]: 8 : printf("Record Format: %" PRIu16 "\n",
2655 : 8 : from_le16(&g_discovery_page->recfmt));
2656 : 8 : printf("\n");
2657 : :
2658 [ + + ]: 24 : for (i = 0; i < g_discovery_page_numrec; i++) {
2659 : 16 : struct spdk_nvmf_discovery_log_page_entry *entry = &g_discovery_page->entries[i];
2660 : :
2661 [ - + ]: 16 : printf("Discovery Log Entry %u\n", i);
2662 [ - + ]: 16 : printf("----------------------\n");
2663 : 16 : printf("Transport Type: %u (%s)\n",
2664 [ - + ]: 16 : entry->trtype, spdk_nvme_transport_id_trtype_str(entry->trtype));
2665 : 16 : printf("Address Family: %u (%s)\n",
2666 [ - + ]: 16 : entry->adrfam, spdk_nvme_transport_id_adrfam_str(entry->adrfam));
2667 : 32 : printf("Subsystem Type: %u (%s)\n",
2668 [ - + ]: 16 : entry->subtype,
2669 [ + - ]: 16 : entry->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY ? "Referral to a discovery service" :
2670 [ + + ]: 24 : entry->subtype == SPDK_NVMF_SUBTYPE_NVME ? "NVM Subsystem" :
2671 [ + - ]: 8 : entry->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY_CURRENT ? "Current Discovery Subsystem" :
2672 : : "Unknown");
2673 [ - + ]: 16 : printf("Entry Flags:\n");
2674 : 16 : printf(" Duplicate Returned Information: %u\n",
2675 [ - + ]: 16 : !!(entry->eflags & SPDK_NVMF_DISCOVERY_LOG_EFLAGS_DUPRETINFO));
2676 : 16 : printf(" Explicit Persistent Connection Support for Discovery: %u\n",
2677 [ - + ]: 16 : !!(entry->eflags & SPDK_NVMF_DISCOVERY_LOG_EFLAGS_EPCSD));
2678 [ - + ]: 16 : printf("Transport Requirements:\n");
2679 [ - + ]: 16 : printf(" Secure Channel: %s\n",
2680 [ + + ]: 16 : entry->treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_NOT_SPECIFIED ? "Not Specified" :
2681 [ + - ]: 16 : entry->treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_REQUIRED ? "Required" :
2682 [ + - ]: 8 : entry->treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_NOT_REQUIRED ? "Not Required" :
2683 : : "Reserved");
2684 [ - + ]: 16 : printf("Port ID: %" PRIu16 " (0x%04" PRIx16 ")\n",
2685 : 16 : from_le16(&entry->portid), from_le16(&entry->portid));
2686 [ - + ]: 16 : printf("Controller ID: %" PRIu16 " (0x%04" PRIx16 ")\n",
2687 : 16 : from_le16(&entry->cntlid), from_le16(&entry->cntlid));
2688 [ - + ]: 16 : printf("Admin Max SQ Size: %" PRIu16 "\n",
2689 : 16 : from_le16(&entry->asqsz));
2690 [ - + ]: 16 : snprintf(str, sizeof(entry->trsvcid) + 1, "%s", entry->trsvcid);
2691 [ - + ]: 16 : printf("Transport Service Identifier: %s\n", str);
2692 [ - + ]: 16 : snprintf(str, sizeof(entry->subnqn) + 1, "%s", entry->subnqn);
2693 [ - + ]: 16 : printf("NVM Subsystem Qualified Name: %s\n", str);
2694 [ - + ]: 16 : snprintf(str, sizeof(entry->traddr) + 1, "%s", entry->traddr);
2695 [ - + ]: 16 : printf("Transport Address: %s\n", str);
2696 : :
2697 [ + + ]: 16 : if (entry->trtype == SPDK_NVMF_TRTYPE_RDMA) {
2698 [ - + ]: 4 : printf("Transport Specific Address Subtype - RDMA\n");
2699 : 8 : printf(" RDMA QP Service Type: %u (%s)\n",
2700 [ - + ]: 4 : entry->tsas.rdma.rdma_qptype,
2701 [ - + ]: 4 : entry->tsas.rdma.rdma_qptype == SPDK_NVMF_RDMA_QPTYPE_RELIABLE_CONNECTED ? "Reliable Connected" :
2702 [ # # ]: 0 : entry->tsas.rdma.rdma_qptype == SPDK_NVMF_RDMA_QPTYPE_RELIABLE_DATAGRAM ? "Reliable Datagram" :
2703 : : "Unknown");
2704 : 8 : printf(" RDMA Provider Type: %u (%s)\n",
2705 [ - + ]: 4 : entry->tsas.rdma.rdma_prtype,
2706 [ - + ]: 4 : entry->tsas.rdma.rdma_prtype == SPDK_NVMF_RDMA_PRTYPE_NONE ? "No provider specified" :
2707 [ # # ]: 0 : entry->tsas.rdma.rdma_prtype == SPDK_NVMF_RDMA_PRTYPE_IB ? "InfiniBand" :
2708 [ # # ]: 0 : entry->tsas.rdma.rdma_prtype == SPDK_NVMF_RDMA_PRTYPE_ROCE ? "InfiniBand RoCE" :
2709 [ # # ]: 0 : entry->tsas.rdma.rdma_prtype == SPDK_NVMF_RDMA_PRTYPE_ROCE2 ? "InfiniBand RoCE v2" :
2710 [ # # ]: 0 : entry->tsas.rdma.rdma_prtype == SPDK_NVMF_RDMA_PRTYPE_IWARP ? "iWARP" :
2711 : : "Unknown");
2712 : 8 : printf(" RDMA CM Service: %u (%s)\n",
2713 [ - + ]: 4 : entry->tsas.rdma.rdma_cms,
2714 [ + - ]: 4 : entry->tsas.rdma.rdma_cms == SPDK_NVMF_RDMA_CMS_RDMA_CM ? "RDMA_CM" :
2715 : : "Unknown");
2716 [ - + ]: 4 : if (entry->adrfam == SPDK_NVMF_ADRFAM_IB) {
2717 [ # # ]: 0 : printf(" RDMA Partition Key: %" PRIu32 "\n",
2718 : 0 : from_le32(&entry->tsas.rdma.rdma_pkey));
2719 : : }
2720 : : }
2721 : : }
2722 : 8 : free(g_discovery_page);
2723 : 8 : g_discovery_page = NULL;
2724 : : }
2725 : : }
2726 : :
2727 : : static void
2728 : 0 : usage(const char *program_name)
2729 : : {
2730 [ # # ]: 0 : printf("%s [options]", program_name);
2731 : 0 : printf("\n");
2732 [ # # ]: 0 : printf("options:\n");
2733 [ # # ]: 0 : printf(" -r trid remote NVMe over Fabrics target address\n");
2734 [ # # ]: 0 : printf(" Format: 'key:value [key:value] ...'\n");
2735 [ # # ]: 0 : printf(" Keys:\n");
2736 [ # # ]: 0 : printf(" trtype Transport type (e.g. RDMA)\n");
2737 [ # # ]: 0 : printf(" adrfam Address family (e.g. IPv4, IPv6)\n");
2738 [ # # ]: 0 : printf(" traddr Transport address (e.g. 192.168.100.8)\n");
2739 [ # # ]: 0 : printf(" trsvcid Transport service identifier (e.g. 4420)\n");
2740 [ # # ]: 0 : printf(" subnqn Subsystem NQN (default: %s)\n", SPDK_NVMF_DISCOVERY_NQN);
2741 [ # # ]: 0 : printf(" hostnqn Host NQN\n");
2742 [ # # ]: 0 : printf(" Example: -r 'trtype:RDMA adrfam:IPv4 traddr:192.168.100.8 trsvcid:4420'\n");
2743 : :
2744 : 0 : spdk_log_usage(stdout, "-L");
2745 : :
2746 [ # # ]: 0 : printf(" -i shared memory group ID\n");
2747 [ # # ]: 0 : printf(" -p core number in decimal to run this application which started from 0\n");
2748 [ # # ]: 0 : printf(" -d DPDK huge memory size in MB\n");
2749 [ # # ]: 0 : printf(" -g use single file descriptor for DPDK memory segments\n");
2750 [ # # ]: 0 : printf(" -v IOVA mode ('pa' or 'va')\n");
2751 [ # # ]: 0 : printf(" -x print hex dump of raw data\n");
2752 [ # # ]: 0 : printf(" -z For NVMe Zoned Namespaces, dump the full zone report (-z) or the first N entries (-z N)\n");
2753 [ # # ]: 0 : printf(" -V enumerate VMD\n");
2754 [ # # ]: 0 : printf(" -S socket implementation, e.g. -S uring (default is posix)\n");
2755 [ # # ]: 0 : printf(" -H show this usage\n");
2756 : 0 : }
2757 : :
2758 : : static int
2759 : 68 : parse_args(int argc, char **argv)
2760 : : {
2761 : : int op, rc;
2762 : : char *hostnqn;
2763 : :
2764 : 68 : spdk_nvme_trid_populate_transport(&g_trid, SPDK_NVME_TRANSPORT_PCIE);
2765 : 68 : snprintf(g_trid.subnqn, sizeof(g_trid.subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
2766 : :
2767 [ + + + + ]: 168 : while ((op = getopt(argc, argv, "d:gi:op:r:v:xz::HL:S:V")) != -1) {
2768 [ - + + - : 100 : switch (op) {
- + - - -
+ - + -
- ]
2769 : 0 : case 'd':
2770 : 0 : g_dpdk_mem = spdk_strtol(optarg, 10);
2771 [ # # ]: 0 : if (g_dpdk_mem < 0) {
2772 [ # # ]: 0 : fprintf(stderr, "Invalid DPDK memory size\n");
2773 : 0 : return g_dpdk_mem;
2774 : : }
2775 : 0 : break;
2776 : 2 : case 'g':
2777 : 2 : g_dpdk_mem_single_seg = true;
2778 : 2 : break;
2779 : 21 : case 'i':
2780 : 21 : g_shm_id = spdk_strtol(optarg, 10);
2781 [ - + ]: 21 : if (g_shm_id < 0) {
2782 [ # # ]: 0 : fprintf(stderr, "Invalid shared memory ID\n");
2783 : 0 : return g_shm_id;
2784 : : }
2785 : 21 : break;
2786 : 0 : case 'o':
2787 : 0 : g_ocssd_verbose = true;
2788 : 0 : break;
2789 : 0 : case 'p':
2790 : 0 : g_main_core = spdk_strtol(optarg, 10);
2791 [ # # ]: 0 : if (g_main_core < 0) {
2792 [ # # ]: 0 : fprintf(stderr, "Invalid core number\n");
2793 : 0 : return g_main_core;
2794 : : }
2795 [ # # ]: 0 : snprintf(g_core_mask, sizeof(g_core_mask), "0x%llx", 1ULL << g_main_core);
2796 : 0 : break;
2797 : 62 : case 'r':
2798 [ - + ]: 62 : if (spdk_nvme_transport_id_parse(&g_trid, optarg) != 0) {
2799 [ # # ]: 0 : fprintf(stderr, "Error parsing transport address\n");
2800 : 0 : return 1;
2801 : : }
2802 : :
2803 [ - + ]: 62 : assert(optarg != NULL);
2804 [ - + ]: 62 : hostnqn = strcasestr(optarg, "hostnqn:");
2805 [ - + ]: 62 : if (hostnqn) {
2806 : : size_t len;
2807 : :
2808 : 0 : hostnqn += strlen("hostnqn:");
2809 : :
2810 [ # # ]: 0 : len = strcspn(hostnqn, " \t\n");
2811 [ # # ]: 0 : if (len > (sizeof(g_hostnqn) - 1)) {
2812 [ # # ]: 0 : fprintf(stderr, "Host NQN is too long\n");
2813 : 0 : return 1;
2814 : : }
2815 : :
2816 [ # # ]: 0 : memcpy(g_hostnqn, hostnqn, len);
2817 : 0 : g_hostnqn[len] = '\0';
2818 : : }
2819 : 62 : break;
2820 : 0 : case 'v':
2821 : 0 : g_iova_mode = optarg;
2822 : 0 : break;
2823 : 0 : case 'x':
2824 : 0 : g_hex_dump = true;
2825 : 0 : break;
2826 : 0 : case 'z':
2827 [ # # # # : 0 : if (optarg == NULL && argv[optind] != NULL && argv[optind][0] != '-') {
# # ]
2828 : 0 : g_zone_report_limit = spdk_strtol(argv[optind], 10);
2829 : 0 : ++optind;
2830 [ # # ]: 0 : } else if (optarg) {
2831 : 0 : g_zone_report_limit = spdk_strtol(optarg, 10);
2832 : : } else {
2833 : 0 : g_zone_report_limit = 0;
2834 : : }
2835 [ # # ]: 0 : if (g_zone_report_limit < 0) {
2836 [ # # ]: 0 : fprintf(stderr, "Invalid Zone Report limit\n");
2837 : 0 : return g_zone_report_limit;
2838 : : }
2839 : 0 : break;
2840 : 14 : case 'L':
2841 : 14 : rc = spdk_log_set_flag(optarg);
2842 [ - + ]: 14 : if (rc < 0) {
2843 [ # # ]: 0 : fprintf(stderr, "unknown flag\n");
2844 : 0 : usage(argv[0]);
2845 : 0 : exit(EXIT_FAILURE);
2846 : : }
2847 : : #ifdef DEBUG
2848 : 14 : spdk_log_set_print_level(SPDK_LOG_DEBUG);
2849 : : #endif
2850 : 14 : break;
2851 : 0 : case 'H':
2852 : 0 : usage(argv[0]);
2853 : 0 : exit(EXIT_SUCCESS);
2854 : 1 : case 'V':
2855 : 1 : g_vmd = true;
2856 : 1 : break;
2857 : 0 : case 'S':
2858 : 0 : rc = spdk_sock_set_default_impl(optarg);
2859 [ # # ]: 0 : if (rc < 0) {
2860 [ # # ]: 0 : fprintf(stderr, "Invalid socket implementation\n");
2861 : 0 : exit(EXIT_FAILURE);
2862 : : }
2863 : 0 : break;
2864 : 0 : default:
2865 : 0 : usage(argv[0]);
2866 : 0 : return 1;
2867 : : }
2868 : : }
2869 : :
2870 : 68 : return 0;
2871 : : }
2872 : :
2873 : : static bool
2874 : 0 : probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
2875 : : struct spdk_nvme_ctrlr_opts *opts)
2876 : : {
2877 : 0 : memcpy(opts->hostnqn, g_hostnqn, sizeof(opts->hostnqn));
2878 : 0 : return true;
2879 : : }
2880 : :
2881 : : static void
2882 : 10 : attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
2883 : : struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
2884 : : {
2885 : 10 : g_controllers_found++;
2886 : 10 : print_controller(ctrlr, trid, opts);
2887 : 10 : spdk_nvme_detach_async(ctrlr, &g_detach_ctx);
2888 : 10 : }
2889 : :
2890 : : int
2891 : 68 : main(int argc, char **argv)
2892 : : {
2893 : : int rc;
2894 : 25 : struct spdk_env_opts opts;
2895 : : struct spdk_nvme_ctrlr *ctrlr;
2896 : :
2897 : 68 : rc = parse_args(argc, argv);
2898 [ - + ]: 68 : if (rc != 0) {
2899 : 0 : return rc;
2900 : : }
2901 : :
2902 : 68 : opts.opts_size = sizeof(opts);
2903 : 68 : spdk_env_opts_init(&opts);
2904 : 68 : opts.name = "identify";
2905 : 68 : opts.shm_id = g_shm_id;
2906 : 68 : opts.mem_size = g_dpdk_mem;
2907 : 68 : opts.mem_channel = 1;
2908 : 68 : opts.main_core = g_main_core;
2909 : 68 : opts.core_mask = g_core_mask;
2910 [ - + ]: 68 : opts.hugepage_single_segments = g_dpdk_mem_single_seg;
2911 : 68 : opts.iova_mode = g_iova_mode;
2912 [ + + ]: 68 : if (g_trid.trtype != SPDK_NVME_TRANSPORT_PCIE) {
2913 : 22 : opts.no_pci = true;
2914 : : }
2915 [ - + ]: 68 : if (spdk_env_init(&opts) < 0) {
2916 [ # # # # ]: 0 : fprintf(stderr, "Unable to initialize SPDK env\n");
2917 : 0 : return 1;
2918 : : }
2919 : :
2920 [ - + + + : 68 : if (g_vmd && spdk_vmd_init()) {
- + ]
2921 [ # # # # ]: 0 : fprintf(stderr, "Failed to initialize VMD."
2922 : : " Some NVMe devices can be unavailable.\n");
2923 : : }
2924 : :
2925 : : /* A specific trid is required. */
2926 [ + + ]: 68 : if (strlen(g_trid.traddr) != 0) {
2927 : 22 : struct spdk_nvme_ctrlr_opts opts;
2928 : :
2929 : 62 : spdk_nvme_ctrlr_get_default_ctrlr_opts(&opts, sizeof(opts));
2930 [ - + ]: 62 : if (g_hostnqn[0] != '\0') {
2931 : 0 : memcpy(opts.hostnqn, g_hostnqn, sizeof(opts.hostnqn));
2932 : : }
2933 : 62 : ctrlr = spdk_nvme_connect(&g_trid, &opts, sizeof(opts));
2934 [ - + ]: 62 : if (!ctrlr) {
2935 [ # # # # ]: 0 : fprintf(stderr, "spdk_nvme_connect() failed\n");
2936 : 0 : rc = 1;
2937 : 0 : goto exit;
2938 : : }
2939 : :
2940 : 62 : g_controllers_found++;
2941 : 62 : print_controller(ctrlr, &g_trid, spdk_nvme_ctrlr_get_opts(ctrlr));
2942 : 62 : spdk_nvme_detach_async(ctrlr, &g_detach_ctx);
2943 [ - + ]: 6 : } else if (spdk_nvme_probe(&g_trid, NULL, probe_cb, attach_cb, NULL) != 0) {
2944 [ # # # # ]: 0 : fprintf(stderr, "spdk_nvme_probe() failed\n");
2945 : 0 : rc = 1;
2946 : 0 : goto exit;
2947 : : }
2948 : :
2949 [ + + ]: 68 : if (g_detach_ctx) {
2950 : 52 : spdk_nvme_detach_poll(g_detach_ctx);
2951 : : }
2952 : :
2953 [ + - ]: 68 : if (g_controllers_found == 0) {
2954 [ # # # # ]: 0 : fprintf(stderr, "No NVMe controllers found.\n");
2955 : : }
2956 : :
2957 : 68 : exit:
2958 [ - + + + ]: 68 : if (g_vmd) {
2959 : 1 : spdk_vmd_fini();
2960 : : }
2961 : :
2962 : 68 : spdk_env_fini();
2963 : :
2964 : 68 : return rc;
2965 : : }
|