Bug 551245

Summary: RFE: reset wakealarm after setting the hardware clock on shutdown
Product: [Fedora] Fedora Reporter: Eric Sandeen <esandeen>
Component: initscriptsAssignee: Lukáš Nykrýn <lnykryn>
Status: CLOSED WONTFIX QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: low    
Version: rawhideCC: clancy.kieran+redhat, iarlyy, initscripts-maint-list, plautrba
Target Milestone: ---Keywords: Reopened
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-06-04 21:48:02 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Eric Sandeen 2009-12-29 16:08:44 UTC
I was working on making mythtv automatically shut down & wake up for the next recording, and came across this:

http://www.mythtv.org/wiki/ACPI_Wakeup#Disable_HWclock_updates

On most machines it is required to make a small change to the Linux shutdown procedure. When your machine shuts down, most Linux distributions write the system time/data back to the BIOS. Most machines never wakeup after this time/data update. It is recommended that you make this change.

The reason for this recommendation is that most Linux distributions write the current system time back to the BIOS when shutting down the machine. With most BIOS, the machine will not wake up if the hardware clock has been modified after the wakeup alarm has been set. To avoid this, it is necessary to disable the writing of the current system time to the BIOS by the system shutdown scripts. 

---

This seems to be the case for me.  Would it be possible to add something like this to the halt script:

--- /etc/rc.d/init.d/halt	2009-12-29 10:06:54.007923517 -0600
+++ /etc/rc.d/init.d/halt.mine	2009-12-29 10:04:02.389461032 -0600
@@ -85,7 +85,9 @@
 chmod 600 /var/lib/random-seed
 action $"Saving random seed: " dd if=/dev/urandom of=/var/lib/random-seed count=1 bs=512 2>/dev/null
 
+WAKEALARM=`cat /sys/class/rtc/rtc0/wakealarm`
 [ -x /sbin/hwclock ] && action $"Syncing hardware clock to system time" /sbin/hwclock --systohc
