summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/main.c15
-rw-r--r--src/shared/hwclock.c9
-rw-r--r--src/shared/hwclock.h4
-rw-r--r--src/timedate/timedated.c13
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);