[CRIU] [PATCH 1/3] time: Write general clock settings at moment of time
Cyrill Gorcunov
gorcunov at gmail.com
Tue Feb 2 07:53:45 PST 2016
When migrating to another machine we rather ignore the time
difference between clocks. For resource just as timers
it's fine because we keep remaining time in the image
and restore it back. But such difference might affect
time sensitive applications which keep clock data
somewhere in own memory.
For their sake we save clocks (realtime, monotonic,
boottime) in the "dump-time" image and on restore
stage will export the delta time.
https://jira.sw.ru/browse/PSBM-41406
Signed-off-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
---
Makefile.crtools | 1 +
cr-dump.c | 4 +++
image-desc.c | 1 +
include/image-desc.h | 1 +
include/magic.h | 1 +
include/protobuf-desc.h | 1 +
include/time.h | 24 +++++++++++++
protobuf/time.proto | 16 +++++++++
time.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 140 insertions(+)
create mode 100644 include/time.h
create mode 100644 time.c
diff --git a/Makefile.crtools b/Makefile.crtools
index 5788ef0..96bd121 100644
--- a/Makefile.crtools
+++ b/Makefile.crtools
@@ -78,6 +78,7 @@ obj-y += fault-injection.o
obj-y += pie/util-fd.o
obj-y += pie/util.o
obj-y += seccomp.o
+obj-y += time.o
ifneq ($(MAKECMDGOALS),clean)
incdeps := y
diff --git a/cr-dump.c b/cr-dump.c
index 4ac3eed..b9fdb3e 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -81,6 +81,7 @@
#include "seccomp.h"
#include "seize.h"
#include "fault-injection.h"
+#include "time.h"
#include "asm/dump.h"
@@ -1666,6 +1667,9 @@ int cr_dump_tasks(pid_t pid)
if (!glob_imgset)
goto err;
+ if (dump_time_write())
+ goto err;
+
if (collect_seccomp_filters() < 0)
goto err;
diff --git a/image-desc.c b/image-desc.c
index 9fb96c8..d85c88f 100644
--- a/image-desc.c
+++ b/image-desc.c
@@ -95,6 +95,7 @@ struct cr_fd_desc_tmpl imgset_template[CR_FD_MAX] = {
FD_ENTRY(CPUINFO, "cpuinfo"),
FD_ENTRY(SECCOMP, "seccomp"),
FD_ENTRY(USERNS, "userns-%d"),
+ FD_ENTRY(DUMP_TIME, "dump-time"),
[CR_FD_STATS] = {
.fmt = "stats-%s",
diff --git a/include/image-desc.h b/include/image-desc.h
index 90933e9..5633397 100644
--- a/include/image-desc.h
+++ b/include/image-desc.h
@@ -78,6 +78,7 @@ enum {
CR_FD_TIMERFD,
CR_FD_FILE_LOCKS,
CR_FD_SECCOMP,
+ CR_FD_DUMP_TIME,
_CR_FD_GLOB_TO,
CR_FD_TMPFS_IMG,
diff --git a/include/magic.h b/include/magic.h
index 3cb3766..a270aa6 100644
--- a/include/magic.h
+++ b/include/magic.h
@@ -91,6 +91,7 @@
#define USERNS_MAGIC 0x55474906 /* Kazan */
#define SECCOMP_MAGIC 0x64413049 /* Kostomuksha */
#define BINFMT_MISC_MAGIC 0x67343323 /* Apatity */
+#define DUMP_TIME_MAGIC 0x67093224 /* Kandalaksha */
#define IFADDR_MAGIC RAW_IMAGE_MAGIC
#define ROUTE_MAGIC RAW_IMAGE_MAGIC
diff --git a/include/protobuf-desc.h b/include/protobuf-desc.h
index bb66a86..54482bf 100644
--- a/include/protobuf-desc.h
+++ b/include/protobuf-desc.h
@@ -57,6 +57,7 @@ enum {
PB_USERNS,
PB_NETNS,
PB_BINFMT_MISC, /* 50 */
+ PB_DUMP_TIME,
/* PB_AUTOGEN_STOP */
diff --git a/include/time.h b/include/time.h
new file mode 100644
index 0000000..8ae3516
--- /dev/null
+++ b/include/time.h
@@ -0,0 +1,24 @@
+#ifndef __CR_TIME_H__
+#define __CR_TIME_H__
+
+#include <time.h>
+
+#include "protobuf/time.pb-c.h"
+
+/* realtime, monotonic, boottime */
+#define NR_CLOCKSET_CLOCKS 3
+
+typedef struct {
+ clockid_t clockid[NR_CLOCKSET_CLOCKS];
+ const char *name[NR_CLOCKSET_CLOCKS];
+ struct timespec ts[NR_CLOCKSET_CLOCKS];
+} clockset_t;
+
+typedef struct {
+ Timespec ts[NR_CLOCKSET_CLOCKS];
+} pb_clockset_t;
+
+extern int clockset_get(clockset_t *clockset);
+extern int dump_time_write(void);
+
+#endif /* __CR_TIME_H__ */
diff --git a/protobuf/time.proto b/protobuf/time.proto
index 09cdf42..221a542 100644
--- a/protobuf/time.proto
+++ b/protobuf/time.proto
@@ -2,3 +2,19 @@ message timeval {
required uint64 tv_sec = 1;
required uint64 tv_usec = 2;
}
+
+message timespec {
+ required uint64 tv_sec = 1;
+ required uint64 tv_nsec = 2;
+}
+
+message clockset_entry {
+ required timespec clock_real = 2;
+ required timespec clock_mono = 3;
+ required timespec clock_boot = 4;
+}
+
+message dump_time_entry {
+ required clockset_entry clocks = 1;
+ optional string date = 2;
+}
diff --git a/time.c b/time.c
new file mode 100644
index 0000000..8cef4f0
--- /dev/null
+++ b/time.c
@@ -0,0 +1,91 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "log.h"
+#include "time.h"
+#include "imgset.h"
+
+#include "protobuf.h"
+
+#undef LOG_PREFIX
+#define LOG_PREFIX "time: "
+
+static void clockset_to_pb(clockset_t *clockset, pb_clockset_t *pb_clockset)
+{
+ size_t i;
+
+ for (i = 0; i < NR_CLOCKSET_CLOCKS; i++) {
+ timespec__init(&pb_clockset->ts[i]);
+
+ pb_clockset->ts[i].tv_sec = clockset->ts[i].tv_sec;
+ pb_clockset->ts[i].tv_nsec = clockset->ts[i].tv_nsec;
+ }
+}
+
+int clockset_get(clockset_t *clockset)
+{
+ static const struct {
+ clockid_t clockid;
+ const char *name;
+ } t[NR_CLOCKSET_CLOCKS] = {
+ [0] = {
+ .clockid = CLOCK_REALTIME,
+ .name = "CLOCK_REALTIME",
+ },
+ [1] = {
+ .clockid = CLOCK_MONOTONIC,
+ .name = "CLOCK_MONOTONIC",
+ },
+ [2] = {
+ .clockid = CLOCK_BOOTTIME,
+ .name = "CLOCK_BOOTTIME",
+ },
+ };
+
+ size_t i;
+
+ for (i = 0; i < NR_CLOCKSET_CLOCKS; i++) {
+ clockset->clockid[i] = t[i].clockid;
+ clockset->name[i] = t[i].name;
+
+ if (clock_gettime(t[i].clockid, &clockset->ts[i])) {
+ pr_perror("Can't get time for %s\n", t[i].name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int dump_time_write(void)
+{
+ DumpTimeEntry dump_time_entry = DUMP_TIME_ENTRY__INIT;
+ ClocksetEntry clockset_entry = CLOCKSET_ENTRY__INIT;
+ pb_clockset_t pb_clockset;
+ clockset_t clockset;
+ char str[32] = { };
+ struct tm tm;
+
+ tm = *localtime(&(time_t){time(NULL)});
+
+ if (clockset_get(&clockset))
+ return -1;
+ clockset_to_pb(&clockset, &pb_clockset);
+
+ clockset_entry.clock_real = &pb_clockset.ts[0];
+ clockset_entry.clock_mono = &pb_clockset.ts[1];
+ clockset_entry.clock_boot = &pb_clockset.ts[2];
+
+ asctime_r(&tm, str);
+ if (str[0] && str[strlen(str) - 1] == '\n')
+ str[strlen(str) - 1] = '\0';
+
+ dump_time_entry.clocks = &clockset_entry;
+ dump_time_entry.date = str;
+
+ return pb_write_one(img_from_set(glob_imgset, CR_FD_DUMP_TIME),
+ &dump_time_entry, PB_DUMP_TIME);
+}
--
2.5.0
More information about the CRIU
mailing list