[systemd-devel] [PATCH] systemd: Fix wrong timestamps in rtc-in-local time mode.
Chunhui He
hchunhui at mail.ustc.edu.cn
Wed Nov 19 02:20:51 PST 2014
systemd generates some timestamps before the very first call of settimeofday().
When we are in rtc-in-local time mode, these timestamps are wrong.
Affected timestamps are:
Kernel, InitRD, Userspace, SecurityStart, SecurityFinish
In this patch, adjustments are applied after the very first call.
Before applying this patch:
$ 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)
...
$ systemctl show
...
FirmwareTimestampMonotonic=0
LoaderTimestampMonotonic=0
KernelTimestamp=Wed 2014-11-19 23:39:10 CST
KernelTimestampMonotonic=0
InitRDTimestampMonotonic=0
UserspaceTimestamp=Wed 2014-11-19 23:39:13 CST
UserspaceTimestampMonotonic=2707714
FinishTimestamp=Wed 2014-11-19 15:39:25 CST
FinishTimestampMonotonic=14463839
SecurityStartTimestamp=Wed 2014-11-19 23:39:13 CST
SecurityStartTimestampMonotonic=2710030
SecurityFinishTimestamp=Wed 2014-11-19 23:39:13 CST
SecurityFinishTimestampMonotonic=2721209
...
After applying this patch:
$ last
hch tty1 Wed Nov 19 15:43 still logged in
reboot system boot 3.16.0-4-amd64 Wed Nov 19 15:43 - 15:43 (00:00)
...
$ systemctl show
...
FirmwareTimestampMonotonic=0
LoaderTimestampMonotonic=0
KernelTimestamp=Wed 2014-11-19 15:42:57 CST
KernelTimestampMonotonic=0
InitRDTimestampMonotonic=0
UserspaceTimestamp=Wed 2014-11-19 15:43:00 CST
UserspaceTimestampMonotonic=2862393
FinishTimestamp=Wed 2014-11-19 15:43:13 CST
FinishTimestampMonotonic=15647941
SecurityStartTimestamp=Wed 2014-11-19 15:43:00 CST
SecurityStartTimestampMonotonic=2864772
SecurityFinishTimestamp=Wed 2014-11-19 15:43:00 CST
SecurityFinishTimestampMonotonic=2875854
...
---
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 64acdf7..86af1e5 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1318,8 +1318,17 @@ int main(int argc, char *argv[]) {
r = clock_set_timezone(&min);
if (r < 0)
log_error("Failed to apply local time delta, ignoring: %s", strerror(-r));
- 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
More information about the systemd-devel
mailing list