Monotonic time can't be changed by users, can't go back and it starts with
zero when a kernel starts.

When we migrate a container on another host, we need to save consistancy
of monotonic time, so we have a per-ve offset.

This patch adds the ability to set this offset. When a container is
migrated, the value from ve.start_timespec on a source host should be
written in the same file on a destination host.

https://jira.sw.ru/browse/PSBM-41311?jql=text%20~%20%22of%20persia%22

Cc: Cyrill Gorcunov <[email protected]>
Signed-off-by: Andrew Vagin <[email protected]>
---
 include/linux/ve.h    |    3 +++
 kernel/posix-timers.c |   41 +++++++++++++++++++++++++++++++++++++++++
 kernel/ve/ve.c        |   36 ++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/include/linux/ve.h b/include/linux/ve.h
index 86b95c3..5f972aa 100644
--- a/include/linux/ve.h
+++ b/include/linux/ve.h
@@ -222,6 +222,9 @@ extern struct tty_driver *vtty_console_driver(int *index);
 extern int vtty_open_master(envid_t veid, int idx);
 #endif /* CONFIG_TTY */
 
+extern int get_ve_monotonic_time(struct ve_struct *ve, struct timespec *tp);
+extern int set_ve_monotonic_time(struct ve_struct *ve, struct timespec *tp);
+
 #else  /* CONFIG_VE */
 
 #define ve_uevent_seqnum uevent_seqnum
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index a4b1ca7..25ff0ca 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -1053,6 +1053,47 @@ SYSCALL_DEFINE2(clock_settime, const clockid_t, 
which_clock,
        return kc->clock_set(which_clock, &new_tp);
 }
 
+#ifdef CONFIG_VE
+int get_ve_monotonic_time(struct ve_struct *ve, struct timespec *tp)
+{
+       struct k_clock *kc = clockid_to_kclock(CLOCK_MONOTONIC);
+       int error;
+
+       if (!kc)
+               return -EINVAL;
+
+       error = kc->clock_get(CLOCK_MONOTONIC, tp);
+       if (error)
+               return error;
+
+       set_normalized_timespec(tp,
+                       tp->tv_sec - ve->start_timespec.tv_sec,
+                       tp->tv_nsec - ve->start_timespec.tv_nsec);
+
+       return 0;
+}
+
+int set_ve_monotonic_time(struct ve_struct *ve, struct timespec *tp)
+{
+       struct timespec kernel_tp;
+       struct k_clock *kc = clockid_to_kclock(CLOCK_MONOTONIC);
+       int error;
+
+       if (!kc)
+               return -EINVAL;
+
+       error = kc->clock_get(CLOCK_MONOTONIC, &kernel_tp);
+       if (error)
+               return error;
+
+       set_normalized_timespec(&ve->start_timespec,
+                       kernel_tp.tv_sec - tp->tv_sec,
+                       kernel_tp.tv_nsec - tp->tv_nsec);
+
+       return 0;
+}
+#endif
+
 SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
                struct timespec __user *,tp)
 {
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index e9219e6..eafef1c 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -768,6 +768,24 @@ static void ve_attach(struct cgroup *cg, struct 
cgroup_taskset *tset)
        on_each_cpu(ve_update_cpuid_faulting, NULL, 1);
 }
 
+static int ve_start_timespec_read(struct cgroup *cg, struct cftype *cft,
+                        struct seq_file *m)
+{
+       struct ve_struct *ve = cgroup_ve(cg);
+       struct timespec tp;
+       char str[42];
+       int error;
+
+       error = get_ve_monotonic_time(ve, &tp);
+       if (error)
+               return error;
+
+       snprintf(str, sizeof(str), "%ld %ld", tp.tv_sec, tp.tv_nsec);
+       seq_puts(m, str);
+
+       return 0;
+}
+
 static int ve_state_read(struct cgroup *cg, struct cftype *cft,
                         struct seq_file *m)
 {
@@ -810,6 +828,18 @@ static void ve_start_work(struct callback_head *head)
        kfree(work);
 }
 
+static int ve_start_timespec_write(struct cgroup *cg, struct cftype *cft,
+                         const char *buffer)
+{
+       struct ve_struct *ve = cgroup_ve(cg);
+       struct timespec tp;
+
+       if (sscanf(buffer, "%ld %ld\n", &tp.tv_sec, &tp.tv_nsec) != 2)
+               return -EINVAL;
+
+       return set_ve_monotonic_time(ve, &tp);
+}
+
 static int ve_state_write(struct cgroup *cg, struct cftype *cft,
                          const char *buffer)
 {
@@ -1214,6 +1244,12 @@ static struct cftype ve_cftypes[] = {
                .write_u64              = ve_write_u64,
                .private                = VE_CF_IPTABLES_MASK,
        },
+       {
+               .name                   = "start_timespec",
+               .flags                  = CFTYPE_NOT_ON_ROOT,
+               .read_seq_string        = ve_start_timespec_read,
+               .write_string           = ve_start_timespec_write,
+       },
        { }
 };
 
-- 
1.7.1

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to