[Devel] [PATCH 11/14] fs: convert ve monotonic to abs time when setting timerfd

Kirill Tkhai ktkhai at odin.com
Mon Jun 8 07:22:15 PDT 2015


Porting patch diff-ve-timers-convert-ve-monotonic-to-abs-time-when-setting-timerfd-2
from 2.6.32:

* [timers] corrected TFD_TIMER_ABSTIME timer handling,
	the issue led to high cpu usage inside a Fedora 18 CT
	by 'init' process (PSBM-18284)


Monotonic time inside container, as it can be obtained using various system
calls such as clock_gettime, is reported since start of the container, not
since start of the whole system. This was made in order to avoid time issues
while a container is migrated between different physical hosts, but this also
introduced a lot of problems in time- related system calls because absolute
monotonic time, which is in fact relative to container, passed to those system
calls must be converted to system-wide monotonic time, which is used by kernel
hrtimers.

One of those buggy system calls is timerfd_settime which accepts as an argument
absolute time if flag TFD_TIMER_ABSTIME is specified.

The patch fixes it by converting container monotonic time to system- wide
monotonic time using the monotonic_ve_to_abs() function, which was introduced
earlier and is now exported for that reason.

https://jira.sw.ru/browse/PSBM-18284

Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
Signed-off-by: Kirill Tkhai <ktkhai at odin.com>

To Konstantin: we most likely need to convert old time, which is
returned to userspace, back in absolute. This is need for 2.6.32
and 3.10 both. Please, create a jira task to do not forget.
---
 fs/timerfd.c          |    6 +++++-
 include/linux/ve.h    |    2 ++
 kernel/posix-timers.c |    8 ++++----
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/fs/timerfd.c b/fs/timerfd.c
index ad10267..9f01709 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -24,6 +24,7 @@
 #include <linux/syscalls.h>
 #include <linux/compat.h>
 #include <linux/rcupdate.h>
+#include <linux/ve.h>
 
 struct timerfd_ctx {
 	struct hrtimer tmr;
@@ -349,7 +350,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
 }
 
 static int do_timerfd_settime(int ufd, int flags, 
-		const struct itimerspec *new,
+		struct itimerspec *new,
 		struct itimerspec *old)
 {
 	struct fd f;
@@ -395,6 +396,9 @@ static int do_timerfd_settime(int ufd, int flags,
 	/*
 	 * Re-program the timer to the new value ...
 	 */
+	if ((flags & TFD_TIMER_ABSTIME) &&
+	    (new->it_value.tv_sec || new->it_value.tv_nsec))
+		monotonic_ve_to_abs(ctx->clockid, &new->it_value);
 	ret = timerfd_setup(ctx, flags, new);
 
 	spin_unlock_irq(&ctx->wqh.lock);
diff --git a/include/linux/ve.h b/include/linux/ve.h
index 0029f57..758ff85 100644
--- a/include/linux/ve.h
+++ b/include/linux/ve.h
@@ -211,6 +211,8 @@ static inline struct ve_struct *cgroup_ve(struct cgroup *cgroup)
 }
 
 extern unsigned long long ve_relative_clock(struct timespec * ts);
+extern void monotonic_abs_to_ve(clockid_t which_clock, struct timespec *tp);
+extern void monotonic_ve_to_abs(clockid_t which_clock, struct timespec *tp);
 
 #ifdef CONFIG_VTTYS
 extern int vtty_open_master(int veid, int idx);
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index b9c849f..720a215 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -133,7 +133,7 @@ static struct k_clock posix_clocks[MAX_CLOCKS];
 	 (which_clock) == CLOCK_MONOTONIC_COARSE)
 
 #ifdef CONFIG_VE
-static void monotonic_abs_to_ve(clockid_t which_clock, struct timespec *tp)
+void monotonic_abs_to_ve(clockid_t which_clock, struct timespec *tp)
 {
 	struct ve_struct *ve = get_exec_env();
 
@@ -143,7 +143,7 @@ static void monotonic_abs_to_ve(clockid_t which_clock, struct timespec *tp)
 				tp->tv_nsec - ve->start_timespec.tv_nsec);
 }
 
-static void monotonic_ve_to_abs(clockid_t which_clock, struct timespec *tp)
+void monotonic_ve_to_abs(clockid_t which_clock, struct timespec *tp)
 {
 	struct ve_struct *ve = get_exec_env();
 
@@ -153,9 +153,9 @@ static void monotonic_ve_to_abs(clockid_t which_clock, struct timespec *tp)
 				tp->tv_nsec + ve->start_timespec.tv_nsec);
 }
 #else
-static inline void monotonic_abs_to_ve(clockid_t which_clock,
+void monotonic_abs_to_ve(clockid_t which_clock,
 				       struct timespec *tp) { }
-static inline void monotonic_ve_to_abs(clockid_t which_clock,
+void monotonic_ve_to_abs(clockid_t which_clock,
 				       struct timepsec *tp) { }
 #endif
 




More information about the Devel mailing list