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