Hi all,

When the system is configured to read the RTC time in the local time zone,
some timestamps recorded by systemd are wrong.

This bug can be demonstrated as the following:
(RTC is in UTC+08:00)

$ last
hch      tty1                          Wed Nov 19 15:39   still logged in
reboot   system boot  3.16.0-4-amd64   Wed Nov 19 23:39 - 15:40  (-7:-59)  <-- 
here
...

$ systemctl show
...
FirmwareTimestampMonotonic=0
LoaderTimestampMonotonic=0
KernelTimestamp=Wed 2014-11-19 23:39:10 CST            <-- here
KernelTimestampMonotonic=0
InitRDTimestampMonotonic=0
UserspaceTimestamp=Wed 2014-11-19 23:39:13 CST
UserspaceTimestampMonotonic=2707714
FinishTimestamp=Wed 2014-11-19 15:39:25 CST            <-- here
FinishTimestampMonotonic=14463839
SecurityStartTimestamp=Wed 2014-11-19 23:39:13 CST
SecurityStartTimestampMonotonic=2710030
SecurityFinishTimestamp=Wed 2014-11-19 23:39:13 CST
SecurityFinishTimestampMonotonic=2721209
...

Note that timestamps are _inconsistent_.
(15:39 is correct, 23:39 is 15:39 +08:00)

I think this bug is introduced in commit 
c3a170f3d3358135a39ac6eafe66f18aef0bd67d
(systemd: record the timestamps as early as possible).

In that commit, in order to get more accurate timestamps,
some timestamps are recorded _before_ the very first call of
settimeofday(), which does a time warp in the kernel.

The following is my patch. It has been tested with the latest systemd in git 
repo.

Thanks!
Chunhui He

( I posted this patch last month:
http://lists.freedesktop.org/archives/systemd-devel/2014-November/025341.html )

---
 src/core/main.c        | 11 ++++++++++-
 src/shared/time-util.c | 14 ++++++++++++++
 src/shared/time-util.h |  1 +
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/src/core/main.c b/src/core/main.c
index 77980e3..d658867 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1312,8 +1312,17 @@ int main(int argc, char *argv[]) {
                                 r = clock_set_timezone(&min);
                                 if (r < 0)
                                         log_error_errno(r, "Failed to apply 
local time delta, ignoring: %m");
-                                else
+                                else {
                                         log_info("RTC configured in localtime, 
applying delta of %i minutes to system time.", min);
+
+                                        /* Fix timestamps generated before the 
very first call. */
+                                        dual_timestamp_warp(&kernel_timestamp, 
min);
+                                        
dual_timestamp_warp(&userspace_timestamp, min);
+                                        if(in_initrd())
+                                                
dual_timestamp_warp(&initrd_timestamp, min);
+                                        
dual_timestamp_warp(&security_start_timestamp, min);
+                                        
dual_timestamp_warp(&security_finish_timestamp, min);
+                                }
                         } else if (!in_initrd()) {
                                 /*
                                  * Do a dummy very first call to seal the 
kernel's time warp magic.
diff --git a/src/shared/time-util.c b/src/shared/time-util.c
index d3404af..f323835 100644
--- a/src/shared/time-util.c
+++ b/src/shared/time-util.c
@@ -88,6 +88,20 @@ dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp 
*ts, usec_t u) {
         return ts;
 }
 
+dual_timestamp* dual_timestamp_warp(dual_timestamp *ts, int min) {
+        usec_t d;
+        if (min >= 0) {
+                d = min * USEC_PER_MINUTE;
+                ts->realtime =
+                        ts->realtime > d ?
+                        ts->realtime - d : 0;
+        } else {
+                d = (-min) * USEC_PER_MINUTE;
+                ts->realtime = ts->realtime + d;
+        }
+        return ts;
+}
+
 usec_t timespec_load(const struct timespec *ts) {
         assert(ts);
 
diff --git a/src/shared/time-util.h b/src/shared/time-util.h
index b55a660..8c09963 100644
--- a/src/shared/time-util.h
+++ b/src/shared/time-util.h
@@ -74,6 +74,7 @@ usec_t now(clockid_t clock);
 dual_timestamp* dual_timestamp_get(dual_timestamp *ts);
 dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u);
 dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u);
+dual_timestamp* dual_timestamp_warp(dual_timestamp *ts, int min);
 
 static inline bool dual_timestamp_is_set(dual_timestamp *ts) {
         return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
-- 
2.1.3


_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to