[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