122 lines
6.0 KiB
Diff
122 lines
6.0 KiB
Diff
|
Based on c264aeab4b0e7b69f469e12e78d4a48b3ed7a66e Mon Sep 17 00:00:00 2001
|
||
|
From: Kay Sievers <kay@vrfy.org>
|
||
|
Date: Sun, 27 Jul 2014 00:11:08 +0200
|
||
|
Subject: [PATCH] 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
|
||
|
---
|
||
|
src/core/main.c | 23 +++++++++++++++--------
|
||
|
src/shared/hwclock.c | 15 ++++++++-------
|
||
|
src/shared/hwclock.h | 2 +-
|
||
|
3 files changed, 24 insertions(+), 16 deletions(-)
|
||
|
|
||
|
--- src/core/main.c
|
||
|
+++ src/core/main.c 2014-07-28 09:59:35.778235585 +0000
|
||
|
@@ -1349,7 +1349,14 @@ int main(int argc, char *argv[]) {
|
||
|
if (hwclock_is_localtime() > 0) {
|
||
|
int min;
|
||
|
|
||
|
- /* The first-time call to settimeofday() does a time warp in the kernel */
|
||
|
+ /*
|
||
|
+ * The very first call of settimeofday() also does a time warp in the kernel.
|
||
|
+ *
|
||
|
+ * In the rtc-in-local time mode, we set the kernel's timezone, and rely on
|
||
|
+ * external tools to take care of maintaining the RTC and do all adjustments.
|
||
|
+ * This matches the behavior of Windows, which leaves the RTC alone if the
|
||
|
+ * registry tells that the RTC runs in UTC.
|
||
|
+ */
|
||
|
r = hwclock_set_timezone(&min);
|
||
|
if (r < 0)
|
||
|
log_error("Failed to apply local time delta, ignoring: %s", strerror(-r));
|
||
|
@@ -1357,19 +1364,19 @@ int main(int argc, char *argv[]) {
|
||
|
log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
|
||
|
} else if (!in_initrd()) {
|
||
|
/*
|
||
|
- * Do dummy first-time call to seal the kernel's time warp magic
|
||
|
+ * Do a dummy very first call to seal the kernel's time warp magic.
|
||
|
*
|
||
|
* Do not call this this from inside the initrd. The initrd might not
|
||
|
* carry /etc/adjtime with LOCAL, but the real system could be set up
|
||
|
* that way. In such case, we need to delay the time-warp or the sealing
|
||
|
* until we reach the real system.
|
||
|
+ *
|
||
|
+ * Do no set the kernel's timezone. The concept of local time cannot
|
||
|
+ * be supported reliably, the time will jump or be incorrect at every daylight
|
||
|
+ * saving time change. All kernel local time concepts will be treated
|
||
|
+ * as UTC that way.
|
||
|
*/
|
||
|
- hwclock_reset_timezone();
|
||
|
-
|
||
|
- /* Tell the kernel our timezone */
|
||
|
- r = hwclock_set_timezone(NULL);
|
||
|
- if (r < 0)
|
||
|
- log_error("Failed to set the kernel's timezone, ignoring: %s", strerror(-r));
|
||
|
+ hwclock_reset_timewarp();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
--- src/shared/hwclock.c
|
||
|
+++ src/shared/hwclock.c 2014-07-28 09:59:12.914235566 +0000
|
||
|
@@ -124,9 +124,10 @@ int hwclock_set_timezone(int *min) {
|
||
|
tz.tz_dsttime = 0; /* DST_NONE*/
|
||
|
|
||
|
/*
|
||
|
- * If the hardware clock does not run in UTC, but in local time:
|
||
|
- * The very first time we set the kernel's timezone, it will warp
|
||
|
- * the clock so that it runs in UTC instead of local time.
|
||
|
+ * If the RTC does not run in UTC but in local time, the very first
|
||
|
+ * call to settimeofday() will set the kernel's timezone and will warp the
|
||
|
+ * system clock, so that it runs in UTC instead of the local time we
|
||
|
+ * have read from the RTC.
|
||
|
*/
|
||
|
if (settimeofday(tv_null, &tz) < 0)
|
||
|
return -errno;
|
||
|
@@ -135,7 +136,7 @@ int hwclock_set_timezone(int *min) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
-int hwclock_reset_timezone(void) {
|
||
|
+int hwclock_reset_timewarp(void) {
|
||
|
const struct timeval *tv_null = NULL;
|
||
|
struct timezone tz;
|
||
|
|
||
|
@@ -143,9 +144,9 @@ int hwclock_reset_timezone(void) {
|
||
|
tz.tz_dsttime = 0; /* DST_NONE*/
|
||
|
|
||
|
/*
|
||
|
- * The very first time we set the kernel's timezone, it will warp
|
||
|
- * the clock. Do a dummy call here, so the time warping is sealed
|
||
|
- * and we set only the timezone with next call.
|
||
|
+ * The very first call to settimeofday() does time warp magic. Do a
|
||
|
+ * dummy call here, so the time warping is sealed and all later calls
|
||
|
+ * behave as expected.
|
||
|
*/
|
||
|
if (settimeofday(tv_null, &tz) < 0)
|
||
|
return -errno;
|
||
|
--- src/shared/hwclock.h
|
||
|
+++ src/shared/hwclock.h 2014-07-28 09:59:25.034736002 +0000
|
||
|
@@ -23,6 +23,6 @@
|
||
|
|
||
|
int hwclock_is_localtime(void);
|
||
|
int hwclock_set_timezone(int *min);
|
||
|
-int hwclock_reset_timezone(void);
|
||
|
+int hwclock_reset_timewarp(void);
|
||
|
int hwclock_get_time(struct tm *tm);
|
||
|
int hwclock_set_time(const struct tm *tm);
|