]>
git.proxmox.com Git - mirror_smartmontools-debian.git/blob - nvmeprint.cpp
fe7053e13c9ae747e66716d7eb04daaf03573662
4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2016-17 Christian Franke
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * You should have received a copy of the GNU General Public License
14 * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
19 #include "nvmeprint.h"
21 const char * nvmeprint_cvsid
= "$Id: nvmeprint.cpp 4580 2017-11-03 19:41:14Z chrfranke $"
26 #include "dev_interface.h"
28 #include "atacmds.h" // dont_print_serial_number
29 #include "scsicmds.h" // dStrHex()
32 using namespace smartmontools
;
34 // Return true if 128 bit LE integer is != 0.
35 static bool le128_is_non_zero(const unsigned char (& val
)[16])
37 for (int i
= 0; i
< 16; i
++) {
44 // Format 128 bit integer for printing.
45 // Add value with SI prefixes if BYTES_PER_UNIT is specified.
46 static const char * le128_to_str(char (& str
)[64], uint64_t hi
, uint64_t lo
, unsigned bytes_per_unit
)
49 // Up to 64-bit, print exact value
50 format_with_thousands_sep(str
, sizeof(str
)-16, lo
);
52 if (lo
&& bytes_per_unit
&& lo
< 0xffffffffffffffffULL
/ bytes_per_unit
) {
54 str
[i
++] = ' '; str
[i
++] = '[';
55 format_capacity(str
+i
, (int)sizeof(str
)-i
-1, lo
* bytes_per_unit
);
57 str
[i
++] = ']'; str
[i
] = 0;
61 // More than 64-bit, print approximate value, prepend ~ flag
62 snprintf(str
, sizeof(str
), "~%.0f",
63 hi
* (0xffffffffffffffffULL
+ 1.0) + lo
);
69 // Format 128 bit LE integer for printing.
70 // Add value with SI prefixes if BYTES_PER_UNIT is specified.
71 static const char * le128_to_str(char (& str
)[64], const unsigned char (& val
)[16],
72 unsigned bytes_per_unit
= 0)
74 uint64_t hi
= val
[15];
75 for (int i
= 15-1; i
>= 8; i
--) {
76 hi
<<= 8; hi
+= val
[i
];
79 for (int i
= 7-1; i
>= 0; i
--) {
80 lo
<<= 8; lo
+= val
[i
];
82 return le128_to_str(str
, hi
, lo
, bytes_per_unit
);
85 // Format capacity specified as 64bit LBA count for printing.
86 static const char * lbacap_to_str(char (& str
)[64], uint64_t lba_cnt
, int lba_bits
)
88 return le128_to_str(str
, (lba_cnt
>> (64 - lba_bits
)), (lba_cnt
<< lba_bits
), 1);
91 // Format a Kelvin temperature value in Celsius.
92 static const char * kelvin_to_str(char (& str
)[64], int k
)
94 if (!k
) // unsupported?
95 str
[0] = '-', str
[1] = 0;
97 snprintf(str
, sizeof(str
), "%d Celsius", k
- 273);
101 static inline unsigned le16_to_uint(const unsigned char (& val
)[2])
103 return ((val
[1] << 8) | val
[0]);
106 static void print_drive_info(const nvme_id_ctrl
& id_ctrl
, const nvme_id_ns
& id_ns
,
107 unsigned nsid
, bool show_all
)
110 pout("Model Number: %s\n", format_char_array(buf
, id_ctrl
.mn
));
111 if (!dont_print_serial_number
)
112 pout("Serial Number: %s\n", format_char_array(buf
, id_ctrl
.sn
));
113 pout("Firmware Version: %s\n", format_char_array(buf
, id_ctrl
.fr
));
115 // Vendor and Subsystem IDs are usually equal
116 if (show_all
|| id_ctrl
.vid
!= id_ctrl
.ssvid
) {
117 pout("PCI Vendor ID: 0x%04x\n", id_ctrl
.vid
);
118 pout("PCI Vendor Subsystem ID: 0x%04x\n", id_ctrl
.ssvid
);
121 pout("PCI Vendor/Subsystem ID: 0x%04x\n", id_ctrl
.vid
);
124 pout("IEEE OUI Identifier: 0x%02x%02x%02x\n",
125 id_ctrl
.ieee
[2], id_ctrl
.ieee
[1], id_ctrl
.ieee
[0]);
127 // Capacity info is optional for devices without namespace management
128 if (show_all
|| le128_is_non_zero(id_ctrl
.tnvmcap
) || le128_is_non_zero(id_ctrl
.unvmcap
)) {
129 pout("Total NVM Capacity: %s\n", le128_to_str(buf
, id_ctrl
.tnvmcap
, 1));
130 pout("Unallocated NVM Capacity: %s\n", le128_to_str(buf
, id_ctrl
.unvmcap
, 1));
133 pout("Controller ID: %d\n", id_ctrl
.cntlid
);
135 // Print namespace info if available
136 pout("Number of Namespaces: %u\n", id_ctrl
.nn
);
138 if (nsid
&& id_ns
.nsze
) {
139 const char * align
= &(" "[nsid
< 10 ? 0 : (nsid
< 100 ? 1 : 2)]);
140 int fmt_lba_bits
= id_ns
.lbaf
[id_ns
.flbas
& 0xf].ds
;
142 // Size and Capacity are equal if thin provisioning is not supported
143 if (show_all
|| id_ns
.ncap
!= id_ns
.nsze
|| (id_ns
.nsfeat
& 0x01)) {
144 pout("Namespace %u Size: %s%s\n", nsid
, align
,
145 lbacap_to_str(buf
, id_ns
.nsze
, fmt_lba_bits
));
146 pout("Namespace %u Capacity: %s%s\n", nsid
, align
,
147 lbacap_to_str(buf
, id_ns
.ncap
, fmt_lba_bits
));
150 pout("Namespace %u Size/Capacity: %s%s\n", nsid
, align
,
151 lbacap_to_str(buf
, id_ns
.nsze
, fmt_lba_bits
));
153 // Utilization may be always equal to Capacity if thin provisioning is not supported
154 if (show_all
|| id_ns
.nuse
!= id_ns
.ncap
|| (id_ns
.nsfeat
& 0x01))
155 pout("Namespace %u Utilization: %s%s\n", nsid
, align
,
156 lbacap_to_str(buf
, id_ns
.nuse
, fmt_lba_bits
));
158 pout("Namespace %u Formatted LBA Size: %s%u\n", nsid
, align
, (1U << fmt_lba_bits
));
160 if (show_all
|| nonempty(id_ns
.eui64
, sizeof(id_ns
.eui64
)))
161 pout("Namespace %u IEEE EUI-64: %s%02x%02x%02x %02x%02x%02x%02x%02x\n",
162 nsid
, align
, id_ns
.eui64
[0], id_ns
.eui64
[1], id_ns
.eui64
[2], id_ns
.eui64
[3],
163 id_ns
.eui64
[4], id_ns
.eui64
[5], id_ns
.eui64
[6], id_ns
.eui64
[7]);
166 char td
[DATEANDEPOCHLEN
]; dateandtimezone(td
);
167 pout("Local Time is: %s\n", td
);
170 // Format scaled power value.
171 static const char * format_power(char (& str
)[16], unsigned power
, unsigned scale
)
173 switch (scale
& 0x3) {
174 case 0: // not reported
175 str
[0] = '-'; str
[1] = ' '; str
[2] = 0; break;
177 snprintf(str
, sizeof(str
), "%u.%04uW", power
/ 10000, power
% 10000); break;
179 snprintf(str
, sizeof(str
), "%u.%02uW", power
/ 100, power
% 100); break;
181 str
[0] = '?'; str
[1] = 0; break;
186 static void print_drive_capabilities(const nvme_id_ctrl
& id_ctrl
, const nvme_id_ns
& id_ns
,
187 unsigned nsid
, bool show_all
)
189 pout("Firmware Updates (0x%02x): %d Slot%s%s%s\n", id_ctrl
.frmw
,
190 ((id_ctrl
.frmw
>> 1) & 0x7), (((id_ctrl
.frmw
>> 1) & 0x7) != 1 ? "s" : ""),
191 ((id_ctrl
.frmw
& 0x01) ? ", Slot 1 R/O" : ""),
192 ((id_ctrl
.frmw
& 0x10) ? ", no Reset required" : ""));
194 if (show_all
|| id_ctrl
.oacs
)
195 pout("Optional Admin Commands (0x%04x): %s%s%s%s%s%s%s%s%s%s%s\n", id_ctrl
.oacs
,
196 (!id_ctrl
.oacs
? " -" : ""),
197 ((id_ctrl
.oacs
& 0x0001) ? " Security" : ""),
198 ((id_ctrl
.oacs
& 0x0002) ? " Format" : ""),
199 ((id_ctrl
.oacs
& 0x0004) ? " Frmw_DL" : ""),
200 ((id_ctrl
.oacs
& 0x0008) ? " NS_Mngmt" : ""),
201 ((id_ctrl
.oacs
& 0x0010) ? " Self_Test" : ""), // NVMe 1.3 ...
202 ((id_ctrl
.oacs
& 0x0020) ? " Directvs" : ""),
203 ((id_ctrl
.oacs
& 0x0040) ? " MI_Snd/Rec" : ""),
204 ((id_ctrl
.oacs
& 0x0080) ? " Vrt_Mngmt" : ""),
205 ((id_ctrl
.oacs
& 0x0100) ? " Drbl_Bf_Cfg" : ""),
206 ((id_ctrl
.oacs
& ~0x01ff) ? " *Other*" : ""));
208 if (show_all
|| id_ctrl
.oncs
)
209 pout("Optional NVM Commands (0x%04x): %s%s%s%s%s%s%s%s%s\n", id_ctrl
.oncs
,
210 (!id_ctrl
.oncs
? " -" : ""),
211 ((id_ctrl
.oncs
& 0x0001) ? " Comp" : ""),
212 ((id_ctrl
.oncs
& 0x0002) ? " Wr_Unc" : ""),
213 ((id_ctrl
.oncs
& 0x0004) ? " DS_Mngmt" : ""),
214 ((id_ctrl
.oncs
& 0x0008) ? " Wr_Zero" : ""),
215 ((id_ctrl
.oncs
& 0x0010) ? " Sav/Sel_Feat" : ""),
216 ((id_ctrl
.oncs
& 0x0020) ? " Resv" : ""),
217 ((id_ctrl
.oncs
& 0x0040) ? " Timestmp" : ""), // NVMe 1.3
218 ((id_ctrl
.oncs
& ~0x007f) ? " *Other*" : ""));
221 pout("Maximum Data Transfer Size: %u Pages\n", (1U << id_ctrl
.mdts
));
223 pout("Maximum Data Transfer Size: -\n");
225 // Temperature thresholds are optional
227 if (show_all
|| id_ctrl
.wctemp
)
228 pout("Warning Comp. Temp. Threshold: %s\n", kelvin_to_str(buf
, id_ctrl
.wctemp
));
229 if (show_all
|| id_ctrl
.cctemp
)
230 pout("Critical Comp. Temp. Threshold: %s\n", kelvin_to_str(buf
, id_ctrl
.cctemp
));
232 if (nsid
&& (show_all
|| id_ns
.nsfeat
)) {
233 const char * align
= &(" "[nsid
< 10 ? 0 : (nsid
< 100 ? 1 : 2)]);
234 pout("Namespace %u Features (0x%02x): %s%s%s%s%s%s%s\n", nsid
, id_ns
.nsfeat
, align
,
235 (!id_ns
.nsfeat
? " -" : ""),
236 ((id_ns
.nsfeat
& 0x01) ? " Thin_Prov" : ""),
237 ((id_ns
.nsfeat
& 0x02) ? " NA_Fields" : ""),
238 ((id_ns
.nsfeat
& 0x04) ? " Dea/Unw_Error" : ""),
239 ((id_ns
.nsfeat
& 0x08) ? " No_ID_Reuse" : ""), // NVMe 1.3
240 ((id_ns
.nsfeat
& ~0x0f) ? " *Other*" : ""));
243 // Print Power States
244 pout("\nSupported Power States\n");
245 pout("St Op Max Active Idle RL RT WL WT Ent_Lat Ex_Lat\n");
246 for (int i
= 0; i
<= id_ctrl
.npss
/* 1-based */ && i
< 32; i
++) {
247 char p1
[16], p2
[16], p3
[16];
248 const nvme_id_power_state
& ps
= id_ctrl
.psd
[i
];
249 pout("%2d %c %9s %8s %8s %3d %2d %2d %2d %8u %7u\n", i
,
250 ((ps
.flags
& 0x02) ? '-' : '+'),
251 format_power(p1
, ps
.max_power
, ((ps
.flags
& 0x01) ? 1 : 2)),
252 format_power(p2
, ps
.active_power
, ps
.active_work_scale
),
253 format_power(p3
, ps
.idle_power
, ps
.idle_scale
),
254 ps
.read_lat
& 0x1f, ps
.read_tput
& 0x1f,
255 ps
.write_lat
& 0x1f, ps
.write_tput
& 0x1f,
256 ps
.entry_lat
, ps
.exit_lat
);
260 if (nsid
&& id_ns
.lbaf
[0].ds
) {
261 pout("\nSupported LBA Sizes (NSID 0x%x)\n", nsid
);
262 pout("Id Fmt Data Metadt Rel_Perf\n");
263 for (int i
= 0; i
<= id_ns
.nlbaf
/* 1-based */ && i
< 16; i
++) {
264 const nvme_lbaf
& lba
= id_ns
.lbaf
[i
];
265 pout("%2d %c %7u %7d %9d\n", i
, (i
== id_ns
.flbas
? '+' : '-'),
266 (1U << lba
.ds
), lba
.ms
, lba
.rp
);
271 static void print_critical_warning(unsigned char w
)
273 pout("SMART overall-health self-assessment test result: %s\n",
274 (!w
? "PASSED" : "FAILED!"));
278 pout("- available spare has fallen below threshold\n");
280 pout("- temperature is above or below threshold\n");
282 pout("- NVM subsystem reliability has been degraded\n");
284 pout("- media has been placed in read only mode\n");
286 pout("- volatile memory backup device has failed\n");
288 pout("- unknown critical warning(s) (0x%02x)\n", w
& ~0x1f);
294 static void print_smart_log(const nvme_smart_log
& smart_log
, unsigned nsid
,
295 const nvme_id_ctrl
& id_ctrl
, bool show_all
)
298 pout("SMART/Health Information (NVMe Log 0x02, NSID 0x%x)\n", nsid
);
299 pout("Critical Warning: 0x%02x\n", smart_log
.critical_warning
);
300 pout("Temperature: %s\n",
301 kelvin_to_str(buf
, le16_to_uint(smart_log
.temperature
)));
302 pout("Available Spare: %u%%\n", smart_log
.avail_spare
);
303 pout("Available Spare Threshold: %u%%\n", smart_log
.spare_thresh
);
304 pout("Percentage Used: %u%%\n", smart_log
.percent_used
);
305 pout("Data Units Read: %s\n", le128_to_str(buf
, smart_log
.data_units_read
, 1000*512));
306 pout("Data Units Written: %s\n", le128_to_str(buf
, smart_log
.data_units_written
, 1000*512));
307 pout("Host Read Commands: %s\n", le128_to_str(buf
, smart_log
.host_reads
));
308 pout("Host Write Commands: %s\n", le128_to_str(buf
, smart_log
.host_writes
));
309 pout("Controller Busy Time: %s\n", le128_to_str(buf
, smart_log
.ctrl_busy_time
));
310 pout("Power Cycles: %s\n", le128_to_str(buf
, smart_log
.power_cycles
));
311 pout("Power On Hours: %s\n", le128_to_str(buf
, smart_log
.power_on_hours
));
312 pout("Unsafe Shutdowns: %s\n", le128_to_str(buf
, smart_log
.unsafe_shutdowns
));
313 pout("Media and Data Integrity Errors: %s\n", le128_to_str(buf
, smart_log
.media_errors
));
314 pout("Error Information Log Entries: %s\n", le128_to_str(buf
, smart_log
.num_err_log_entries
));
316 // Temperature thresholds are optional
317 if (show_all
|| id_ctrl
.wctemp
|| smart_log
.warning_temp_time
)
318 pout("Warning Comp. Temperature Time: %d\n", smart_log
.warning_temp_time
);
319 if (show_all
|| id_ctrl
.cctemp
|| smart_log
.critical_comp_time
)
320 pout("Critical Comp. Temperature Time: %d\n", smart_log
.critical_comp_time
);
322 // Temperature sensors are optional
323 for (int i
= 0; i
< 8; i
++) {
324 if (show_all
|| smart_log
.temp_sensor
[i
])
325 pout("Temperature Sensor %d: %s\n", i
+ 1,
326 kelvin_to_str(buf
, smart_log
.temp_sensor
[i
]));
328 if (show_all
|| smart_log
.thm_temp1_trans_count
)
329 pout("Thermal Temp. 1 Transition Count: %d\n", smart_log
.thm_temp1_trans_count
);
330 if (show_all
|| smart_log
.thm_temp2_trans_count
)
331 pout("Thermal Temp. 2 Transition Count: %d\n", smart_log
.thm_temp2_trans_count
);
332 if (show_all
|| smart_log
.thm_temp1_total_time
)
333 pout("Thermal Temp. 1 Total Time: %d\n", smart_log
.thm_temp1_total_time
);
334 if (show_all
|| smart_log
.thm_temp2_total_time
)
335 pout("Thermal Temp. 2 Total Time: %d\n", smart_log
.thm_temp2_total_time
);
339 static void print_error_log(const nvme_error_log_page
* error_log
,
340 unsigned num_entries
, unsigned print_entries
)
342 pout("Error Information (NVMe Log 0x01, max %u entries)\n", num_entries
);
345 for (unsigned i
= 0; i
< num_entries
; i
++) {
346 const nvme_error_log_page
& e
= error_log
[i
];
348 continue; // unused or invalid entry
349 if (++cnt
> print_entries
)
353 pout("Num ErrCount SQId CmdId Status PELoc LBA NSID VS\n");
355 char sq
[16] = "-", cm
[16] = "-", st
[16] = "-", pe
[16] = "-";
356 char lb
[32] = "-", ns
[16] = "-", vs
[8] = "-";
357 if (e
.sqid
!= 0xffff)
358 snprintf(sq
, sizeof(sq
), "%d", e
.sqid
);
359 if (e
.cmdid
!= 0xffff)
360 snprintf(cm
, sizeof(cm
), "0x%04x", e
.cmdid
);
361 if (e
.status_field
!= 0xffff)
362 snprintf(st
, sizeof(st
), "0x%04x", e
.status_field
);
363 if (e
.parm_error_location
!= 0xffff)
364 snprintf(pe
, sizeof(pe
), "0x%03x", e
.parm_error_location
);
365 if (e
.lba
!= 0xffffffffffffffffULL
)
366 snprintf(lb
, sizeof(lb
), "%" PRIu64
, e
.lba
);
367 if (e
.nsid
!= 0xffffffffU
)
368 snprintf(ns
, sizeof(ns
), "%u", e
.nsid
);
370 snprintf(vs
, sizeof(vs
), "0x%02x", e
.vs
);
372 pout("%3u %10" PRIu64
" %5s %7s %7s %6s %12s %5s %5s\n",
373 i
, e
.error_count
, sq
, cm
, st
, pe
, lb
, ns
, vs
);
377 pout("No Errors Logged\n");
378 else if (cnt
> print_entries
)
379 pout("... (%u entries not shown)\n", cnt
- print_entries
);
383 int nvmePrintMain(nvme_device
* device
, const nvme_print_options
& options
)
385 if (!( options
.drive_info
|| options
.drive_capabilities
386 || options
.smart_check_status
|| options
.smart_vendor_attrib
387 || options
.error_log_entries
|| options
.log_page_size
)) {
388 pout("NVMe device successfully opened\n\n"
389 "Use 'smartctl -a' (or '-x') to print SMART (and more) information\n\n");
393 // Show unset optional values only if debugging is enabled
394 bool show_all
= (nvme_debugmode
> 0);
396 // Read Identify Controller always
397 nvme_id_ctrl id_ctrl
;
398 if (!nvme_read_id_ctrl(device
, id_ctrl
)) {
399 pout("Read NVMe Identify Controller failed: %s\n", device
->get_errmsg());
403 // Print Identify Controller/Namespace info
404 if (options
.drive_info
|| options
.drive_capabilities
) {
405 pout("=== START OF INFORMATION SECTION ===\n");
406 nvme_id_ns id_ns
; memset(&id_ns
, 0, sizeof(id_ns
));
408 unsigned nsid
= device
->get_nsid();
409 if (nsid
== 0xffffffffU
) {
410 // Broadcast namespace
411 if (id_ctrl
.nn
== 1) {
412 // No namespace management, get size from single namespace
414 if (!nvme_read_id_ns(device
, nsid
, id_ns
))
419 // Identify current namespace
420 if (!nvme_read_id_ns(device
, nsid
, id_ns
)) {
421 pout("Read NVMe Identify Namespace 0x%x failed: %s\n", nsid
, device
->get_errmsg());
426 if (options
.drive_info
)
427 print_drive_info(id_ctrl
, id_ns
, nsid
, show_all
);
428 if (options
.drive_capabilities
)
429 print_drive_capabilities(id_ctrl
, id_ns
, nsid
, show_all
);
433 if ( options
.smart_check_status
|| options
.smart_vendor_attrib
434 || options
.error_log_entries
)
435 pout("=== START OF SMART DATA SECTION ===\n");
437 // Print SMART Status and SMART/Health Information
439 if (options
.smart_check_status
|| options
.smart_vendor_attrib
) {
440 nvme_smart_log smart_log
;
441 if (!nvme_read_smart_log(device
, smart_log
)) {
442 pout("Read NVMe SMART/Health Information failed: %s\n\n", device
->get_errmsg());
446 if (options
.smart_check_status
) {
447 print_critical_warning(smart_log
.critical_warning
);
448 if (smart_log
.critical_warning
)
449 retval
|= FAILSTATUS
;
452 if (options
.smart_vendor_attrib
) {
453 print_smart_log(smart_log
, device
->get_nsid(), id_ctrl
, show_all
);
457 // Print Error Information Log
458 if (options
.error_log_entries
) {
459 unsigned num_entries
= id_ctrl
.elpe
+ 1; // 0-based value
460 raw_buffer
error_log_buf(num_entries
* sizeof(nvme_error_log_page
));
461 nvme_error_log_page
* error_log
=
462 reinterpret_cast<nvme_error_log_page
*>(error_log_buf
.data());
464 if (!nvme_read_error_log(device
, error_log
, num_entries
)) {
465 pout("Read Error Information Log failed: %s\n\n", device
->get_errmsg());
466 return retval
| FAILSMART
;
469 print_error_log(error_log
, num_entries
, options
.error_log_entries
);
473 if (options
.log_page_size
) {
474 // Align size to dword boundary
475 unsigned size
= ((options
.log_page_size
+ 4-1) / 4) * 4;
476 raw_buffer
log_buf(size
);
478 if (!nvme_read_log_page(device
, options
.log_page
, log_buf
.data(), size
)) {
479 pout("Read NVMe Log 0x%02x failed: %s\n\n", options
.log_page
, device
->get_errmsg());
480 return retval
| FAILSMART
;
483 pout("NVMe Log 0x%02x (0x%04x bytes)\n", options
.log_page
, size
);
484 dStrHex(log_buf
.data(), size
, 0);