ref: 390c71f0c79b2b8b94997cd9ae03037272075f8b
parent: e23bb0103b46e73f9ce8d69abb19a3726135fff3
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Wed May 24 12:14:33 EDT 2023
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.
--- a/rc/bin/fshalt
+++ b/rc/bin/fshalt
@@ -31,13 +31,14 @@
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 @@
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 @@
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'
}
}
--- a/sys/src/9/port/sdnvme.c
+++ b/sys/src/9/port/sdnvme.c
@@ -208,9 +208,8 @@
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 @@
count -= n;
lba += n;
}
- if(!write) {
+ if(!write)
dmaflush(0, a, p - (uchar*)a);
- }
return p - (uchar*)a;
}
@@ -521,9 +519,16 @@
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;