[PATCH 4/5] ntp: Do leapsecond adjustment in adjtimex read path

From: John Stultz
Date: Thu Jun 11 2015 - 18:56:14 EST


Since the leapsecond is applied at tick-time, this
means there is a small window of time at the start
of a leap-second where we cross into the next second
before applying the leap.

This patch modified adjtimex so that the leap-second
is applied on the second edge. Providing more correct
leapsecond behavior.

This does make it so that adjtimex()'s returned time
values can be inconsistent with time values read from
gettimeofday() or clock_gettime(CLOCK_REALTIME,...)
for a brief period of one tick at the leapsecond.
However, those other interfaces do not provide the
TIME_OOP time_state return that adjtimex() provides, which
allows the leapsecond to be properly represented. They
instead only see a time discontinuity, and cannot tell the
first 23:59:59 from the repeated 23:59:59 leap second.

This seems like a reasonable tradeoff given clock_gettime()
/ gettimeofday() cannot properly represent a leapsecond,
and users likely care more about performance, while folks
who are using adjtimex() more likely care about leap-second
correctness.

Cc: Prarit Bhargava <prarit@xxxxxxxxxx>
Cc: Daniel Bristot de Oliveira <bristot@xxxxxxxxxx>
Cc: Richard Cochran <richardcochran@xxxxxxxxx>
Cc: Jan Kara <jack@xxxxxxx>
Cc: Jiri Bohac <jbohac@xxxxxxx>
Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxxxxx>
Signed-off-by: John Stultz <john.stultz@xxxxxxxxxx>
---
kernel/time/ntp.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 033743e..fb4d98c 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -740,6 +740,24 @@ int __do_adjtimex(struct timex *txc, struct timespec64 *ts, s32 *time_tai)
if (!(time_status & STA_NANO))
txc->time.tv_usec /= NSEC_PER_USEC;

+ /* Handle leapsec adjustments */
+ if (unlikely(ts->tv_sec >= ntp_next_leap_sec)) {
+ if ((time_state == TIME_INS) && (time_status & STA_INS)) {
+ result = TIME_OOP;
+ txc->tai++;
+ txc->time.tv_sec--;
+ }
+ if ((time_state == TIME_DEL) && (time_status & STA_DEL)) {
+ result = TIME_WAIT;
+ txc->tai--;
+ txc->time.tv_sec++;
+ }
+ if ((time_state == TIME_OOP) &&
+ (ts->tv_sec == ntp_next_leap_sec)) {
+ result = TIME_WAIT;
+ }
+ }
+
return result;
}

--
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/