From c44346096c2dca59a1eff39f60990a5570894103 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 9 Mar 2017 18:16:56 +0100 Subject: [PATCH] sys: add null driver Add a new clock driver that doesn't actually try to adjust the clock. It allows chronyd to run without the capability to adjust/set the system clock, e.g. in some containers. It can be enabled by the -x option. --- Makefile.in | 2 +- doc/chronyd.adoc | 7 +++ main.c | 6 +- sys.c | 16 +++++- sys.h | 2 +- sys_null.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++ sys_null.h | 34 ++++++++++++ 7 files changed, 202 insertions(+), 5 deletions(-) create mode 100644 sys_null.c create mode 100644 sys_null.h diff --git a/Makefile.in b/Makefile.in index 6f67b92..732d4b9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -37,7 +37,7 @@ HASH_OBJ = @HASH_OBJ@ OBJS = array.o cmdparse.o conf.o local.o logging.o main.o memory.o \ reference.o regress.o rtc.o sched.o sources.o sourcestats.o stubs.o \ - sys.o smooth.o tempcomp.o util.o $(HASH_OBJ) + smooth.o sys.o sys_null.o tempcomp.o util.o $(HASH_OBJ) EXTRA_OBJS=@EXTRA_OBJECTS@ diff --git a/doc/chronyd.adoc b/doc/chronyd.adoc index 9cb8eff..2ae5b17 100644 --- a/doc/chronyd.adoc +++ b/doc/chronyd.adoc @@ -151,6 +151,13 @@ support this option. This option will lock *chronyd* into RAM so that it will never be paged out. This mode is only supported on Linux. +*-x*:: +This option disables the control of the system clock. *chronyd* will not make +any adjustments of the clock, but it will still track its offset and frequency +relative to the estimated true time, and be able to operate as an NTP server. +This allows *chronyd* to run without the capability to adjust or set the system +clock (e.g. in some containers). + *-v*:: With this option *chronyd* will print version number to the terminal and exit. diff --git a/main.c b/main.c index 21c89be..be99f0d 100644 --- a/main.c +++ b/main.c @@ -376,7 +376,7 @@ int main int do_init_rtc = 0, restarted = 0, timeout = 0; int other_pid; int scfilter_level = 0, lock_memory = 0, sched_priority = 0; - int system_log = 1; + int clock_control = 1, system_log = 1; int config_args = 0; do_platform_checks(); @@ -435,6 +435,8 @@ int main ++argv, --argc; if (argc == 0 || sscanf(*argv, "%d", &timeout) != 1 || timeout <= 0) LOG_FATAL("Bad timeout"); + } else if (!strcmp("-x", *argv)) { + clock_control = 0; } else if (!strcmp("-4", *argv)) { address_family = IPADDR_INET4; } else if (!strcmp("-6", *argv)) { @@ -499,7 +501,7 @@ int main PRV_Initialise(); LCL_Initialise(); SCH_Initialise(); - SYS_Initialise(); + SYS_Initialise(clock_control); RTC_Initialise(do_init_rtc); SRC_Initialise(); RCL_Initialise(); diff --git a/sys.c b/sys.c index f27170d..5b56aae 100644 --- a/sys.c +++ b/sys.c @@ -30,6 +30,7 @@ #include "sysincl.h" #include "sys.h" +#include "sys_null.h" #include "logging.h" #if defined(LINUX) @@ -44,9 +45,18 @@ /* ================================================== */ +static int null_driver; + +/* ================================================== */ + void -SYS_Initialise(void) +SYS_Initialise(int clock_control) { + null_driver = !clock_control; + if (null_driver) { + SYS_Null_Initialise(); + return; + } #if defined(LINUX) SYS_Linux_Initialise(); #elif defined(SOLARIS) @@ -65,6 +75,10 @@ SYS_Initialise(void) void SYS_Finalise(void) { + if (null_driver) { + SYS_Null_Finalise(); + return; + } #if defined(LINUX) SYS_Linux_Finalise(); #elif defined(SOLARIS) diff --git a/sys.h b/sys.h index bd990e2..cb726f2 100644 --- a/sys.h +++ b/sys.h @@ -30,7 +30,7 @@ #define GOT_SYS_H /* Called at the start of the run to do initialisation */ -extern void SYS_Initialise(void); +extern void SYS_Initialise(int clock_control); /* Called at the end of the run to do final clean-up */ extern void SYS_Finalise(void); diff --git a/sys_null.c b/sys_null.c new file mode 100644 index 0000000..3a0d5f6 --- /dev/null +++ b/sys_null.c @@ -0,0 +1,140 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Miroslav Lichvar 2017 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + ********************************************************************** + + ======================================================================= + + Null clock driver for operation with no clock control. + */ + +#include "config.h" + +#include "sysincl.h" + +#include "sys_null.h" + +#include "local.h" +#include "localp.h" +#include "logging.h" +#include "util.h" + +/* Current frequency offset of the system clock (in ppm) */ +static double freq; + +/* Offset of the system clock at the last update */ +static double offset_register; + +/* Time of the last update */ +static struct timespec last_update; + +/* Minimum interval between updates when frequency is constant */ +#define MIN_UPDATE_INTERVAL 1000.0 + +/* ================================================== */ + +static void +update_offset(void) +{ + struct timespec now; + double duration; + + LCL_ReadRawTime(&now); + duration = UTI_DiffTimespecsToDouble(&now, &last_update); + offset_register += 1.0e-6 * freq * duration; + last_update = now; + + DEBUG_LOG("System clock offset=%e freq=%f", offset_register, freq); +} + +/* ================================================== */ + +static double +read_frequency(void) +{ + return freq; +} + +/* ================================================== */ + +static double +set_frequency(double freq_ppm) +{ + update_offset(); + freq = freq_ppm; + + return freq; +} + +/* ================================================== */ + +static void +accrue_offset(double offset, double corr_rate) +{ + offset_register += offset; +} + +/* ================================================== */ + +static int +apply_step_offset(double offset) +{ + return 0; +} + +/* ================================================== */ + +static void +offset_convert(struct timespec *raw, double *corr, double *err) +{ + double duration; + + duration = UTI_DiffTimespecsToDouble(raw, &last_update); + + if (duration > MIN_UPDATE_INTERVAL) { + update_offset(); + duration = 0.0; + } + + *corr = -1.0e-6 * freq * duration - offset_register; + + if (err) + *err = 0.0; +} + +/* ================================================== */ + +void +SYS_Null_Initialise(void) +{ + offset_register = 0.0; + LCL_ReadRawTime(&last_update); + + lcl_RegisterSystemDrivers(read_frequency, set_frequency, accrue_offset, + apply_step_offset, offset_convert, NULL, NULL); + + LOG(LOGS_INFO, "Disabled control of system clock"); +} + +/* ================================================== */ + +void +SYS_Null_Finalise(void) +{ +} diff --git a/sys_null.h b/sys_null.h new file mode 100644 index 0000000..0fbf077 --- /dev/null +++ b/sys_null.h @@ -0,0 +1,34 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Miroslav Lichvar 2017 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + ********************************************************************** + + ======================================================================= + + Header file for null clock driver + */ + +#ifndef GOT_SYS_NULL_H +#define GOT_SYS_NULL_H + +extern void SYS_Null_Initialise(void); + +extern void SYS_Null_Finalise(void); + +#endif