]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hwclock: always set the kernel's timezone
authorKay Sievers <kay@vrfy.org>
Mon, 17 Sep 2012 14:41:13 +0000 (16:41 +0200)
committerKay Sievers <kay@vrfy.org>
Mon, 17 Sep 2012 14:56:26 +0000 (16:56 +0200)
Properly tell the kernel at bootup, and any later time zone changes,
the actual system time zone.

Things like the kernel's FAT filesystem driver needs the actual time
zone to calculate the proper local time to use for the on-disk time
stamps.

https://bugzilla.redhat.com/show_bug.cgi?id=802198

src/core/main.c
src/shared/hwclock.c
src/shared/hwclock.h
src/timedate/timedated.c

index 44c010cfbf817bc7485a414e40dbde7844507270..199383e6368e39b3f34355ab26f5087cb6ef72b3 100644 (file)
@@ -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);
index 9f8ab08e2bdd0589b9fd5a0d7446c713afbbe5dc..d9d5600ff34052db0bc03b5075a6e1ddcf24e71e 100644 (file)
@@ -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;
 
index 26d1b444e7cd598de1e80aa3a6db6a337bfae094..b2bdc78f0cd139868bf6f97ef674624898958697 100644 (file)
@@ -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);
 
index 7eed31c477e73a0670477cd5c71f061e8b608914..0ebece893fe135b5891d894cc9123ab2fc8a97a9 100644 (file)
@@ -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);