summaryrefslogtreecommitdiffstats
path: root/sys-utils/hwclock.c
diff options
context:
space:
mode:
authorJ William Piggott2014-09-25 13:38:25 +0200
committerJ William Piggott2014-10-15 20:45:29 +0200
commitd17a12a3685945e7d5579db491543d223618d060 (patch)
tree67325e74bcc60f94277ecf71c259e5ddfe3d16b9 /sys-utils/hwclock.c
parenthwclock: hctosys drift compensation II MAN (diff)
downloadkernel-qcow2-util-linux-d17a12a3685945e7d5579db491543d223618d060.tar.gz
kernel-qcow2-util-linux-d17a12a3685945e7d5579db491543d223618d060.tar.xz
kernel-qcow2-util-linux-d17a12a3685945e7d5579db491543d223618d060.zip
hwclock: persistent_clock_is_local
When hctosys is used at boot time, making it the first caller of settimeofday, the responsibility of setting persistent_clock_is_local is thrust upon it. Currently hctosys always leaves this variable uninitialized. This causes a Hardware Clock configured to use the local timescale to be clobbered with the UTC timescale by the kernel's NTP eleven minute mode. This patch fixes this hctosys bug, by having it properly set persistent_clock_is_local according to the time scale configured for the Hardware Clock. It does this via the kernel warp_clock function but this in inconsequential, because we set the system time immediately afterward. Signed-off-by: J William Piggott <elseifthen@gmx.com>
Diffstat (limited to 'sys-utils/hwclock.c')
-rw-r--r--sys-utils/hwclock.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c
index 4befbab32..dc8f9574e 100644
--- a/sys-utils/hwclock.c
+++ b/sys-utils/hwclock.c
@@ -809,6 +809,12 @@ static int interpret_date_string(const char *date_opt, time_t * const time_p)
* environment variable and/or /usr/lib/zoneinfo/, interpreted as tzset()
* would interpret them.
*
+ * If this is the first call of settimeofday since boot, then this also sets
+ * the kernel variable persistent_clock_is_local so that NTP 11 minute mode
+ * will update the Hardware Clock with the proper timescale. If the Hardware
+ * Clock's timescale configuration is changed then a reboot is required for
+ * persistent_clock_is_local to be updated.
+ *
* EXCEPT: if hclock_valid is false, just issue an error message saying
* there is no valid time in the Hardware Clock to which to set the system
* time.
@@ -818,7 +824,7 @@ static int interpret_date_string(const char *date_opt, time_t * const time_p)
*/
static int
set_system_clock(const bool hclock_valid, const struct timeval newtime,
- const bool testing)
+ const bool testing, const bool universal)
{
int retcode;
@@ -828,9 +834,10 @@ set_system_clock(const bool hclock_valid, const struct timeval newtime,
"we cannot set the System Time from it."));
retcode = 1;
} else {
+ const struct timeval *tv_null = NULL;
struct tm *broken;
int minuteswest;
- int rc;
+ int rc = 0;
broken = localtime(&newtime.tv_sec);
#ifdef HAVE_TM_GMTOFF
@@ -854,7 +861,14 @@ set_system_clock(const bool hclock_valid, const struct timeval newtime,
} else {
const struct timezone tz = { minuteswest, 0 };
- rc = settimeofday(&newtime, &tz);
+ /* Set kernel persistent_clock_is_local so that 11 minute
+ * mode does not clobber the Hardware Clock with UTC. This
+ * is only available on first call of settimeofday after boot.
+ */
+ if (!universal)
+ rc = settimeofday(tv_null, &tz);
+ if (!rc)
+ rc = settimeofday(&newtime, &tz);
if (rc) {
if (errno == EPERM) {
warnx(_
@@ -1376,7 +1390,8 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
adjust_drift_factor(&adjtime, nowtime,
hclock_valid, hclocktime);
} else if (hctosys) {
- rc = set_system_clock(hclock_valid, hclocktime, testing);
+ rc = set_system_clock(hclock_valid, hclocktime,
+ testing, universal);
if (rc) {
printf(_("Unable to set system clock.\n"));
return rc;