sdnvme, fshalt: turn disks off on fshalt

MNT Reform's power rails are switched off abruptly on shutdown
which causes an "unsafe" shutdown on nvme. This may result in
loss of valid data in the volatile write cache, which is never
going to be synced in this case. This problem has been reported
on forums about Linux too, including actual filesystem errors
resulting from that behavior.

Notify nvme about a shutdown and wait up to 3s before disabling
the controller. This resulted in "unsafe shutdowns" nvme's counter
to never increase on fshalt.
This commit is contained in:
Sigrid Solveig Haflínudóttir 2023-05-24 16:14:33 +00:00
parent e23bb0103b
commit 390c71f0c7
2 changed files with 25 additions and 15 deletions

View file

@ -31,13 +31,14 @@ sleep 1
c=`{ls /srv/cwfs*cmd >[2]/dev/null}
h=`{ls /srv/hjfs*cmd >[2]/dev/null}
s=`{awk '/^sd./ {print substr($1,3,1)}' <'#S/sdctl' >[2]/dev/null}
# for scram, don't scram other systems
bind -b '#P' /dev >[2]/dev/null
if(! ~ $reboot yes){
if (test -e '#P'/apm)
if(test -e '#P'/apm)
scram=yes
if (test -e '#P'/acpitbls -a -e '#P'/iow)
if(test -e '#P'/acpitbls -a -e '#P'/iow)
scram=yes
}
@ -66,9 +67,9 @@ bind /tmp /bin
fn x {
echo
echo -n halting...
for (i in $c $h)
for(i in $c $h)
echo halt >>$i
for (i in $c $h){
for(i in $c $h){
echo -n $i...
while(test -e $i)
sleep 1
@ -76,15 +77,19 @@ fn x {
echo
echo done halting
if (~ $reboot yes) {
# turn off disk drives
for(i in $s)
echo config spec $i switch off >>'#S/sdctl'
if(~ $reboot yes){
echo rebooting...
echo reboot $bootf >'#c/reboot'
}
if not if (test -e /dev/pmctl) {
echo power off >>/dev/pmctl
}
if (~ $scram yes){
scram
if not {
if (test -e /dev/pmctl)
echo power off >>/dev/pmctl
if (~ $scram yes)
scram
echo 'It''s now safe to turn off your computer'
}
}

View file

@ -208,9 +208,8 @@ wcmd(WS *ws, u32int *e)
SQ *sq = ws->queue;
Ctlr *ctlr = sq->ctlr;
if(e != nil) {
if(e != nil)
dmaflush(1, e, 64);
}
coherence();
ctlr->reg[DBell + ((sq-ctlr->sq)*2+0 << ctlr->dstrd)] = sq->tail & sq->mask;
if(sq > ctlr->sq) {
@ -270,9 +269,8 @@ nvmebio(SDunit *u, int lun, int write, void *a, long count, uvlong lba)
count -= n;
lba += n;
}
if(!write) {
if(!write)
dmaflush(0, a, p - (uchar*)a);
}
return p - (uchar*)a;
}
@ -521,9 +519,16 @@ nvmedisable(SDev *sd)
ctlr->reg[IntMs] = ~ctlr->ints;
iunlock(&ctlr->intr);
/* notify normal power off */
ctlr->reg[CCfg] = (ctlr->reg[CCfg] & ~(3<<14)) | 1<<14;
for(i = 0; i < 30; i++){
if((ctlr->reg[CSts] & 0xc) == 0x8)
break;
tsleep(&up->sleep, return0, nil, 100);
}
/* disable controller */
ctlr->reg[CCfg] = 0;
for(i = 0; i < 10; i++){
if((ctlr->reg[CSts] & 1) == 0)
break;