[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