From 162c6a49b5f714b374f9e043381cdf7d71510073 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Wed, 27 Nov 2013 17:33:03 +0100 Subject: [PATCH] Add option to trim RTC automatically --- chrony.texi.in | 20 ++++++++++++++++++++ conf.c | 25 +++++++++++++++++++++++++ conf.h | 2 ++ rtc_linux.c | 27 +++++++++++++++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/chrony.texi.in b/chrony.texi.in index 8cf6e93..7714d9d 100644 --- a/chrony.texi.in +++ b/chrony.texi.in @@ -1157,6 +1157,7 @@ directives can occur in any order in the file. * port directive:: Set port to use for NTP packets * refclock directive:: Specify a reference clock * reselectdist directive:: Set improvement in distance needed to reselect a source +* rtcautotrim directive:: Specify threshold at which RTC is trimmed automatically * rtcdevice directive:: Specify name of enhanced RTC device (if not /dev/rtc) * rtcfile directive:: Specify the file where real-time clock data is stored * rtconutc directive:: Specify that the real time clock keeps UTC not local time @@ -2603,6 +2604,25 @@ The syntax is reselectdist @end example @c }}} +@c {{{ rtcautotrim +@node rtcautotrim directive +@subsection rtcautotrim +The @code{rtcautotrim} directive is used to keep the real time clock (RTC) +close to the system clock automatically. When the system clock is synchronized +and the estimated error between the two clocks is larger than the specified +threshold, @code{chronyd} will trim the RTC as if the @code{trimrtc} +(@pxref{trimrtc command}) command was issued. + +This directive is effective only with the @code{rtcfile} directive. + +An example of the use of this directive is + +@example +rtcautotrim 30 +@end example + +This would set the threshold error to 30 seconds. +@c }}} @c {{{ rtcdevice @node rtcdevice directive @subsection rtcdevice diff --git a/conf.c b/conf.c index 265cdb4..82eecd4 100644 --- a/conf.c +++ b/conf.c @@ -90,6 +90,7 @@ static void parse_pidfile(char *); static void parse_port(char *); static void parse_refclock(char *); static void parse_reselectdist(char *); +static void parse_rtcautotrim(char *); static void parse_rtcdevice(char *); static void parse_rtcfile(char *); static void parse_rtconutc(char *); @@ -158,6 +159,9 @@ static int rtc_sync = 0; static int make_step_limit = 0; static double make_step_threshold = 0.0; +/* Threshold for automatic RTC trimming */ +static double rtc_autotrim_threshold = 0.0; + /* Number of updates before offset checking, number of ignored updates before exiting and the maximum allowed offset */ static int max_offset_delay = -1; @@ -441,6 +445,8 @@ CNF_ReadFile(const char *filename) parse_refclock(p); } else if (!strcasecmp(command, "reselectdist")) { parse_reselectdist(p); + } else if (!strcasecmp(command, "rtcautotrim")) { + parse_rtcautotrim(p); } else if (!strcasecmp(command, "rtcdevice")) { parse_rtcdevice(p); } else if (!strcasecmp(command, "rtcfile")) { @@ -789,6 +795,17 @@ parse_keyfile(char *line) /* ================================================== */ +static void +parse_rtcautotrim(char *line) +{ + check_number_of_args(line, 1); + if (sscanf(line, "%lf", &rtc_autotrim_threshold) != 1) { + command_parse_error(); + } +} + +/* ================================================== */ + static void parse_rtcfile(char *line) { @@ -1586,6 +1603,14 @@ CNF_GetKeysFile(void) /* ================================================== */ +double +CNF_GetRtcAutotrim(void) +{ + return rtc_autotrim_threshold; +} + +/* ================================================== */ + char * CNF_GetRtcFile(void) { diff --git a/conf.h b/conf.h index d03406b..52491f9 100644 --- a/conf.h +++ b/conf.h @@ -99,4 +99,6 @@ extern char *CNF_GetUser(void); extern int CNF_GetMaxSamples(void); extern int CNF_GetMinSamples(void); +extern double CNF_GetRtcAutotrim(void); + #endif /* GOT_CONF_H */ diff --git a/rtc_linux.c b/rtc_linux.c index 85418a0..4d2ffb3 100644 --- a/rtc_linux.c +++ b/rtc_linux.c @@ -38,6 +38,7 @@ #include "local.h" #include "util.h" #include "sys_linux.h" +#include "reference.h" #include "regress.h" #include "rtc.h" #include "rtc_linux.h" @@ -123,6 +124,9 @@ static double coef_gain_rate; RTC data file once we have reacquired its offset after the step */ static double saved_coef_gain_rate; +/* Threshold for automatic RTC trimming in seconds, zero when disabled */ +static double autotrim_threshold; + /* Filename supplied by config file where RTC coefficients are stored. */ static char *coefs_file_name; @@ -375,6 +379,8 @@ setup_config(void) } else { rtc_on_utc = 0; } + + autotrim_threshold = CNF_GetRtcAutotrim(); } /* ================================================== */ @@ -686,6 +692,26 @@ handle_relock_after_trim(void) /* ================================================== */ +static void +maybe_autotrim(void) +{ + /* Trim only when in normal mode, the coefficients are fresh, the current + offset is above the threshold and the system clock is synchronized */ + + if (operating_mode != OM_NORMAL || !coefs_valid || n_samples_since_regression) + return; + + if (autotrim_threshold <= 0.0 || fabs(coef_seconds_fast) < autotrim_threshold) + return; + + if (REF_GetOurStratum() >= 16) + return; + + RTC_Linux_Trim(); +} + +/* ================================================== */ + static void process_reading(time_t rtc_time, struct timeval *system_time) { @@ -699,6 +725,7 @@ process_reading(time_t rtc_time, struct timeval *system_time) if (n_samples_since_regression >= N_SAMPLES_PER_REGRESSION) { run_regression(1, &coefs_valid, &coef_ref_time, &coef_seconds_fast, &coef_gain_rate); n_samples_since_regression = 0; + maybe_autotrim(); } break;