diff options
author | Kay Sievers <kay@vrfy.org> | 2014-07-27 00:11:08 +0200 |
---|---|---|
committer | Kay Sievers <kay@vrfy.org> | 2014-07-27 10:44:31 +0200 |
commit | c264aeab4b0e7b69f469e12e78d4a48b3ed7a66e (patch) | |
tree | a99191d8ebde57537e362f6053074609bf19d7cc /src/timesync | |
parent | c6a373a26348544d944b08bf0c5dea4f72f6980b (diff) |
core: only set the kernel's timezone when the RTC runs in local time
We can not reliably manage any notion of local time. Every daylight
saving time change or time zone change by traveling will make the
time jump, and the local time might jump backwards which creates
unsolvable problems with file timestamps.
We will no longer tell the kernel our local time zone and leave
everything set to UTC. This will effectively turn FAT timestamps
into UTC timestamps.
If and only if the machine is configured to read the RTC in local
time mode, the kernel's time zone will be configured, but
systemd-timesysnc will disable the kernel's system time to RTC
syncing. In this mode, the RTC will not be managed, and external
tools like Windows bootups are expected to manage the RTC's time.
https://bugs.freedesktop.org/show_bug.cgi?id=81538
Diffstat (limited to 'src/timesync')
-rw-r--r-- | src/timesync/timesyncd.c | 24 | ||||
-rw-r--r-- | src/timesync/timesyncd.h | 3 |
2 files changed, 22 insertions, 5 deletions
diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c index 732f5bf6c2..b80e03b349 100644 --- a/src/timesync/timesyncd.c +++ b/src/timesync/timesyncd.c @@ -386,9 +386,6 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) { /* * For small deltas, tell the kernel to gradually adjust the system * clock to the NTP time, larger deltas are just directly set. - * - * Clear STA_UNSYNC, it will enable the kernel's 11-minute mode, which - * syncs the system time periodically to the hardware clock. */ if (fabs(offset) < NTP_MAX_ADJUST) { tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR; @@ -399,7 +396,7 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) { tmx.esterror = 0; log_debug(" adjust (slew): %+.3f sec\n", offset); } else { - tmx.modes = ADJ_SETOFFSET | ADJ_NANO; + tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET; /* ADJ_NANO uses nanoseconds in the microseconds field */ tmx.time.tv_sec = (long)offset; @@ -415,6 +412,17 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) { log_debug(" adjust (jump): %+.3f sec\n", offset); } + /* + * An unset STA_UNSYNC will enable the kernel's 11-minute mode, + * which syncs the system time periodically to the RTC. + * + * In case the RTC runs in local time, never touch the RTC, + * we have no way to properly handle daylight saving changes and + * mobile devices moving between time zones. + */ + if (m->rtc_local_time) + tmx.status |= STA_UNSYNC; + switch (leap_sec) { case 1: tmx.status |= STA_INS; @@ -437,7 +445,7 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) { " constant : %li\n" " offset : %+.3f sec\n" " freq offset : %+li (%i ppm)\n", - tmx.status, tmx.status & STA_UNSYNC ? "" : "sync", + tmx.status, tmx.status & STA_UNSYNC ? "unsync" : "sync", tmx.time.tv_sec, (unsigned long long) (tmx.time.tv_usec / NSEC_PER_MSEC), tmx.constant, (double)tmx.offset / NSEC_PER_SEC, @@ -1218,6 +1226,12 @@ int main(int argc, char *argv[]) { goto out; } + if (clock_is_localtime() > 0) { + log_info("The system is configured to read the RTC time in the local time zone. " + "This mode can not be fully supported. All system time to RTC updates are disabled."); + m->rtc_local_time = true; + } + manager_add_server_string(m, NTP_SERVERS); manager_parse_config_file(m); diff --git a/src/timesync/timesyncd.h b/src/timesync/timesyncd.h index 52cca6d1ed..e723404d82 100644 --- a/src/timesync/timesyncd.h +++ b/src/timesync/timesyncd.h @@ -97,6 +97,9 @@ struct Manager { /* Retry connections */ sd_event_source *event_retry; + + /* RTC runs in local time, leave it alone */ + bool rtc_local_time; }; const struct ConfigPerfItem* timesyncd_gperf_lookup(const char *key, unsigned length); |