diff options
-rw-r--r-- | src/core/main.c | 15 | ||||
-rw-r--r-- | src/shared/hwclock.c | 9 | ||||
-rw-r--r-- | src/shared/hwclock.h | 4 | ||||
-rw-r--r-- | src/timedate/timedated.c | 13 |
4 files changed, 26 insertions, 15 deletions
diff --git a/src/core/main.c b/src/core/main.c index 44c010cfbf..199383e636 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1319,17 +1319,26 @@ int main(int argc, char *argv[]) { if (label_init(NULL) < 0) goto finish; - if (!skip_setup) + if (!skip_setup) { if (hwclock_is_localtime() > 0) { int min; - r = hwclock_apply_localtime_delta(&min); + /* The first-time call to settimeofday() does a time warp in the kernel */ + r = hwclock_set_timezone(&min); if (r < 0) log_error("Failed to apply local time delta, ignoring: %s", strerror(-r)); else log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min); - } + } else { + /* Do dummy first-time call to seal the kernel's time warp magic */ + hwclock_reset_timezone(); + /* Tell the kernel our time zone */ + r = hwclock_set_timezone(NULL); + if (r < 0) + log_error("Failed to set the kernel's time zone, ignoring: %s", strerror(-r)); + } + } } else { arg_running_as = MANAGER_USER; log_set_target(LOG_TARGET_AUTO); diff --git a/src/shared/hwclock.c b/src/shared/hwclock.c index 9f8ab08e2b..d9d5600ff3 100644 --- a/src/shared/hwclock.c +++ b/src/shared/hwclock.c @@ -188,7 +188,7 @@ int hwclock_is_localtime(void) { return local; } -int hwclock_apply_localtime_delta(int *min) { +int hwclock_set_timezone(int *min) { const struct timeval *tv_null = NULL; struct timespec ts; struct tm *tm; @@ -214,13 +214,18 @@ int hwclock_apply_localtime_delta(int *min) { return 0; } -int hwclock_reset_localtime_delta(void) { +int hwclock_reset_timezone(void) { const struct timeval *tv_null = NULL; struct timezone tz; tz.tz_minuteswest = 0; 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 time zone with next call. + */ if (settimeofday(tv_null, &tz) < 0) return -errno; diff --git a/src/shared/hwclock.h b/src/shared/hwclock.h index 26d1b444e7..b2bdc78f0c 100644 --- a/src/shared/hwclock.h +++ b/src/shared/hwclock.h @@ -23,8 +23,8 @@ ***/ int hwclock_is_localtime(void); -int hwclock_apply_localtime_delta(int *min); -int hwclock_reset_localtime_delta(void); +int hwclock_set_timezone(int *min); +int hwclock_reset_timezone(void); int hwclock_get_time(struct tm *tm); int hwclock_set_time(const struct tm *tm); diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 7eed31c477..0ebece893f 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -696,13 +696,13 @@ static DBusHandlerResult timedate_message_handler( return bus_send_error_reply(connection, message, NULL, r); } + /* 2. Tell the kernel our time zone */ + hwclock_set_timezone(NULL); + if (tz.local_rtc) { struct timespec ts; struct tm *tm; - /* 2. Teach kernel new timezone */ - hwclock_apply_localtime_delta(NULL); - /* 3. Sync RTC from system clock, with the new delta */ assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); assert_se(tm = localtime(&ts.tv_sec)); @@ -753,11 +753,8 @@ static DBusHandlerResult timedate_message_handler( return bus_send_error_reply(connection, message, NULL, r); } - /* 2. Teach kernel new timezone */ - if (tz.local_rtc) - hwclock_apply_localtime_delta(NULL); - else - hwclock_reset_localtime_delta(); + /* 2. Tell the kernel our time zone */ + hwclock_set_timezone(NULL); /* 3. Synchronize clocks */ assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); |