On 8 September 2012 15:33, Dave Reisner <d@falconindy.com> wrote:
One last bug about hwclock [1] is still outstanding, but I'm not able to reproduce it. I'm still unconvinced of whether it's a legit bug in hwclock or just something we need to fix in initscripts, but I've forwarded the bug onto the util-linux ML to see if I can get input from elsewhere.
Cheers, Dave
Falconindy, you're going to kill me. Today I realized that I unset HARDWARECLOCK in rc.conf yesterday, which made it look like it works due to the use of hwclock daemon. Instead the hwclock wasn't run during startup at all. So the problem is still here. This time, however, I have a fix for that. It works, although I'm not sure whether it's a correct fix. There's some strange problem with "hwclock --systz" which looks like it doesn't set the time zone correctly, but it can be fixed by using "hwclock --hctosys" instead (see attached patch). I just found out about the --debug switch to hwclock at it does print some interesting info (the output is at the end of this email). Note the "Calling settimeofday" output, especially the "tz.tz_minuteswest". This is completely utterly wrong according to "man 2 settimeofday": Under Linux there are some peculiar "warp clock" semantics associated with the settimeofday() system call if on the very first call (after booting) that has a non-NULL tz argument, the tv argument is NULL and the tz_minuteswest field is nonzero. (The tz_dsttime field should be zero for this case.) In such a case it is assumed that the CMOS clock is on local time, and that it has to be incremented by this amount to get UTC system time. No doubt it is a bad idea to use this feature. I have CMOS clock set to UTC. However, according to the documentation the hwclock causes system to think it uses local time. If I set tz_minuteswest in that call to zero manually, the error during mount disappears. However the "date" output is still incorrect. So I tried to change the settimeofday call according to the documentation. I other words, I forced tz_minuteswest to 0 in all calls in hwclock.c. And (surprisingly) it fixed this problem. To sum, what I think happens here: prerequisites: * CMOS (hardware) time set to UTC * Time zone different from UTC, in my case its "Europe/Prague" (UTC + 2 hours) what is the problem: 1. hwclock calls settimeofday with tz_minuteswest = -120 2. due to tz_minuteswest being non-zero, kernel thinks the hardware clock is in local time and thus it sets its clock to UTC - 2 hours 3. a) the wrong kernel clock causes the "Superblock last write time is in the future." warnings. b) and because kernel clock is UTC - 2, date shows "kernel time + 2" which resuts in showing the time for UTC-2+2, which is equal to UTC time. what should happen: 1. hwclock calls settimeofday with tz_minuteswest = 0 2. kernel knows the hardware clock is in UTC, and it sets its clock appropriately (ie to UTC) 3. now that the kernel clock is in UTC, date shows correctly UTC+2, ie. localtime Broken --------- # hwclock --utc --noadjfile Using /dev interface to clock. Assuming hardware clock is kept in UTC time. Waiting for clock tick... ...got clock tick Time read from Hardware Clock: 2012/09/10 06:19:46 Hw clock time : 2012/09/10 06:19:46 = 1347257986 seconds since 1969 Mon Sep 10 08:19:46 2012 -0.234800 seconds # date output Mon Sep 10 08:19:45 CEST 2012 # hwclock --systz --debug hwclock from util-linux 2.22 Last drift adjustment done at 1347212233 seconds after 1969 Last calibration done at 1347212233 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Current system time: 1347257985 = 2012/09/10 06:19:45 Calling settimeofday: UTC: 2012/09/10 06:19:45 tv.tv_sec = 1347257985, tv.tv_usec = 784261 tz.tz_minuteswest = -120 # date output Mon Sep 10 06:19:45 CEST 2012 Working ---------- #hwclock --utc --noadjfile Using /dev interface to clock. Assuming hardware clock is kept in UTC time. Waiting for clock tick... ...got clock tick Time read from Hardware Clock: 2012/09/10 06:22:24 Hw clock time : 2012/09/10 06:22:24 = 1347258144 seconds since 1969 Mon Sep 10 08:22:24 2012 -0.453554 seconds # date output Mon Sep 10 08:22:23 CEST 2012 # hwclock --hctosys --debug hwclock from util-linux 2.22 Using /dev interface to clock. Last drift adjustment done at 1347212233 seconds after 1969 Last calibration done at 1347212233 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick... ...got clock tick Time read from Hardware Clock: 2012/09/10 06:22:25 Hw clock time : 2012/09/10 06:22:25 = 1347258145 seconds since 1969 Calling settimeofday: tv.tv_sec = 1347258145, tv.tv_usec = 0 tz.tz_minuteswest = -120 # date Mon Sep 10 08:22:25 CEST 2012 /me hides Lukas