On Sun, Feb 26, 2017 at 07:56:06PM +0100, Andreas Henriksson wrote:
> > But this doesn't work if the driver for the RTC is compiled as a module
> > or if the kernel was compiled with CONFIG_RTC_HCTOSYS disabled.
> 
> Second (easy) case first, if CONFIG_RTC_HCTOSYS is disabled then
> I think we should not second guess this at all. period.

If all RTC drivers are built as modules, there's no point in enabling
CONFIG_RTC_HCTOSYS as it just bloats the kernel with code that's never
executed.

Hence disabling CONFIG_RTC_HCTOSYS cannot be interpreted as an unambiguous
policy decision that the system time should never be set from an RTC.


> For the module part, I'd consider this a problem on the kernel side
> primarily. If this problem won't/can't be fixed in the kernel itself
> then I'd rather see the entire kernel mechanism deprecated and
> a proper userspace component designed to handle it all.

As said, the kernel's rtc_hctosys() is a late_initcall, i.e. it is
executed prior to loading modules.  Indeed it would be better if
the kernel would execute rtc_hctosys() once an RTC becomes available.
Regardless, user space should respond to this failure gracefully.

Currently if systemd is used, the system time is never set from the
RTC.  Worse, the kernel periodically syncs the system time *back* to
the RTC.  So even if the user sets both the system time and hwclock
manually, both will be reset to the epoch on the next reboot.  It's
as if no RTC was present and that behaviour is almost never what the
user wants.

Googling for "systemd" "hwclock-set" gets 1230 results, the vast majority
are recipes to remove the systemd condition from hwclock-set, cargo-culted
over and over again for almost 6 years.  This awfulness needs to stop.


> A better approach would be for the RPi solutions to ship (a package
> containing) a separate rules file and a script that (in best of
> worlds detects it's being run on the targeted hardware) and does
> what's needed. No hacking of util-linux packaged files needed
> and no unwanted overwrites.

This isn't limited to the Raspberry Pi, it's just the #1 example
because that's what most of the recipes you can find with Google
pertain to.


> Not a total fan of your patch. Consider the case where a system has
> more than one RTC. Consider specifically when CONFIG_RTC_HCTOSYS_DEVICE
> is set to rtc1. With your patch applied that would mean that we'd
> start running:
> /sbin/hwclock --rtc=rtc0 --hctosys
> (without first running: /sbin/hwclock --rtc=rtc0 --systz)
> right?
> 
> That seems bad.
> 
> (That the current udev rule only targets rtc0 is another thing I'd
> consider a bug. But that might be another discussion.)

Okay, let's define a policy first.  How about:

(1) Users can set HWCLOCKACCESS=no in /etc/default/hwclock to prohibit
    setting the system time or time zone from any RTC.  (The parameter
    is already defined in the config file, but it's not honored by
    hwclock-set.)

(2) Users can set HCTOSYS_DEVICE in /etc/default/hwclock to constrain
    setting the system time or time zone to a specific RTC.  (Same as
    above, parameter is already defined but not honored by hwclock-set.
    This will also fix #785445.)  If this parameter is not set,
    hwclock-set will pick the first RTC that becomes available.

(3) If the kernel has already set the system time from *any* hwclock,
    we don't set it once more in hwclock-set.  (We only adjust the
    timezone.)

(4) If systemd is present, we don't adjust the timezone once more in
    hwclock-set.

Does this work for you?  I've already coded the above up in my local repo
but haven't tested it yet, pending your response.  (Tentative patch is
attached.)

Thanks,

Lukas
diff --git a/debian/hwclock-set b/debian/hwclock-set
index eacf948..516563c 100755
--- a/debian/hwclock-set
+++ b/debian/hwclock-set
@@ -4,10 +4,6 @@
 
 dev=$1
 
-if [ -e /run/systemd/system ] ; then
-    exit 0
-fi
-
 if [ -e /run/udev/hwclock-set ]; then
     exit 0
 fi
@@ -20,17 +16,33 @@ fi
 BADYEAR=no
 HWCLOCKACCESS=yes
 HWCLOCKPARS=
-HCTOSYS_DEVICE=rtc0
+HCTOSYS_DEVICE=
 if [ -f /etc/default/hwclock ] ; then
     . /etc/default/hwclock
 fi
 
+if [ $HWCLOCKACCESS != yes -o \
+     ( -n $HCTOSYS_DEVICE -a $HCTOSYS_DEVICE != $2 ) ]
+    exit 0
+fi
+
+# If the kernel has already set the system time from the hwclock,
+# we only adjust the timezone
+cat /sys/class/rtc/*/hctosys 2>/dev/null | while read kernel_hctosys ; do
+    if [ $kernel_hctosys = 1 ] ; then
+	break
+    fi
+done
+
 if [ yes = "$BADYEAR" ] ; then
-    /sbin/hwclock --rtc=$dev --systz --badyear
-    /sbin/hwclock --rtc=$dev --hctosys --badyear
-else
-    /sbin/hwclock --rtc=$dev --systz
-    /sbin/hwclock --rtc=$dev --hctosys
+    badyear="--badyear"
+fi
+
+if [ ! -e /run/systemd/system ] ; then
+    /sbin/hwclock --rtc=$dev --systz $badyear
+fi
+if [ $kernel_hctosys != 1 ] ; then
+    /sbin/hwclock --rtc=$dev --hctosys $badyear
 fi
 
 # Note 'touch' may not be available in initramfs
diff --git a/debian/hwclock.rules b/debian/hwclock.rules
index 972e4aa..8584deb 100644
--- a/debian/hwclock.rules
+++ b/debian/hwclock.rules
@@ -1,4 +1,4 @@
 # Set the System Time from the Hardware Clock and set the kernel's timezone
 # value to the local timezone when the kernel clock module is loaded.
 
-KERNEL=="rtc0", RUN+="/lib/udev/hwclock-set $root/$name"
+KERNEL=="rtc*", RUN+="/lib/udev/hwclock-set $root/$name $kernel"

Reply via email to