mirror of
https://github.com/systemd/systemd
synced 2026-04-23 15:34:50 +02:00
Compare commits
17 Commits
6725a64f6e
...
59b8e67582
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59b8e67582 | ||
|
|
922a650829 | ||
|
|
b016e77efd | ||
|
|
1aa7ca2241 | ||
|
|
1f129b7fb7 | ||
|
|
87057128e6 | ||
|
|
20c1a21066 | ||
|
|
ec75e8e07a | ||
|
|
7cb08ea80f | ||
|
|
adc07c2bf5 | ||
|
|
5ba674cca5 | ||
|
|
9a8b43021b | ||
|
|
0fd08026f8 | ||
|
|
853efc39ea | ||
|
|
c696878ac0 | ||
|
|
aabda4f3e0 | ||
|
|
40c6b5143b |
@ -526,3 +526,11 @@ be updated to operate in a hotplug fashion without depending on
|
|||||||
systemd-udev-settle.service:
|
systemd-udev-settle.service:
|
||||||
|
|
||||||
@OFFENDING_UNITS@
|
@OFFENDING_UNITS@
|
||||||
|
|
||||||
|
-- 7c8a41f37b764941a0e1780b1be2f037
|
||||||
|
Subject: Initial clock synchronization
|
||||||
|
Defined-By: systemd
|
||||||
|
Support: %SUPPORT_URL%
|
||||||
|
|
||||||
|
For the first time during the current boot an NTP synchronization has been
|
||||||
|
acquired and the local system clock adjustment has been initiated.
|
||||||
|
|||||||
@ -39,6 +39,7 @@
|
|||||||
#include "dirent-util.h"
|
#include "dirent-util.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
|
#include "event-util.h"
|
||||||
#include "exec-util.h"
|
#include "exec-util.h"
|
||||||
#include "execute.h"
|
#include "execute.h"
|
||||||
#include "exit-status.h"
|
#include "exit-status.h"
|
||||||
@ -406,13 +407,8 @@ static int manager_setup_time_change(Manager *m) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
m->time_change_event_source = sd_event_source_disable_unref(m->time_change_event_source);
|
m->time_change_event_source = sd_event_source_disable_unref(m->time_change_event_source);
|
||||||
m->time_change_fd = safe_close(m->time_change_fd);
|
|
||||||
|
|
||||||
m->time_change_fd = time_change_fd();
|
r = event_add_time_change(m->event, &m->time_change_event_source, manager_dispatch_time_change_fd, m);
|
||||||
if (m->time_change_fd < 0)
|
|
||||||
return log_error_errno(m->time_change_fd, "Failed to create timer change timer fd: %m");
|
|
||||||
|
|
||||||
r = sd_event_add_io(m->event, &m->time_change_event_source, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to create time change event source: %m");
|
return log_error_errno(r, "Failed to create time change event source: %m");
|
||||||
|
|
||||||
@ -421,8 +417,6 @@ static int manager_setup_time_change(Manager *m) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set priority of time change event sources: %m");
|
return log_error_errno(r, "Failed to set priority of time change event sources: %m");
|
||||||
|
|
||||||
(void) sd_event_source_set_description(m->time_change_event_source, "manager-time-change");
|
|
||||||
|
|
||||||
log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
|
log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -820,7 +814,6 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
|
|||||||
.notify_fd = -1,
|
.notify_fd = -1,
|
||||||
.cgroups_agent_fd = -1,
|
.cgroups_agent_fd = -1,
|
||||||
.signal_fd = -1,
|
.signal_fd = -1,
|
||||||
.time_change_fd = -1,
|
|
||||||
.user_lookup_fds = { -1, -1 },
|
.user_lookup_fds = { -1, -1 },
|
||||||
.private_listen_fd = -1,
|
.private_listen_fd = -1,
|
||||||
.dev_autofs_fd = -1,
|
.dev_autofs_fd = -1,
|
||||||
@ -1509,7 +1502,6 @@ Manager* manager_free(Manager *m) {
|
|||||||
safe_close(m->signal_fd);
|
safe_close(m->signal_fd);
|
||||||
safe_close(m->notify_fd);
|
safe_close(m->notify_fd);
|
||||||
safe_close(m->cgroups_agent_fd);
|
safe_close(m->cgroups_agent_fd);
|
||||||
safe_close(m->time_change_fd);
|
|
||||||
safe_close_pair(m->user_lookup_fds);
|
safe_close_pair(m->user_lookup_fds);
|
||||||
|
|
||||||
manager_close_ask_password(m);
|
manager_close_ask_password(m);
|
||||||
@ -2913,7 +2905,6 @@ static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint
|
|||||||
Unit *u;
|
Unit *u;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(m->time_change_fd == fd);
|
|
||||||
|
|
||||||
log_struct(LOG_DEBUG,
|
log_struct(LOG_DEBUG,
|
||||||
"MESSAGE_ID=" SD_MESSAGE_TIME_CHANGE_STR,
|
"MESSAGE_ID=" SD_MESSAGE_TIME_CHANGE_STR,
|
||||||
|
|||||||
@ -226,7 +226,6 @@ struct Manager {
|
|||||||
|
|
||||||
sd_event_source *sigchld_event_source;
|
sd_event_source *sigchld_event_source;
|
||||||
|
|
||||||
int time_change_fd;
|
|
||||||
sd_event_source *time_change_event_source;
|
sd_event_source *time_change_event_source;
|
||||||
|
|
||||||
sd_event_source *timezone_change_event_source;
|
sd_event_source *timezone_change_event_source;
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "event-source.h"
|
#include "event-source.h"
|
||||||
#include "event-util.h"
|
#include "event-util.h"
|
||||||
|
#include "fd-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
|
||||||
@ -121,3 +122,41 @@ int event_source_is_enabled(sd_event_source *s) {
|
|||||||
|
|
||||||
return sd_event_source_get_enabled(s, NULL);
|
return sd_event_source_get_enabled(s, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handler_t callback, void *userdata) {
|
||||||
|
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *s = NULL;
|
||||||
|
_cleanup_close_ int fd = -1;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(e);
|
||||||
|
|
||||||
|
/* Allocates an IO event source that gets woken up whenever the clock changes. Needs to be recreated on each event */
|
||||||
|
|
||||||
|
fd = time_change_fd();
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
r = sd_event_add_io(e, &s, fd, EPOLLIN, callback, userdata);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_event_source_set_io_fd_own(s, true);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
TAKE_FD(fd);
|
||||||
|
|
||||||
|
r = sd_event_source_set_description(s, "time-change");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
*ret = TAKE_PTR(s);
|
||||||
|
else {
|
||||||
|
r = sd_event_source_set_floating(s, true);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -29,3 +29,5 @@ int event_reset_time_relative(
|
|||||||
bool force_reset);
|
bool force_reset);
|
||||||
int event_source_disable(sd_event_source *s);
|
int event_source_disable(sd_event_source *s);
|
||||||
int event_source_is_enabled(sd_event_source *s);
|
int event_source_is_enabled(sd_event_source *s);
|
||||||
|
|
||||||
|
int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handler_t callback, void *userdata);
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include "bus-polkit.h"
|
#include "bus-polkit.h"
|
||||||
#include "dirent-util.h"
|
#include "dirent-util.h"
|
||||||
#include "dns-domain.h"
|
#include "dns-domain.h"
|
||||||
|
#include "event-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-util.h"
|
||||||
@ -338,28 +339,16 @@ static int on_clock_change(sd_event_source *source, int fd, uint32_t revents, vo
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int manager_clock_change_listen(Manager *m) {
|
static int manager_clock_change_listen(Manager *m) {
|
||||||
_cleanup_close_ int fd = -1;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
m->clock_change_event_source = sd_event_source_disable_unref(m->clock_change_event_source);
|
m->clock_change_event_source = sd_event_source_disable_unref(m->clock_change_event_source);
|
||||||
|
|
||||||
fd = time_change_fd();
|
r = event_add_time_change(m->event, &m->clock_change_event_source, on_clock_change, m);
|
||||||
if (fd < 0)
|
|
||||||
return log_error_errno(fd, "Failed to allocate clock change timer fd: %m");
|
|
||||||
|
|
||||||
r = sd_event_add_io(m->event, &m->clock_change_event_source, fd, EPOLLIN, on_clock_change, m);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to create clock change event source: %m");
|
return log_error_errno(r, "Failed to create clock change event source: %m");
|
||||||
|
|
||||||
r = sd_event_source_set_io_fd_own(m->clock_change_event_source, true);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to pass ownership of clock fd to event source: %m");
|
|
||||||
TAKE_FD(fd);
|
|
||||||
|
|
||||||
(void) sd_event_source_set_description(m->clock_change_event_source, "clock-change");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -200,6 +200,9 @@ _SD_BEGIN_DECLARATIONS;
|
|||||||
#define SD_MESSAGE_SYSTEMD_UDEV_SETTLE_DEPRECATED_STR \
|
#define SD_MESSAGE_SYSTEMD_UDEV_SETTLE_DEPRECATED_STR \
|
||||||
SD_ID128_MAKE_STR(1c,04,54,c1,bd,22,41,e0,ac,6f,ef,b4,bc,63,14,33)
|
SD_ID128_MAKE_STR(1c,04,54,c1,bd,22,41,e0,ac,6f,ef,b4,bc,63,14,33)
|
||||||
|
|
||||||
|
#define SD_MESSAGE_TIME_SYNC SD_ID128_MAKE(7c,8a,41,f3,7b,76,49,41,a0,e1,78,0b,1b,e2,f0,37)
|
||||||
|
#define SD_MESSAGE_TIME_SYNC_STR SD_ID128_MAKE_STR(7c,8a,41,f3,7b,76,49,41,a0,e1,78,0b,1b,e2,f0,37)
|
||||||
|
|
||||||
_SD_END_DECLARATIONS;
|
_SD_END_DECLARATIONS;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -11,9 +11,11 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "sd-daemon.h"
|
#include "sd-daemon.h"
|
||||||
|
#include "sd-messages.h"
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "dns-domain.h"
|
#include "dns-domain.h"
|
||||||
|
#include "event-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
@ -28,6 +30,7 @@
|
|||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
#include "timesyncd-conf.h"
|
#include "timesyncd-conf.h"
|
||||||
#include "timesyncd-manager.h"
|
#include "timesyncd-manager.h"
|
||||||
|
#include "user-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#ifndef ADJ_SETOFFSET
|
#ifndef ADJ_SETOFFSET
|
||||||
@ -59,7 +62,7 @@ static int manager_arm_timer(Manager *m, usec_t next);
|
|||||||
static int manager_clock_watch_setup(Manager *m);
|
static int manager_clock_watch_setup(Manager *m);
|
||||||
static int manager_listen_setup(Manager *m);
|
static int manager_listen_setup(Manager *m);
|
||||||
static void manager_listen_stop(Manager *m);
|
static void manager_listen_stop(Manager *m);
|
||||||
static int manager_save_time_and_rearm(Manager *m);
|
static int manager_save_time_and_rearm(Manager *m, usec_t t);
|
||||||
|
|
||||||
static double ntp_ts_short_to_d(const struct ntp_ts_short *ts) {
|
static double ntp_ts_short_to_d(const struct ntp_ts_short *ts) {
|
||||||
return be16toh(ts->sec) + (be16toh(ts->frac) / 65536.0);
|
return be16toh(ts->sec) + (be16toh(ts->frac) / 65536.0);
|
||||||
@ -229,14 +232,9 @@ static int manager_clock_watch_setup(Manager *m) {
|
|||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
m->event_clock_watch = sd_event_source_unref(m->event_clock_watch);
|
m->event_clock_watch = sd_event_source_disable_unref(m->event_clock_watch);
|
||||||
safe_close(m->clock_watch_fd);
|
|
||||||
|
|
||||||
m->clock_watch_fd = time_change_fd();
|
r = event_add_time_change(m->event, &m->event_clock_watch, manager_clock_watch, m);
|
||||||
if (m->clock_watch_fd < 0)
|
|
||||||
return log_error_errno(m->clock_watch_fd, "Failed to create timerfd: %m");
|
|
||||||
|
|
||||||
r = sd_event_add_io(m->event, &m->event_clock_watch, m->clock_watch_fd, EPOLLIN, manager_clock_watch, m);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to create clock watch event source: %m");
|
return log_error_errno(r, "Failed to create clock watch event source: %m");
|
||||||
|
|
||||||
@ -244,31 +242,29 @@ static int manager_clock_watch_setup(Manager *m) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
|
static int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
|
||||||
struct timex tmx = {};
|
struct timex tmx;
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
/*
|
/* For small deltas, tell the kernel to gradually adjust the system clock to the NTP time, larger
|
||||||
* For small deltas, tell the kernel to gradually adjust the system
|
* deltas are just directly set. */
|
||||||
* clock to the NTP time, larger deltas are just directly set.
|
|
||||||
*/
|
|
||||||
if (fabs(offset) < NTP_MAX_ADJUST) {
|
if (fabs(offset) < NTP_MAX_ADJUST) {
|
||||||
tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR;
|
tmx = (struct timex) {
|
||||||
tmx.status = STA_PLL;
|
.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR,
|
||||||
tmx.offset = offset * NSEC_PER_SEC;
|
.status = STA_PLL,
|
||||||
tmx.constant = log2i(m->poll_interval_usec / USEC_PER_SEC) - 4;
|
.offset = offset * NSEC_PER_SEC,
|
||||||
tmx.maxerror = 0;
|
.constant = log2i(m->poll_interval_usec / USEC_PER_SEC) - 4,
|
||||||
tmx.esterror = 0;
|
};
|
||||||
|
|
||||||
log_debug(" adjust (slew): %+.3f sec", offset);
|
log_debug(" adjust (slew): %+.3f sec", offset);
|
||||||
} else {
|
} else {
|
||||||
tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET | ADJ_MAXERROR | ADJ_ESTERROR;
|
tmx = (struct timex) {
|
||||||
|
.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET | ADJ_MAXERROR | ADJ_ESTERROR,
|
||||||
|
|
||||||
/* ADJ_NANO uses nanoseconds in the microseconds field */
|
/* ADJ_NANO uses nanoseconds in the microseconds field */
|
||||||
tmx.time.tv_sec = (long)offset;
|
.time.tv_sec = (long)offset,
|
||||||
tmx.time.tv_usec = (offset - tmx.time.tv_sec) * NSEC_PER_SEC;
|
.time.tv_usec = (offset - (double) (long) offset) * NSEC_PER_SEC,
|
||||||
tmx.maxerror = 0;
|
};
|
||||||
tmx.esterror = 0;
|
|
||||||
|
|
||||||
/* the kernel expects -0.3s as {-1, 7000.000.000} */
|
/* the kernel expects -0.3s as {-1, 7000.000.000} */
|
||||||
if (tmx.time.tv_usec < 0) {
|
if (tmx.time.tv_usec < 0) {
|
||||||
@ -280,14 +276,11 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
|
|||||||
log_debug(" adjust (jump): %+.3f sec", offset);
|
log_debug(" adjust (jump): %+.3f sec", offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* An unset STA_UNSYNC will enable the kernel's 11-minute mode, which syncs the system time
|
||||||
* An unset STA_UNSYNC will enable the kernel's 11-minute mode,
|
* periodically to the RTC.
|
||||||
* which syncs the system time periodically to the RTC.
|
|
||||||
*
|
*
|
||||||
* In case the RTC runs in local time, never touch the RTC,
|
* In case the RTC runs in local time, never touch the RTC, we have no way to properly handle
|
||||||
* we have no way to properly handle daylight saving changes and
|
* daylight saving changes and mobile devices moving between time zones. */
|
||||||
* mobile devices moving between time zones.
|
|
||||||
*/
|
|
||||||
if (m->rtc_local_time)
|
if (m->rtc_local_time)
|
||||||
tmx.status |= STA_UNSYNC;
|
tmx.status |= STA_UNSYNC;
|
||||||
|
|
||||||
@ -300,17 +293,9 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = clock_adjtime(CLOCK_REALTIME, &tmx);
|
if (clock_adjtime(CLOCK_REALTIME, &tmx) < 0)
|
||||||
if (r < 0)
|
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
r = manager_save_time_and_rearm(m);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* If touch fails, there isn't much we can do. Maybe it'll work next time. */
|
|
||||||
(void) touch("/run/systemd/timesync/synchronized");
|
|
||||||
|
|
||||||
m->drift_freq = tmx.freq;
|
m->drift_freq = tmx.freq;
|
||||||
|
|
||||||
log_debug(" status : %04i %s\n"
|
log_debug(" status : %04i %s\n"
|
||||||
@ -427,15 +412,12 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
|
|||||||
.msg_name = &server_addr,
|
.msg_name = &server_addr,
|
||||||
.msg_namelen = sizeof(server_addr),
|
.msg_namelen = sizeof(server_addr),
|
||||||
};
|
};
|
||||||
struct cmsghdr *cmsg;
|
|
||||||
struct timespec *recv_time = NULL;
|
struct timespec *recv_time = NULL;
|
||||||
|
triple_timestamp dts;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
double origin, receive, trans, dest;
|
double origin, receive, trans, dest, delay, offset, root_distance;
|
||||||
double delay, offset;
|
|
||||||
double root_distance;
|
|
||||||
bool spike;
|
bool spike;
|
||||||
int leap_sec;
|
int leap_sec, r;
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(source);
|
assert(source);
|
||||||
assert(m);
|
assert(m);
|
||||||
@ -466,21 +448,9 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMSG_FOREACH(cmsg, &msghdr) {
|
recv_time = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_TIMESTAMPNS, struct timespec);
|
||||||
if (cmsg->cmsg_level != SOL_SOCKET)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (cmsg->cmsg_type) {
|
|
||||||
case SCM_TIMESTAMPNS:
|
|
||||||
assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct timespec)));
|
|
||||||
|
|
||||||
recv_time = (struct timespec *) CMSG_DATA(cmsg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!recv_time)
|
if (!recv_time)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Packet timestamp missing.");
|
||||||
"Invalid packet timestamp.");
|
|
||||||
|
|
||||||
if (!m->pending) {
|
if (!m->pending) {
|
||||||
log_debug("Unexpected reply. Ignoring.");
|
log_debug("Unexpected reply. Ignoring.");
|
||||||
@ -597,10 +567,23 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
|
|||||||
m->samples_jitter, spike ? " spike" : "",
|
m->samples_jitter, spike ? " spike" : "",
|
||||||
m->poll_interval_usec / USEC_PER_SEC);
|
m->poll_interval_usec / USEC_PER_SEC);
|
||||||
|
|
||||||
|
/* Get current monotonic/realtime clocks immediately before adjusting the latter */
|
||||||
|
triple_timestamp_get(&dts);
|
||||||
|
|
||||||
if (!spike) {
|
if (!spike) {
|
||||||
|
/* Fix up our idea of the time. */
|
||||||
|
dts.realtime = (usec_t) (dts.realtime + offset * USEC_PER_SEC);
|
||||||
|
|
||||||
r = manager_adjust_clock(m, offset, leap_sec);
|
r = manager_adjust_clock(m, offset, leap_sec);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to call clock_adjtime(): %m");
|
log_error_errno(r, "Failed to call clock_adjtime(): %m");
|
||||||
|
|
||||||
|
(void) manager_save_time_and_rearm(m, dts.realtime);
|
||||||
|
|
||||||
|
/* If touch fails, there isn't much we can do. Maybe it'll work next time. */
|
||||||
|
r = touch("/run/systemd/timesync/synchronized");
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to touch /run/systemd/timesync/synchronized, ignoring: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save NTP response */
|
/* Save NTP response */
|
||||||
@ -621,15 +604,26 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
|
|||||||
"NTPMessage",
|
"NTPMessage",
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (!m->good) {
|
if (!m->talking) {
|
||||||
_cleanup_free_ char *pretty = NULL;
|
_cleanup_free_ char *pretty = NULL;
|
||||||
|
|
||||||
m->good = true;
|
m->talking = true;
|
||||||
|
|
||||||
server_address_pretty(m->current_server_address, &pretty);
|
(void) server_address_pretty(m->current_server_address, &pretty);
|
||||||
/* "Initial", as further successful syncs will not be logged. */
|
|
||||||
log_info("Initial synchronization to time server %s (%s).", strna(pretty), m->current_server_name->string);
|
log_info("Contacted time server %s (%s).", strna(pretty), m->current_server_name->string);
|
||||||
sd_notifyf(false, "STATUS=Initial synchronization to time server %s (%s).", strna(pretty), m->current_server_name->string);
|
(void) sd_notifyf(false, "STATUS=Contacted time server %s (%s).", strna(pretty), m->current_server_name->string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!spike && !m->synchronized) {
|
||||||
|
m->synchronized = true;
|
||||||
|
|
||||||
|
log_struct(LOG_INFO,
|
||||||
|
LOG_MESSAGE("Initial clock synchronization to %s.", FORMAT_TIMESTAMP_STYLE(dts.realtime, TIMESTAMP_US)),
|
||||||
|
"MESSAGE_ID=" SD_MESSAGE_TIME_SYNC_STR,
|
||||||
|
"MONOTONIC_USEC=" USEC_FMT, dts.monotonic,
|
||||||
|
"REALTIME_USEC=" USEC_FMT, dts.realtime,
|
||||||
|
"BOOTIME_USEC=" USEC_FMT, dts.boottime);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = manager_arm_timer(m, m->poll_interval_usec);
|
r = manager_arm_timer(m, m->poll_interval_usec);
|
||||||
@ -686,14 +680,14 @@ static int manager_begin(Manager *m) {
|
|||||||
assert_return(m->current_server_name, -EHOSTUNREACH);
|
assert_return(m->current_server_name, -EHOSTUNREACH);
|
||||||
assert_return(m->current_server_address, -EHOSTUNREACH);
|
assert_return(m->current_server_address, -EHOSTUNREACH);
|
||||||
|
|
||||||
m->good = false;
|
m->talking = false;
|
||||||
m->missed_replies = NTP_MAX_MISSED_REPLIES;
|
m->missed_replies = NTP_MAX_MISSED_REPLIES;
|
||||||
if (m->poll_interval_usec == 0)
|
if (m->poll_interval_usec == 0)
|
||||||
m->poll_interval_usec = m->poll_interval_min_usec;
|
m->poll_interval_usec = m->poll_interval_min_usec;
|
||||||
|
|
||||||
server_address_pretty(m->current_server_address, &pretty);
|
server_address_pretty(m->current_server_address, &pretty);
|
||||||
log_debug("Connecting to time server %s (%s).", strna(pretty), m->current_server_name->string);
|
log_debug("Connecting to time server %s (%s).", strna(pretty), m->current_server_name->string);
|
||||||
sd_notifyf(false, "STATUS=Connecting to time server %s (%s).", strna(pretty), m->current_server_name->string);
|
(void) sd_notifyf(false, "STATUS=Connecting to time server %s (%s).", strna(pretty), m->current_server_name->string);
|
||||||
|
|
||||||
r = manager_clock_watch_setup(m);
|
r = manager_clock_watch_setup(m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -818,7 +812,7 @@ int manager_connect(Manager *m) {
|
|||||||
if (m->current_server_address && m->current_server_address->addresses_next)
|
if (m->current_server_address && m->current_server_address->addresses_next)
|
||||||
manager_set_server_address(m, m->current_server_address->addresses_next);
|
manager_set_server_address(m, m->current_server_address->addresses_next);
|
||||||
else {
|
else {
|
||||||
struct addrinfo hints = {
|
static const struct addrinfo hints = {
|
||||||
.ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG,
|
.ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG,
|
||||||
.ai_socktype = SOCK_DGRAM,
|
.ai_socktype = SOCK_DGRAM,
|
||||||
};
|
};
|
||||||
@ -910,12 +904,11 @@ void manager_disconnect(Manager *m) {
|
|||||||
|
|
||||||
manager_listen_stop(m);
|
manager_listen_stop(m);
|
||||||
|
|
||||||
m->event_clock_watch = sd_event_source_unref(m->event_clock_watch);
|
m->event_clock_watch = sd_event_source_disable_unref(m->event_clock_watch);
|
||||||
m->clock_watch_fd = safe_close(m->clock_watch_fd);
|
|
||||||
|
|
||||||
m->event_timeout = sd_event_source_unref(m->event_timeout);
|
m->event_timeout = sd_event_source_unref(m->event_timeout);
|
||||||
|
|
||||||
sd_notify(false, "STATUS=Idle.");
|
(void) sd_notify(false, "STATUS=Idle.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void manager_flush_server_names(Manager *m, ServerType t) {
|
void manager_flush_server_names(Manager *m, ServerType t) {
|
||||||
@ -1098,21 +1091,26 @@ int manager_new(Manager **ret) {
|
|||||||
|
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
m = new0(Manager, 1);
|
m = new(Manager, 1);
|
||||||
if (!m)
|
if (!m)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
m->root_distance_max_usec = NTP_ROOT_DISTANCE_MAX_USEC;
|
*m = (Manager) {
|
||||||
m->poll_interval_min_usec = NTP_POLL_INTERVAL_MIN_USEC;
|
.root_distance_max_usec = NTP_ROOT_DISTANCE_MAX_USEC,
|
||||||
m->poll_interval_max_usec = NTP_POLL_INTERVAL_MAX_USEC;
|
.poll_interval_min_usec = NTP_POLL_INTERVAL_MIN_USEC,
|
||||||
|
.poll_interval_max_usec = NTP_POLL_INTERVAL_MAX_USEC,
|
||||||
|
|
||||||
m->connection_retry_usec = DEFAULT_CONNECTION_RETRY_USEC;
|
.connection_retry_usec = DEFAULT_CONNECTION_RETRY_USEC,
|
||||||
|
|
||||||
m->server_socket = m->clock_watch_fd = -1;
|
.server_socket = -1,
|
||||||
|
|
||||||
m->ratelimit = (RateLimit) { RATELIMIT_INTERVAL_USEC, RATELIMIT_BURST };
|
.ratelimit = (RateLimit) {
|
||||||
|
RATELIMIT_INTERVAL_USEC,
|
||||||
|
RATELIMIT_BURST
|
||||||
|
},
|
||||||
|
|
||||||
m->save_time_interval_usec = DEFAULT_SAVE_TIME_INTERVAL_USEC;
|
.save_time_interval_usec = DEFAULT_SAVE_TIME_INTERVAL_USEC,
|
||||||
|
};
|
||||||
|
|
||||||
r = sd_event_default(&m->event);
|
r = sd_event_default(&m->event);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -1123,6 +1121,12 @@ int manager_new(Manager **ret) {
|
|||||||
|
|
||||||
(void) sd_event_set_watchdog(m->event, true);
|
(void) sd_event_set_watchdog(m->event, true);
|
||||||
|
|
||||||
|
/* Load previous synchronization state */
|
||||||
|
r = access("/run/systemd/timesync/synchronized", F_OK);
|
||||||
|
if (r < 0 && errno != ENOENT)
|
||||||
|
log_debug_errno(errno, "Failed to determine whether /run/systemd/timesync/synchronized exists, ignoring: %m");
|
||||||
|
m->synchronized = r >= 0;
|
||||||
|
|
||||||
r = sd_resolve_default(&m->resolve);
|
r = sd_resolve_default(&m->resolve);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -1147,7 +1151,7 @@ static int manager_save_time_handler(sd_event_source *s, uint64_t usec, void *us
|
|||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
(void) manager_save_time_and_rearm(m);
|
(void) manager_save_time_and_rearm(m, USEC_INFINITY);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1175,12 +1179,16 @@ int manager_setup_save_time_event(Manager *m) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_save_time_and_rearm(Manager *m) {
|
static int manager_save_time_and_rearm(Manager *m, usec_t t) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
r = touch(CLOCK_FILE);
|
/* Updates the timestamp file to the specified time. If 't' is USEC_INFINITY uses the current system
|
||||||
|
* clock, but otherwise uses the specified timestamp. Note that whenever we acquire an NTP sync the
|
||||||
|
* specified timestamp value might be more accurate than the system clock, since the latter is
|
||||||
|
* subject to slow adjustments. */
|
||||||
|
r = touch_file(CLOCK_FILE, false, t, UID_INVALID, GID_INVALID, MODE_INVALID);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_debug_errno(r, "Failed to update " CLOCK_FILE ", ignoring: %m");
|
log_debug_errno(r, "Failed to update " CLOCK_FILE ", ignoring: %m");
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ struct Manager {
|
|||||||
int missed_replies;
|
int missed_replies;
|
||||||
uint64_t packet_count;
|
uint64_t packet_count;
|
||||||
sd_event_source *event_timeout;
|
sd_event_source *event_timeout;
|
||||||
bool good;
|
bool talking;
|
||||||
|
|
||||||
/* last sent packet */
|
/* last sent packet */
|
||||||
struct timespec trans_time_mon;
|
struct timespec trans_time_mon;
|
||||||
@ -92,7 +92,6 @@ struct Manager {
|
|||||||
|
|
||||||
/* watch for time changes */
|
/* watch for time changes */
|
||||||
sd_event_source *event_clock_watch;
|
sd_event_source *event_clock_watch;
|
||||||
int clock_watch_fd;
|
|
||||||
|
|
||||||
/* Retry connections */
|
/* Retry connections */
|
||||||
sd_event_source *event_retry;
|
sd_event_source *event_retry;
|
||||||
@ -105,6 +104,9 @@ struct Manager {
|
|||||||
struct timespec origin_time, dest_time;
|
struct timespec origin_time, dest_time;
|
||||||
bool spike;
|
bool spike;
|
||||||
|
|
||||||
|
/* Indicates whether we ever managed to set the local clock from NTP */
|
||||||
|
bool synchronized;
|
||||||
|
|
||||||
/* save time event */
|
/* save time event */
|
||||||
sd_event_source *event_save_time;
|
sd_event_source *event_save_time;
|
||||||
usec_t save_time_interval_usec;
|
usec_t save_time_interval_usec;
|
||||||
|
|||||||
@ -16,16 +16,19 @@ int server_address_new(
|
|||||||
assert(socklen >= offsetof(struct sockaddr, sa_data));
|
assert(socklen >= offsetof(struct sockaddr, sa_data));
|
||||||
assert(socklen <= sizeof(union sockaddr_union));
|
assert(socklen <= sizeof(union sockaddr_union));
|
||||||
|
|
||||||
a = new0(ServerAddress, 1);
|
a = new(ServerAddress, 1);
|
||||||
if (!a)
|
if (!a)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*a = (ServerAddress) {
|
||||||
|
.name = n,
|
||||||
|
.socklen = socklen,
|
||||||
|
};
|
||||||
|
|
||||||
memcpy(&a->sockaddr, sockaddr, socklen);
|
memcpy(&a->sockaddr, sockaddr, socklen);
|
||||||
a->socklen = socklen;
|
|
||||||
|
|
||||||
LIST_FIND_TAIL(addresses, n->addresses, tail);
|
LIST_FIND_TAIL(addresses, n->addresses, tail);
|
||||||
LIST_INSERT_AFTER(addresses, n->addresses, tail, a);
|
LIST_INSERT_AFTER(addresses, n->addresses, tail, a);
|
||||||
a->name = n;
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
*ret = a;
|
*ret = a;
|
||||||
@ -58,12 +61,16 @@ int server_name_new(
|
|||||||
assert(m);
|
assert(m);
|
||||||
assert(string);
|
assert(string);
|
||||||
|
|
||||||
n = new0(ServerName, 1);
|
n = new(ServerName, 1);
|
||||||
if (!n)
|
if (!n)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
n->type = type;
|
*n = (ServerName) {
|
||||||
n->string = strdup(string);
|
.manager = m,
|
||||||
|
.type = type,
|
||||||
|
.string = strdup(string),
|
||||||
|
};
|
||||||
|
|
||||||
if (!n->string) {
|
if (!n->string) {
|
||||||
free(n);
|
free(n);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -81,8 +88,6 @@ int server_name_new(
|
|||||||
} else
|
} else
|
||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
|
|
||||||
n->manager = m;
|
|
||||||
|
|
||||||
if (type != SERVER_FALLBACK &&
|
if (type != SERVER_FALLBACK &&
|
||||||
m->current_server_name &&
|
m->current_server_name &&
|
||||||
m->current_server_name->type == SERVER_FALLBACK)
|
m->current_server_name->type == SERVER_FALLBACK)
|
||||||
|
|||||||
@ -22,9 +22,8 @@
|
|||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
|
|
||||||
static int load_clock_timestamp(uid_t uid, gid_t gid) {
|
static int load_clock_timestamp(uid_t uid, gid_t gid) {
|
||||||
|
usec_t min = TIME_EPOCH * USEC_PER_SEC, ct;
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
usec_t min = TIME_EPOCH * USEC_PER_SEC;
|
|
||||||
usec_t ct;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Let's try to make sure that the clock is always
|
/* Let's try to make sure that the clock is always
|
||||||
@ -40,8 +39,7 @@ static int load_clock_timestamp(uid_t uid, gid_t gid) {
|
|||||||
usec_t stamp;
|
usec_t stamp;
|
||||||
|
|
||||||
/* check if the recorded time is later than the compiled-in one */
|
/* check if the recorded time is later than the compiled-in one */
|
||||||
r = fstat(fd, &st);
|
if (fstat(fd, &st) >= 0) {
|
||||||
if (r >= 0) {
|
|
||||||
stamp = timespec_load(&st.st_mtim);
|
stamp = timespec_load(&st.st_mtim);
|
||||||
if (stamp > min)
|
if (stamp > min)
|
||||||
min = stamp;
|
min = stamp;
|
||||||
@ -64,7 +62,7 @@ static int load_clock_timestamp(uid_t uid, gid_t gid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create stamp file with the compiled-in date */
|
/* create stamp file with the compiled-in date */
|
||||||
r = touch_file(CLOCK_FILE, false, min, uid, gid, 0644);
|
r = touch_file(CLOCK_FILE, /* parents= */ false, min, uid, gid, 0644);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_debug_errno(r, "Failed to create %s, ignoring: %m", CLOCK_FILE);
|
log_debug_errno(r, "Failed to create %s, ignoring: %m", CLOCK_FILE);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user