From: Juergen Perlinger Date: Sun, 29 Nov 2020 09:41:07 +0000 (+0100) Subject: [Bug 3699] Problems handling drift file and restoring previous drifts - command line options override config statements where applicable - make initial frequency settings idempotent and reversible - make sure kernel PLL gets a revovered drift componsation bk: 5fc36cb3F2W6QL8Of1bpmb77G6JTyA --- diff --git a/include/ntp.h b/include/ntp.h index 8e0ea2b20..c037f5986 100644 --- a/include/ntp.h +++ b/include/ntp.h @@ -759,6 +759,7 @@ struct pkt { #define LOOP_CODEC 13 /* set audio codec frequency */ #define LOOP_LEAP 14 /* insert leap after second 23:59 */ #define LOOP_TICK 15 /* sim. low precision clock */ +#define LOOP_NOFREQ 16 /* undo a previos LOOP_FREQ */ /* * Configuration items for the stats printer diff --git a/ntpd/cmd_args.c b/ntpd/cmd_args.c index adb4a606b..aa461cb4d 100644 --- a/ntpd/cmd_args.c +++ b/ntpd/cmd_args.c @@ -71,7 +71,7 @@ getCmdOpts( } if (HAVE_OPT( DRIFTFILE )) - stats_config(STATS_FREQ_FILE, OPT_ARG( DRIFTFILE ), 0); + stats_config(STATS_FREQ_FILE, OPT_ARG( DRIFTFILE ), 1); if (HAVE_OPT( PANICGATE )) allow_panic = TRUE; @@ -90,7 +90,7 @@ getCmdOpts( getauthkeys(OPT_ARG( KEYFILE )); if (HAVE_OPT( PIDFILE )) - stats_config(STATS_PID_FILE, OPT_ARG( PIDFILE ), 0); + stats_config(STATS_PID_FILE, OPT_ARG( PIDFILE ), 1); if (HAVE_OPT( QUIT )) mode_ntpdate = TRUE; @@ -110,7 +110,7 @@ getCmdOpts( } while (0); if (HAVE_OPT( STATSDIR )) - stats_config(STATS_STATSDIR, OPT_ARG( STATSDIR ), 0); + stats_config(STATS_STATSDIR, OPT_ARG( STATSDIR ), 1); if (HAVE_OPT( TRUSTEDKEY )) { int ct = STACKCT_OPT( TRUSTEDKEY ); diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c index cdc391c1b..f5ea35630 100644 --- a/ntpd/ntp_config.c +++ b/ntpd/ntp_config.c @@ -3991,11 +3991,9 @@ config_vars( break; case T_Driftfile: - if ('\0' == curr_var->value.s[0]) { - stats_drift_file = 0; + if ('\0' == curr_var->value.s[0]) msyslog(LOG_INFO, "config: driftfile disabled"); - } else - stats_config(STATS_FREQ_FILE, curr_var->value.s, 0); + stats_config(STATS_FREQ_FILE, curr_var->value.s, 0); break; case T_Dscp: diff --git a/ntpd/ntp_loopfilter.c b/ntpd/ntp_loopfilter.c index b7a742bbd..0499c3633 100644 --- a/ntpd/ntp_loopfilter.c +++ b/ntpd/ntp_loopfilter.c @@ -1117,6 +1117,11 @@ start_kern_loop(void) * unconditionally set to sys_poll, whereas elsewhere is is * modified depending on nanosecond vs. microsecond kernel? */ + /*[bug 3699] make sure kernel PLL sees our initial drift compensation */ + if (freq_set) { + ntv.modes |= MOD_FREQUENCY; + ntv.freq = DTOFREQ(drift_comp); + } #ifdef SIGSYS /* * Use sigsetjmp() to save state and then call ntp_adjtime(); if @@ -1314,7 +1319,12 @@ loop_config( case LOOP_FREQ: /* initial frequency (freq) */ init_drift_comp = freq; - freq_set++; + freq_set = 1; + break; + + case LOOP_NOFREQ: /* remove any initial drift comp spec */ + init_drift_comp = 0; + freq_set = 0; break; case LOOP_HUFFPUFF: /* huff-n'-puff length (huffpuff) */ diff --git a/ntpd/ntp_util.c b/ntpd/ntp_util.c index 11ca62017..8b5755406 100644 --- a/ntpd/ntp_util.c +++ b/ntpd/ntp_util.c @@ -64,6 +64,15 @@ static char *stats_temp_file; /* temp frequency file name */ static double wander_resid; /* last frequency update */ double wander_threshold = 1e-7; /* initial frequency threshold */ +/* For things where command line has precedence, we have + * to remember we've already seen that. These options have to be + * applied only once... + */ +#define CMDARG_FREQ_FILE 0x01 +#define CMDARG_PID_FILE 0x02 +#define CMDARG_STATSDIR 0x04 +static unsigned int cmdargs_seen = 0; + /* * Statistics file stuff */ @@ -397,24 +406,47 @@ stats_config( * Open and read frequency file. */ case STATS_FREQ_FILE: + if (!optflag && (cmdargs_seen & CMDARG_FREQ_FILE)) + break; + if (optflag) + cmdargs_seen |= CMDARG_FREQ_FILE; + if (!value || (len = strlen(value)) == 0) + { + free(stats_drift_file); + free(stats_temp_file); + stats_drift_file = stats_temp_file = NULL; + } + else + { + stats_drift_file = erealloc(stats_drift_file, len + 1); + stats_temp_file = erealloc(stats_temp_file, + len + sizeof(".TEMP")); + memcpy(stats_drift_file, value, (size_t)(len+1)); + memcpy(stats_temp_file, value, (size_t)len); + memcpy(stats_temp_file + len, temp_ext, sizeof(temp_ext)); + } + + if (NULL == stats_drift_file) { + loop_config(LOOP_NOFREQ, 0.0); + prev_drift_comp = 0.0; break; - - stats_drift_file = erealloc(stats_drift_file, len + 1); - stats_temp_file = erealloc(stats_temp_file, - len + sizeof(".TEMP")); - memcpy(stats_drift_file, value, (size_t)(len+1)); - memcpy(stats_temp_file, value, (size_t)len); - memcpy(stats_temp_file + len, temp_ext, sizeof(temp_ext)); + } /* * Open drift file and read frequency. If the file is * missing or contains errors, tell the loop to reset. */ - if ((fp = fopen(stats_drift_file, "r")) == NULL) - break; + if ((fp = fopen(stats_drift_file, "r")) == NULL) { + if (errno != ENOENT) + msyslog(LOG_WARNING, + "cannot read frequency file %s: %s", + stats_drift_file, strerror(errno)); + break; + } if (fscanf(fp, "%lf", &old_drift) != 1) { + msyslog(LOG_ERR, "format error frequency file %s", stats_drift_file); @@ -425,12 +457,19 @@ stats_config( fclose(fp); loop_config(LOOP_FREQ, old_drift); prev_drift_comp = drift_comp; + msyslog(LOG_INFO, + "initial drift restored to %f", + old_drift); break; /* * Specify statistics directory. */ case STATS_STATSDIR: + if (!optflag && (cmdargs_seen & CMDARG_STATSDIR)) + break; + if (optflag) + cmdargs_seen |= CMDARG_STATSDIR; /* - 1 since value may be missing the DIR_SEP. */ if (strlen(value) >= sizeof(statsdir) - 1) { @@ -463,6 +502,11 @@ stats_config( * Open pid file. */ case STATS_PID_FILE: + if (!optflag && (cmdargs_seen & CMDARG_PID_FILE)) + break; + if (optflag) + cmdargs_seen |= CMDARG_PID_FILE; + if ((fp = fopen(value, "w")) == NULL) { msyslog(LOG_ERR, "pid file %s: %m", value);