ref: 18dd720eca74524f78f5e1c76f6a79956271fdb2
parent: 1ff0619c5c8270cf32b99bda770d15c6ece309b7
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue May 23 09:47:34 EDT 2023
sdnvme: collect useful smart/health info and report via ctl
--- a/sys/src/9/port/sdnvme.c
+++ b/sys/src/9/port/sdnvme.c
@@ -348,6 +348,10 @@
{
Ctlr *ctlr;
char *e, *s;
+ u8int *data;
+ u32int *q;
+ u64int n;
+ WS ws;
if((ctlr = u->dev->ctlr) == nil || ctlr->ident == nil)
return 0;
@@ -359,6 +363,37 @@
p = seprint(p, e, "serial\t%.20s\n", (char*)ctlr->ident+4);
p = seprint(p, e, "firm\t%.8s\n", (char*)ctlr->ident+64);
p = seprint(p, e, "geometry %llud %lud\n", u->sectors, u->secsize);
+
+ /* SMART/health */
+ if((data = mallocalign(0x1000, ctlr->mps, 0, 0)) != nil){
+ q = qcmd(&ws, ctlr, 1, 0x02, 0xffffffff, data, 0x1000);
+ q[10] = (512/4)<<16 | 0x2;
+ q[11] = 0;
+ q[12] = 0;
+ q[13] = 0;
+ q[14] = 0;
+ if(wcmd(&ws, q) == 0){
+ dmaflush(0, data, 0x1000);
+ p = seprint(p, e, "temperature\t%d\n", (data[2]<<8 | data[1]) - 273);
+ p = seprint(p, e, "spare\t%d%%\n", data[3]);
+ p = seprint(p, e, "used\t%d%%\n", data[5]);
+ /* 16 bytes long, ignore the upper half */
+ n = data[144]<<0 | data[145]<<8 | data[146]<<16 | data[147]<<24
+ | (u64int)data[148]<<32
+ | (u64int)data[149]<<40
+ | (u64int)data[150]<<48
+ | (u64int)data[151]<<56;
+ p = seprint(p, e, "unsafe shutdowns\t%llud\n", n);
+ /* 16 bytes long, ignore the upper half */
+ n = data[160]<<0 | data[161]<<8 | data[162]<<16 | data[163]<<24
+ | (u64int)data[164]<<32
+ | (u64int)data[165]<<40
+ | (u64int)data[166]<<48
+ | (u64int)data[167]<<56;
+ p = seprint(p, e, "integrity errors\t%llud\n", n);
+ }
+ free(data);
+ }
return p-s;
}