[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@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:
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.