rtc: set clock to mtime of driftfile when RTC preinit fails

When the RTC preinit function fails, set the system clock to the time of
the last modification of the driftfile if it's in the future. This makes
the -s option somewhat useful on systems where RTC is not supported or
missing.

This is similar to the functionality implemented in the fake-hwclock
script.
This commit is contained in:
Miroslav Lichvar 2014-08-18 18:21:24 +02:00
parent e0af8069c1
commit a5e9e5d0df
3 changed files with 51 additions and 16 deletions

View file

@ -1018,18 +1018,20 @@ Support for real-time clocks is limited at present - the criteria are
described in the section on the @code{rtcfile} directive (@pxref{rtcfile
directive}).
If @code{chronyd} cannot support the real time clock on your computer,
this option cannot be used and a warning message will be logged to the
syslog.
If used in conjunction with the `-r' flag, @code{chronyd} will attempt
to preserve the old samples after setting the system clock from the real
time clock. This can be used to allow @code{chronyd} to perform long
time clock (RTC). This can be used to allow @code{chronyd} to perform long
term averaging of the gain or loss rate across system reboots, and is
useful for dial-up systems that are shut down when not in use. For this
to work well, it relies on @code{chronyd} having been able to determine
accurate statistics for the difference between the real time clock and
accurate statistics for the difference between the RTC and
system clock last time the computer was on.
If @code{chronyd} doesn't support the RTC on your computer or there is no RTC
installed, the system clock will be set with this option to the time of the
last modification of the drift file (specified by the @code{driftfile}
directive) to restore the system time at which @code{chronyd} was previously
stopped.
@item -u <user>
This option sets the name of the user to which will @code{chronyd} switch to
drop root privileges if compiled with Linux capabilities support (default

View file

@ -88,19 +88,20 @@ Support for real-time clocks is limited at present - the criteria
are described in the section on the \fIrtcfile\fR directive in the
documentation supplied with the distribution.
If \fBchronyd\fR cannot support the real time clock on your computer,
this option cannot be used and a warning message will be logged to
the syslog.
If used in conjunction with the \fB-r\fR flag, \fBchronyd\fR will attempt
to preserve the old samples after setting the system clock from
the real time clock. This can be used to allow \fBchronyd\fR to
the real time clock (RTC). This can be used to allow \fBchronyd\fR to
perform long term averaging of the gain or loss rate across system
reboots, and is useful for dial-up systems that are shut down when
not in use. For this to work well, it relies on \fBchronyd\fR having
been able to determine accurate statistics for the difference
between the real time clock and system clock last time the
computer was on.
between the RTC and system clock last time the computer was on.
If \fBchronyd\fR doesn't support the RTC on your computer or there is no RTC
installed, the system clock will be set with this option to the time of the
last modification of the drift file (specified by the \fIdriftfile\fR
directive) to restore the system time at which \fBchronyd\fR was previously
stopped.
.TP
\fB\-u\fR \fIuser\fR
This option sets the name of the user to which will \fBchronyd\fR switch to

38
rtc.c
View file

@ -28,6 +28,7 @@
#include "sysincl.h"
#include "rtc.h"
#include "local.h"
#include "logging.h"
#include "conf.h"
@ -71,6 +72,33 @@ static struct {
#endif
};
/* ================================================== */
/* Set the system clock to the time of last modification of driftfile
if it's in the future */
static void
fallback_time_init(void)
{
struct timeval now;
struct stat buf;
char *drift_file;
drift_file = CNF_GetDriftFile();
if (!drift_file)
return;
if (stat(drift_file, &buf))
return;
LCL_ReadCookedTime(&now, NULL);
if (now.tv_sec < buf.st_mtime) {
LCL_ApplyStepOffset(now.tv_sec - buf.st_mtime);
LOG(LOGS_INFO, LOGF_Rtc,
"System clock set from driftfile %s", drift_file);
}
}
/* ================================================== */
void
@ -79,9 +107,13 @@ RTC_Initialise(int initial_set)
char *file_name;
/* Do an initial read of the RTC and set the system time to it. This
is analogous to what /sbin/hwclock -s would do on Linux. */
if (initial_set && driver.time_pre_init) {
(driver.time_pre_init)();
is analogous to what /sbin/hwclock -s would do on Linux. If that fails
or RTC is not supported, set the clock to the time of the last
modification of driftfile, so we at least get closer to the truth. */
if (initial_set) {
if (!driver.time_pre_init || !driver.time_pre_init()) {
fallback_time_init();
}
}
driver_initialised = 0;