summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-03-18 16:00:58 +0100
committerThomas Haller <thaller@redhat.com>2020-03-18 16:10:49 +0100
commita6574b71242da2da104e781a8adb91e2fcc04838 (patch)
tree6d6ea53abdd32bb06f31c7150ea8457b73d24593 /shared
parent6c837a366b3a81e104ebbd6b58d5a4b0e70ae838 (diff)
downloadNetworkManager-a6574b71242da2da104e781a8adb91e2fcc04838.tar.gz
n-dhcp4: fallback to CLOCK_MONOTONIC for timerfd (resync with upstream)
The upstream merge request [1] was solved differently from commit f49ce4121407 ('client: fallback to CLOCK_MONOTONIC for timerfd'). Resync with upstream. [1] https://github.com/nettools/n-dhcp4/pull/13 [2] https://github.com/nettools/n-dhcp4/commit/a0bb7c69a11a0db31fce5572c43ad7888694bf9e
Diffstat (limited to 'shared')
-rw-r--r--shared/n-dhcp4/src/n-dhcp4-client.c56
-rw-r--r--shared/n-dhcp4/src/n-dhcp4-private.h1
2 files changed, 28 insertions, 29 deletions
diff --git a/shared/n-dhcp4/src/n-dhcp4-client.c b/shared/n-dhcp4/src/n-dhcp4-client.c
index 4fa3d65daa..6b015e8166 100644
--- a/shared/n-dhcp4/src/n-dhcp4-client.c
+++ b/shared/n-dhcp4/src/n-dhcp4-client.c
@@ -388,14 +388,10 @@ _c_public_ int n_dhcp4_client_new(NDhcp4Client **clientp, NDhcp4ClientConfig *co
return -errno;
client->fd_timer = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC | TFD_NONBLOCK);
- if (client->fd_timer < 0) {
- if (errno != EINVAL)
- return -errno;
+ if (client->fd_timer < 0 && errno == EINVAL)
client->fd_timer = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
- if (client->fd_timer < 0)
- return -errno;
- client->timerfd_is_monotonic = true;
- }
+ if (client->fd_timer < 0)
+ return -errno;
ev.data.u32 = N_DHCP4_CLIENT_EPOLL_TIMER;
r = epoll_ctl(client->fd_epoll, EPOLL_CTL_ADD, client->fd_timer, &ev);
@@ -498,41 +494,45 @@ int n_dhcp4_client_raise(NDhcp4Client *client, NDhcp4CEventNode **nodep, unsigne
* must be called whenever a timeout on @client might have changed.
*/
void n_dhcp4_client_arm_timer(NDhcp4Client *client) {
- uint64_t timeout = 0;
+ uint64_t now, offset, timeout = 0;
int r;
if (client->current_probe)
n_dhcp4_client_probe_get_timeout(client->current_probe, &timeout);
if (timeout != client->scheduled_timeout) {
- uint64_t scheduled_timeout = timeout;
- int flags = TFD_TIMER_ABSTIME;
-
- if ( timeout != 0
- && client->timerfd_is_monotonic) {
- uint64_t now;
-
- /* the timerfd ticks with CLOCK_MONOTONIC. Calculate and set the relative
- * timeout. */
- now = n_dhcp4_gettime(CLOCK_BOOTTIME);
- if (timeout <= now)
- timeout = 1;
- else
- timeout = timeout - now;
- flags = 0;
- }
+ /*
+ * Across our codebase, timeouts are specified as absolute
+ * timestamps on CLOCK_BOOTTIME. Unfortunately, there are
+ * systems with CLOCK_BOOTTIME support, but timerfd lacks it
+ * (in particular RHEL). Therefore, our timerfd might be on
+ * CLOCK_MONOTONIC.
+ * To account for this, we always schedule a relative timeout.
+ * We fetch the current time and then calculate the offset
+ * which we then schedule as relative timeout on the timerfd.
+ * This works regardless which clock the timerfd runs on.
+ * Once we no longer support CLOCK_MONOTONIC as fallback, we
+ * can simply switch to TFD_TIMER_ABSTIME here and specify
+ * `timeout` directly as value.
+ */
+ now = n_dhcp4_gettime(CLOCK_BOOTTIME);
+ if (now >= timeout)
+ offset = 1; /* 0 would disarm the timerfd */
+ else
+ offset = timeout - now;
+
r = timerfd_settime(client->fd_timer,
- flags,
+ 0,
&(struct itimerspec){
.it_value = {
- .tv_sec = timeout / UINT64_C(1000000000),
- .tv_nsec = timeout % UINT64_C(1000000000),
+ .tv_sec = offset / UINT64_C(1000000000),
+ .tv_nsec = offset % UINT64_C(1000000000),
},
},
NULL);
c_assert(r >= 0);
- client->scheduled_timeout = scheduled_timeout;
+ client->scheduled_timeout = timeout;
}
}
diff --git a/shared/n-dhcp4/src/n-dhcp4-private.h b/shared/n-dhcp4/src/n-dhcp4-private.h
index f647cb5e2b..e285d95d23 100644
--- a/shared/n-dhcp4/src/n-dhcp4-private.h
+++ b/shared/n-dhcp4/src/n-dhcp4-private.h
@@ -332,7 +332,6 @@ struct NDhcp4Client {
uint64_t scheduled_timeout;
bool preempted : 1;
- bool timerfd_is_monotonic : 1;
};
#define N_DHCP4_CLIENT_NULL(_x) { \