diff mbox

[V9,02/13] ntp: add ADJ_SETOFFSET mode bit

Message ID 60566a54842bcf5974d55ed39f387c32ff9cf5cb.1294917348.git.richard.cochran@omicron.at
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

Richard Cochran Jan. 13, 2011, 11:32 a.m. UTC
This patch adds a new mode bit into the timex structure. When set, the bit
instructs the kernel to add the given time value to the current time.

Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
 include/linux/timex.h |    3 ++-
 kernel/time/ntp.c     |   11 +++++++++++
 2 files changed, 13 insertions(+), 1 deletions(-)

Comments

Kuwahara,T. Jan. 13, 2011, 8:39 p.m. UTC | #1
On Thu, Jan 13, 2011 at 8:32 PM, Richard Cochran
<richardcochran@gmail.com> wrote:
> This patch adds a new mode bit into the timex structure. When set, the bit
> instructs the kernel to add the given time value to the current time.

The unix time is a nonlinear timescale and there's no way to predict
how many leap seconds will be inserted/deleted during the given time
interval.  So it is impossible to convert relative time to absolute
time and thus your patch is broken. (More specifically, the
timekeeping_inject_offset function is broken.)

My proposal: Limit the adjustable range of the offset so that leap
seconds will never occur more than once. (2147.5 seconds would be the
best choice. :-)
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
john stultz Jan. 13, 2011, 8:57 p.m. UTC | #2
On Fri, 2011-01-14 at 05:39 +0900, Kuwahara,T. wrote:
> My proposal: Limit the adjustable range of the offset so that leap
> seconds will never occur more than once. (2147.5 seconds would be the
> best choice. :-)

2147.5? That's ~36 minutes. 

While I think a limit could be a sensible compromise here. Leap seconds
are limited to every six months. So surely a limit of 86400 (one day),
or 2592000 (30 days) would be more reasonable.

thanks
-john


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
john stultz Jan. 13, 2011, 9:52 p.m. UTC | #3
On Thu, 2011-01-13 at 12:57 -0800, john stultz wrote:
> On Fri, 2011-01-14 at 05:39 +0900, Kuwahara,T. wrote:
> > My proposal: Limit the adjustable range of the offset so that leap
> > seconds will never occur more than once. (2147.5 seconds would be the
> > best choice. :-)
> 
> 2147.5? That's ~36 minutes. 
> 
> While I think a limit could be a sensible compromise here. Leap seconds
> are limited to every six months. So surely a limit of 86400 (one day),
> or 2592000 (30 days) would be more reasonable.

Actually. Thinking about this some more (and having to try to
rationalize it for Thomas), this doesn't really seem reasonable. If an
application wants to adjust the time, we can leave the responsibility to
userland to handle compensation for expected or historical leapseconds
if they care.

Since if you're adjusting the time, especially by a large amount, you're
not starting from the correct time value. So expecting the kernel to
incorperate historical or planned future leapseconds (outside of the
TIME_INS notification from NTP) is silly. 

Really, in Linux leapseconds do not really exist except for the moment
they occur. If a leapsecond occurs, then you set your time back to
before the leapsecond, it won't happen a second time. 

So I don't think we need to enforce a limit. The interface suggested
seems totally reasonable to me. I'm happy to hear arguments to the
contrary, but they really must be more convincing.

thanks
-john



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/include/linux/timex.h b/include/linux/timex.h
index 32d852f..800a2c8 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -73,7 +73,7 @@  struct timex {
 	long tolerance;		/* clock frequency tolerance (ppm)
 				 * (read only)
 				 */
-	struct timeval time;	/* (read only) */
+	struct timeval time;	/* (read only, except for ADJ_SETOFFSET) */
 	long tick;		/* (modified) usecs between clock ticks */
 
 	long ppsfreq;           /* pps frequency (scaled ppm) (ro) */
@@ -102,6 +102,7 @@  struct timex {
 #define ADJ_STATUS		0x0010	/* clock status */
 #define ADJ_TIMECONST		0x0020	/* pll time constant */
 #define ADJ_TAI			0x0080	/* set TAI offset */
+#define ADJ_SETOFFSET		0x0100  /* add 'time' to current time */
 #define ADJ_MICRO		0x1000	/* select microsecond resolution */
 #define ADJ_NANO		0x2000	/* select nanosecond resolution */
 #define ADJ_TICK		0x4000	/* tick value */
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index d232189..0c87858 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -482,6 +482,17 @@  int do_adjtimex(struct timex *txc)
 			hrtimer_cancel(&leap_timer);
 	}
 
+	if (txc->modes & ADJ_SETOFFSET) {
+		struct timespec delta;
+		if ((unsigned long)txc->time.tv_usec >= NSEC_PER_SEC)
+			return -EINVAL;
+		delta.tv_sec  = txc->time.tv_sec;
+		delta.tv_nsec = txc->time.tv_usec;
+		if (!(txc->modes & ADJ_NANO))
+			delta.tv_nsec *= 1000;
+		timekeeping_inject_offset(&delta);
+	}
+
 	getnstimeofday(&ts);
 
 	write_seqlock_irq(&xtime_lock);