+echo "$WAKEALARM" > /sys/class/rtc/rtc0/wakealarm
 
 # Try to unmount tmpfs filesystems to avoid swapping them in.  Ignore failures.
 tmpfs=$(awk '$2 ~ /^\/($|proc|dev)/ { next; }

to reset the wakeup time after the hwclock is written?  This should be harmless but I suppose testing for non-null $WAKEALARM before the echo might be best.

Thanks,
-Eric

Comment 1 Bill Nottingham 2010-01-04 20:09:29 UTC
Hm. I wonder if we can always assume that rtc0 is the device that would have the wakealarm.

Comment 2 Eric Sandeen 2010-01-04 20:22:25 UTC
I guess that I don't know... 

Saving it likely wouldn't -hurt- but I suppose missing other rtcX might be bad.

Maybe I should do some digging to find out if the wakealarm clearing is a feature or a bug, first.

Comment 3 Kieran Clancy 2010-01-17 01:38:08 UTC
I think some BIOS reset the wakealarm because they assume that if the time has changed then the alarm's not going to be at the right time anymore so it's better not to have it? My BIOS doesn't reset wakealarm times, for what it's worth.

To cater for rtc1 etc, why not use something like:

--- /etc/rc.d/init.d/halt	2009-12-05 11:14:29.000000000 +1030
+++ halt	2010-01-17 12:02:59.094091031 +1030
@@ -103,10 +103,22 @@ fi
 touch /var/lib/random-seed
 chmod 600 /var/lib/random-seed
 action $"Saving random seed: " dd if=/dev/urandom of=/var/lib/random-seed count=1 bs=512 2>/dev/null
 
+# Save wakealarm times as some BIOS clear this when the hw clock is set
+restore_wake=""
+for f in /sys/class/rtc/*/wakealarm; do
+	[ -f "$f" ] || continue
+	waketime=`< "$f"`
+	[ -n "$waketime" ] || continue
+	restore_wake="$restore_wake echo '$waketime' > '$f';"
+done
+
 [ -x /sbin/hwclock ] && action $"Syncing hardware clock to system time" /sbin/hwclock --systohc
 
+# Restore wakealarm times
+[ -x /sbin/hwclock -a -n "$restore_wake" ] && eval "$restore_wake"
+
 # Try to unmount tmpfs filesystems to avoid swapping them in.  Ignore failures.
 tmpfs=$(awk '$2 ~ /^\/($|proc|dev)/ { next; }
 	     $3 == "tmpfs" { print $2; }' /proc/mounts | sort -r)
 [ -n "$tmpfs" ] && fstab-decode $UMOUNT $tmpfs 2>/dev/null

Comment 4 Bill Nottingham 2010-01-18 17:38:38 UTC
Hah, when thinking about it, the --systohc is only done on the default RTC (i.e., /dev/rtc or /dev/rtc0). So, we shouldn't need to handle non-default wakealarms, as only the default clock is getting reset.

(It does point out that there could be a minor hole in that we're *not* writing back the clock for any non-default RTC, but that hasn't been an issue so far.)

Comment 5 Kieran Clancy 2010-01-18 18:10:18 UTC
Yes, good point.

Hmm, one thing I just noticed on my hardware is that trying to set the wakealarm when it's already set gives you an error like:
# echo +300 > /sys/class/rtc/rtc0/wakealarm
# echo +300 > /sys/class/rtc/rtc0/wakealarm
echo: write error: Device or resource busy

So you have to clear it manually before setting it again:
# echo 0 > wakealarm

Arguably sysfs should handle this better, but just in case we should probably reset it.

--- /etc/rc.d/init.d/halt	2009-12-05 11:14:29.000000000 +1030
+++ halt	2010-01-19 04:31:11.384837255 +1030
@@ -103,9 +103,25 @@ fi
 touch /var/lib/random-seed
 chmod 600 /var/lib/random-seed
 action $"Saving random seed: " dd if=/dev/urandom of=/var/lib/random-seed count=1 bs=512 2>/dev/null
 
-[ -x /sbin/hwclock ] && action $"Syncing hardware clock to system time" /sbin/hwclock --systohc
+if [ -x /sbin/hwclock ]; then
+    # Save wakealarm times; some BIOS clear this when the clock is set
+    # As hwclock only touches rtc0, we shouldn't need to touch rtc1...
+    restore_wake=""
+    if [ -f /sys/class/rtc/rtc0/wakealarm ]; then
+        restore_wake=`< /sys/class/rtc/rtc0/wakealarm`
+    fi
+
+    action $"Syncing hardware clock to system time" /sbin/hwclock --systohc
+
+    # Restore wakealarm times if necessary
+    if [ -n "$restore_wake" ]; then
+	# Unset wakealarm, then set it again
+	echo 0 > /sys/class/rtc/rtc0/wakealarm
+	echo "$restore_wake" > /sys/class/rtc/rtc0/wakealarm
+    fi
+fi
 
 # Try to unmount tmpfs filesystems to avoid swapping them in.  Ignore failures.
 tmpfs=$(awk '$2 ~ /^\/($|proc|dev)/ { next; }
 	     $3 == "tmpfs" { print $2; }' /proc/mounts | sort -r)

Comment 6 Fedora Admin XMLRPC Client 2013-09-04 14:50:44 UTC
This package has changed ownership in the Fedora Package Database.  Reassigning to the new owner of this component.

Comment 7 Eric Sandeen 2017-08-16 15:27:52 UTC
Wow, blast from the past.  I really don't care about this bug anymore, if you want to just close it.  Actually I'll just do that.  Feel free to re-open if you care about it.  It's crazy to have bugs open for 8 years.

Comment 8 David Kaspar // Dee'Kej 2017-08-17 09:28:45 UTC
Hello Eric! :)

Sorry for pulling skeletons from the closet to the light again... :D I have started maintaining initscripts last year, so I'm keeping this BZ open, just to make sure later we no longe have this problem in Fedora. That's all. ;)

Comment 10 Eric Sandeen 2020-06-04 21:48:02 UTC
hah, 11 years later I guess I'll close this one.