[arch-projects] hwclock adjust file

Tom Gundersen teg at jklm.no
Sun Jun 5 13:12:26 EDT 2011


[cc'ing arch-projects and Kurt Bosch as they might have opinions]

Context: I suggested to Dave that we should move
/var/lib/hwclock/adjfile to /etc (which is what upstream does).

Sorry for the verbosity, hwclock does this to me...

On Sun, Jun 5, 2011 at 5:21 PM, Dave Reisner <d at falconindy.com> wrote:
> Poked around at this, and apparently it's FHS that recommends putting
> the adjtime file in /var/lib/hwclock, instead of /etc:
>
> http://www.pathname.com/fhs/2.2/fhs-5.8.html

Hm, didn't know this. That said, I think we should (always) ignore FHS.

> In poking around, I noticed various bugs related to a readonly root
> which made writing to this file problematic. Fedora has gone back to
> using /etc as well.
>
> Seems to me like /var/lib/hwclock is the appropriate place for it.

I don't really have a "real" solution to this problem. It seems
hwclock is really, really messed up. That said, maybe I'm missing the
point. I'll explain the way I see it, and you tell me if i got it all
wrong.

Assumption:
 - We must never ever make system time go backwards.
 - We want to find the correct solution and push it upstream rather
than work around it in Arch.

UTC/LOCALTIME:

When the rtc device is instantiated by the kernel the system time is
set, assuming rtc is in UTC.

If it is not, then we must reset the time to the correct timezone
using "hwclock --systz" (we probably want to call this even if we are
in UTC as it tells the kernel what timezone we are in for the benefit
of fat filesystems (I know, wtf!?)).

I believe already here we have a problem, as there is a gap between
"system time not set" and "system time set correctly", where the time
might be several hours in the future. We should at least make this gap
as small as possible, and make sure that things like udev does not get
started in this gap.

This means that we must know very early whether we are in UTC or in
LOCALTIME, storing this information in /var makes it impossible (so we
work around it at the moment by having a redundant entry in rc.conf
and essentially ignoring the timezone info of adjtime, and upstream
work around it by having adjtime in /etc).

Another option, that I have considered in the past is to add a module
option to rtc-cmos, so you can simply do rtc-cmos.timezone=120 (for
CEST) or rtc-cmos.timezone=0 for UTC. However, that's ugly, as I don't
think it would be possible to pass it the real timezone, as that would
require the kernel to keep a copy of /usr/share/zoneinfo, rather we'd
have to pass the offset in minutes, and we would have to adjust this
when DST kicks in. That said, maybe there is a nice way to do this
that I'm not aware of, as I'm no kernel time/timezone expert.

DRIFT

This is the original purpose of adjtime, and I believe it belongs in
/var (maybe this was the situation when FHS was written ;-) ).

My understanding:

The rtc runs at a relatively constant frequency, however this
frequency is not very accurate. The system time on the other hand has
frequency which is both constant and accurate. By measuring how the
rtc and the system time drift, we are able to calculate the real
frequency of the rtc, and adjusting for this we are able to get a very
accurate time reading even when the system time has not been running
(computer off or sleeping).

This is useful if you want to keep a good time, but don't have a
network connection, so cannot use ntp.

To do this, we must be able to store somewhere the time when we last
adjusted the rtc (so we know how long it has been drifting). If we
want our system time to be adjust ed for drift at boot, we need to do
"hwclock --adjust; hwclock --hctosys". The call to --adjust needs to
save to a file what time it was done at (maybe this could be done with
some /run magic, but I don't think it would be pretty, and it would at
any rate require adjtime to be in /etc), and the call to --hctosys may
only be done very early in boot (otherwise time might go backwards).

I think the correct solution is to keep the drift information in /var,
and only call "hwclock --adjust" (without the --hctosys) after the
system is up and running (possibly just before shutdown/sleep), and
never call "hwclock --systohc" automatically (this is only to be done
when the system time is known to be correct, e.g. after setting the
time). This means that the system time will be a bit wrong, but the
errors will not accumulate (you are only off by the amount you drifted
after the last clean shutdown, which in a non-networked scenario
should be negligible, and a reboot will get you "perfect" time).

Note: if ntpd/dual-boot is happening, the adjustment should never be
done by hwclock, as we will not know the time since last --adjust, and
we will over-shoot the adjustment.


TL;DR:

I propose splitting adjtime in two (upstream), one for /var (drift)
and one for /etc (TZ), if this can be done in a clever way to not lose
any backwards compatibility.

Cheers,

Tom

PS

If no one points out any mistakes in what I wrote, I might continue
the work by Kurt Bosch, and simplify our hwclock handling further.


More information about the arch-projects mailing list