[CRIU] [PATCH 3/4] posix-timer: Add dump functionality and structures.

Pavel Tikhomirov snorcht at gmail.com
Sun May 19 18:24:26 EDT 2013


Signed-off-by: Pavel Tikhomirov <snorcht at gmail.com>
---
 cr-dump.c                  |   13 +++++
 cr-show.c                  |    6 +++
 image.c                    |    1 +
 include/crtools.h          |    2 +
 include/magic.h            |    1 +
 include/parasite-syscall.h |    2 +
 include/parasite.h         |   16 ++++++
 include/proc_parse.h       |   22 ++++++++
 include/protobuf.h         |    1 +
 include/util.h             |    7 +++
 parasite-syscall.c         |   65 ++++++++++++++++++++++++
 pie/parasite.c             |   27 ++++++++++
 proc_parse.c               |  121 ++++++++++++++++++++++++++++++++++++++++++++
 protobuf.c                 |    2 +
 protobuf/Makefile          |    1 +
 protobuf/posix-timer.proto |   15 ++++++
 16 files changed, 302 insertions(+)
 create mode 100644 protobuf/posix-timer.proto

diff --git a/cr-dump.c b/cr-dump.c
index 3ef53e2..ab4c45f 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1548,6 +1548,19 @@ static int dump_one_task(struct pstree_item *item)
 		goto err_cure;
 	}
 
+	struct proc_posix_timers_stat proc_args;
+	ret = parse_posix_timers(pid, &proc_args);
+	if (ret < 0){
+		pr_err("Can't read posix timers file (pid: %d)\n", pid);
+		return ret;
+	}
+
+	ret = parasite_dump_posix_timers_seized(&proc_args, parasite_ctl, cr_fdset);
+	if (ret) {
+		pr_err("Can't dump posix timers (pid: %d)\n", pid);
+		goto err_cure;
+	}
+
 	ret = dump_task_core_all(parasite_ctl, &pps_buf, &misc, &vmas, cr_fdset);
 	if (ret) {
 		pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
diff --git a/cr-show.c b/cr-show.c
index e089f67..9a3e886 100644
--- a/cr-show.c
+++ b/cr-show.c
@@ -37,6 +37,7 @@
 #include "protobuf/pipe-data.pb-c.h"
 #include "protobuf/sa.pb-c.h"
 #include "protobuf/itimer.pb-c.h"
+#include "protobuf/posix-timer.pb-c.h"
 #include "protobuf/mm.pb-c.h"
 #include "protobuf/vma.pb-c.h"
 #include "protobuf/creds.pb-c.h"
@@ -254,6 +255,11 @@ void show_itimers(int fd)
 	pb_show_plain_pretty(fd, PB_ITIMERS, "*:%Lu");
 }
 
+void show_posix_timers(int fd)
+{
+	pb_show_plain_pretty(fd, PB_POSIX_TIMERS, "*:%d 5:%Lu 9:%Lu 10:%lu 11:%Lu 12:%Lu");
+}
+
 void show_creds(int fd)
 {
 	pb_show_vertical(fd, PB_CREDS);
diff --git a/image.c b/image.c
index 918a8f6..e1febe2 100644
--- a/image.c
+++ b/image.c
@@ -144,6 +144,7 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
 	FD_ENTRY(NETLINKSK,	"netlinksk",	 show_netlinksk),
 	FD_ENTRY(SK_QUEUES,	"sk-queues",	 show_sk_queues),
 	FD_ENTRY(ITIMERS,	"itimers-%d",	 show_itimers),
+	FD_ENTRY(POSIX_TIMERS,	"posix-timers-%d",	 show_posix_timers),
 	FD_ENTRY(CREDS,		"creds-%d",	 show_creds),
 	FD_ENTRY(UTSNS,		"utsns-%d",	 show_utsns),
 	FD_ENTRY(IPCNS_VAR,	"ipcns-var-%d",	 show_ipc_var),
diff --git a/include/crtools.h b/include/crtools.h
index 8aa46ba..cc03881 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -29,6 +29,7 @@ enum {
 	CR_FD_VMAS,
 	CR_FD_SIGACT,
 	CR_FD_ITIMERS,
+	CR_FD_POSIX_TIMERS,
 	CR_FD_CREDS,
 	CR_FD_FS,
 	CR_FD_RLIMIT,
@@ -173,6 +174,7 @@ void show_pstree(int fd);
 void show_sigacts(int fd);
 void show_siginfo(int fd);
 void show_itimers(int fd);
+void show_posix_timers(int fd);
 void show_creds(int fd);
 void show_fs(int fd);
 void show_remap_files(int fd);
diff --git a/include/magic.h b/include/magic.h
index a530265..566fea3 100644
--- a/include/magic.h
+++ b/include/magic.h
@@ -38,6 +38,7 @@
 #define INETSK_MAGIC		0x56443851 /* Pereslavl */
 #define PACKETSK_MAGIC		0x60454618 /* Veliky Ustyug */
 #define ITIMERS_MAGIC		0x57464056 /* Kostroma */
+#define POSIX_TIMERS_MAGIC	0x52603957 /* Lipetsk */
 #define SK_QUEUES_MAGIC		0x56264026 /* Suzdal */
 #define UTSNS_MAGIC		0x54473203 /* Smolensk */
 #define CREDS_MAGIC		0x54023547 /* Kozelsk */
diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index 4441592..b3ff12e 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -33,6 +33,8 @@ struct list_head;
 
 extern int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset);
 extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset);
+struct proc_posix_timers_stat;
+extern int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args, struct parasite_ctl *ctl, struct cr_fdset *cr_fdset);
 
 void *parasite_args_s(struct parasite_ctl *ctl, int args_size);
 int parasite_execute(unsigned int cmd, struct parasite_ctl *ctl);
diff --git a/include/parasite.h b/include/parasite.h
index d3fa28a..331949b 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -13,6 +13,8 @@
 #include "image.h"
 #include "util-net.h"
 
+#include <time.h>
+
 #include "protobuf/vma.pb-c.h"
 
 #define __head __used __section(.head.text)
@@ -29,6 +31,7 @@ enum {
 
 	PARASITE_CMD_DUMP_SIGACTS,
 	PARASITE_CMD_DUMP_ITIMERS,
+	PARASITE_CMD_DUMP_POSIX_TIMERS,
 	PARASITE_CMD_DUMP_MISC,
 	PARASITE_CMD_DUMP_CREDS,
 	PARASITE_CMD_DUMP_THREAD,
@@ -88,6 +91,19 @@ struct parasite_dump_itimers_args {
 	struct itimerval prof;
 };
 
+struct posix_timer {
+	int it_id;
+	struct itimerspec val;
+	int overrun;
+};
+
+struct parasite_dump_posix_timers_args {
+	int timer_n;
+	struct posix_timer timer[0];
+	//to dump list of timers  //define some 512
+	//why 0 is OK? and won't it overflow args?
+};
+
 /*
  * Misc sfuff, that is too small for separate file, but cannot
  * be read w/o using parasite
diff --git a/include/proc_parse.h b/include/proc_parse.h
index 9459872..b09c417 100644
--- a/include/proc_parse.h
+++ b/include/proc_parse.h
@@ -117,6 +117,26 @@ struct mount_info {
 	struct list_head siblings;
 };
 
+struct proc_posix_timer {
+	struct list_head list;
+	int it_id;
+	int clock_id;
+	int si_signo;
+	int it_sigev_notify;
+	union{
+		void * p;
+		long unsigned int i;
+	} sival_ptr;
+
+	int it_pid;
+	int it_tid;
+};
+
+struct proc_posix_timers_stat {
+	int timer_n;
+	struct list_head timers; //[512];
+};
+
 extern struct mount_info *mnt_entry_alloc();
 extern void mnt_entry_free(struct mount_info *mi);
 
@@ -141,4 +161,6 @@ extern int parse_fdinfo(int fd, int type,
 extern int parse_cpuinfo_features(int (*handler)(char *tok));
 extern int parse_file_locks(void);
 
+extern int parse_posix_timers(pid_t pid, struct proc_posix_timers_stat * args);
+
 #endif /* __CR_PROC_PARSE_H__ */
diff --git a/include/protobuf.h b/include/protobuf.h
index 5b0ef75..2bf025b 100644
--- a/include/protobuf.h
+++ b/include/protobuf.h
@@ -14,6 +14,7 @@ enum {
 	PB_VMAS,
 	PB_SIGACT,
 	PB_ITIMERS,
+	PB_POSIX_TIMERS,
 	PB_CREDS,
 	PB_FS,
 	PB_UTSNS,
diff --git a/include/util.h b/include/util.h
index 1b466c0..e08a6fa 100644
--- a/include/util.h
+++ b/include/util.h
@@ -275,6 +275,13 @@ static inline bool dir_dots(struct dirent *de)
 
 extern int read_fd_link(int lfd, char *buf, size_t size);
 
+#define alloc_posix_timer()					\
+	({							\
+		struct proc_posix_timer *p__			\
+			= xzalloc(sizeof(*p__));		\
+		p__;						\
+	})
+
 #define USEC_PER_SEC	1000000L
 
 #endif /* __CR_UTIL_H__ */
diff --git a/parasite-syscall.c b/parasite-syscall.c
index c02f426..164e5b3 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -8,6 +8,7 @@
 #include "protobuf.h"
 #include "protobuf/sa.pb-c.h"
 #include "protobuf/itimer.pb-c.h"
+#include "protobuf/posix-timer.pb-c.h"
 #include "protobuf/creds.pb-c.h"
 #include "protobuf/core.pb-c.h"
 #include "protobuf/pagemap.pb-c.h"
@@ -24,6 +25,8 @@
 #include "net.h"
 #include "mem.h"
 
+#include "proc_parse.h"
+
 #include <string.h>
 #include <stdlib.h>
 
@@ -438,6 +441,67 @@ int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_f
 	return ret;
 }
 
+static int dump_one_posix_timer(struct posix_timer *v, struct proc_posix_timer *vp, int fd)
+{
+	PosixTimerEntry pte = POSIX_TIMER_ENTRY__INIT;
+
+	pte.it_id = vp->it_id;
+	pte.clock_id = vp->clock_id;
+	pte.si_signo = vp->si_signo;
+	pte.it_sigev_notify = vp->it_sigev_notify;
+	pte.sival_ptr = vp->sival_ptr.i; //pointer to int through union
+	pte.it_pid = vp->it_pid;
+	pte.it_tid = vp->it_tid;
+
+	pte.overrun = v->overrun;
+
+	pte.isec = v->val.it_interval.tv_sec;
+	pte.insec = v->val.it_interval.tv_nsec;
+	pte.vsec = v->val.it_value.tv_sec;
+	pte.vnsec = v->val.it_value.tv_nsec;
+
+	return pb_write_one(fd, &pte, PB_POSIX_TIMERS);
+}
+
+int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args, struct parasite_ctl *ctl, struct cr_fdset *cr_fdset)
+{
+	struct parasite_dump_posix_timers_args * args;
+	struct proc_posix_timer *temp;
+	int i, fd;
+	int ret = 0;
+
+	args = parasite_args_s(ctl, sizeof(int) + sizeof(struct posix_timer) * proc_args->timer_n);
+	args->timer_n = proc_args->timer_n;
+
+	i = 0;
+	list_for_each_entry(temp, &proc_args->timers, list) {
+		args->timer[i].it_id = temp->it_id;
+		i++;
+	}
+
+	ret = parasite_execute(PARASITE_CMD_DUMP_POSIX_TIMERS, ctl);
+	if (ret < 0)
+		goto end_posix;
+
+	fd = fdset_fd(cr_fdset, CR_FD_POSIX_TIMERS);
+
+	i = 0;
+	list_for_each_entry(temp, &proc_args->timers, list) {
+		ret = dump_one_posix_timer(&args->timer[i], temp, fd);
+		i++;
+		if (ret)
+			goto end_posix;
+	}
+
+end_posix:
+	while (!list_empty(&proc_args->timers)) {
+		temp = list_first_entry(&proc_args->timers, struct proc_posix_timer, list);
+		list_del(&temp->list);
+		xfree(temp);
+	}
+	return ret;
+}
+
 int parasite_dump_misc_seized(struct parasite_ctl *ctl, struct parasite_dump_misc *misc)
 {
 	struct parasite_dump_misc *ma;
@@ -499,6 +563,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl,
 	if (ret) {
 		pr_err("Parasite failed to drain descriptors\n");
 		goto err;
+
 	}
 
 	ret = recv_fds(ctl->tsock, lfds, dfds->nr_fds, opts);
diff --git a/pie/parasite.c b/pie/parasite.c
index 7d505ec..f32c507 100644
--- a/pie/parasite.c
+++ b/pie/parasite.c
@@ -111,6 +111,31 @@ static int dump_itimers(struct parasite_dump_itimers_args *args)
 	return ret;
 }
 
+static int dump_posix_timers(struct parasite_dump_posix_timers_args *args)
+{
+	int i;
+	int ret = 0;
+
+	for(i = 0; i < args->timer_n; i++){
+		ret = sys_timer_gettime(args->timer[i].it_id, &args->timer[i].val);
+		if (ret == -1) {
+			pr_err("sys_timer_gettime failed\n");
+			return ret;
+		}
+		args->timer[i].overrun = sys_timer_getoverrun(args->timer[i].it_id);
+		ret = args->timer[i].overrun;
+		if (ret == -1) {
+			pr_err("sys_timer_getoverrun failed\n");
+			return ret;
+		}
+	}
+
+	if (ret < 0)
+		pr_err("getposixtimer failed\n");
+
+	return ret;
+}
+
 static int dump_misc(struct parasite_dump_misc *args)
 {
 	args->brk = sys_brk(0);
@@ -451,6 +476,8 @@ int __used parasite_service(unsigned int cmd, void *args)
 		return dump_sigact(args);
 	case PARASITE_CMD_DUMP_ITIMERS:
 		return dump_itimers(args);
+	case PARASITE_CMD_DUMP_POSIX_TIMERS:
+		return dump_posix_timers(args);
 	case PARASITE_CMD_DUMP_MISC:
 		return dump_misc(args);
 	case PARASITE_CMD_DUMP_CREDS:
diff --git a/proc_parse.c b/proc_parse.c
index 049a605..669c6e6 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -1145,3 +1145,124 @@ err:
 	fclose(fl_locks);
 	return ret;
 }
+
+int parse_posix_timers(pid_t pid, struct proc_posix_timers_stat *args)
+{
+	int i;
+	int ret = 0;
+	int get = 0;
+	char * str_path;
+
+	FILE * file;
+	char * line1 = NULL;
+	char * line2 = NULL;
+	char * line3 = NULL;
+	char * line4 = NULL;
+	size_t len1 = 0;
+	size_t len2 = 0;
+	size_t len3 = 0;
+	size_t len4 = 0;
+
+	char * siginfo;
+	char siginfo_tmp[20];
+	char sigpid[7];
+	char tidpid[4];
+
+	char str_name[10];
+	struct proc_posix_timer *timer = NULL;
+
+	INIT_LIST_HEAD(&args->timers);
+	args->timer_n = 0;
+
+	str_path = malloc(snprintf(NULL, 0, "/proc/%d/timers", pid) + 1);
+	sprintf(str_path, "/proc/%d/timers", pid);
+
+	file = fopen(str_path, "r");
+	if (file == NULL) {
+		pr_perror("Can't open posix timers file!");
+		free(str_path);
+		ret = -1;
+		goto end_posix;
+	}
+	free(str_path);
+
+	while (1) {
+		get = getline(&line1, &len1, file);
+		if (get == -1)
+			goto end_posix;
+		get = getline(&line2, &len2, file);
+		if (get == -1)
+			goto end_posix;
+		get = getline(&line3, &len3, file);
+		if (get == -1)
+			goto end_posix;
+		get = getline(&line4, &len4, file);
+		if (get == -1)
+			goto end_posix;
+
+		timer = alloc_posix_timer();
+
+		ret = sscanf(line1, "%s %d", str_name, &timer->it_id);
+		if (ret != 2 || str_name[0] != 'I')
+			goto parse_err_posix;
+		ret = sscanf(line2, "%s %d%s", str_name, &timer->si_signo, siginfo_tmp);
+		if (ret != 3 || str_name[0] != 's')
+			goto parse_err_posix;
+		siginfo=&siginfo_tmp[1];
+		ret = sscanf(siginfo, "%p", &timer->sival_ptr.p);
+		if (ret != 1)
+			goto parse_err_posix;
+		for (i = 0; i<len3; i++) {
+			if (line3[i] == '/' || line3[i] == '.') {
+				line3[i] = ' ';
+			}
+		}
+		ret = sscanf(line3, "%s %s %s %d", str_name, sigpid, tidpid, &timer->it_pid);
+		if (ret != 4 || str_name[0] != 'n')
+			goto parse_err_posix;
+		switch ( sigpid[0]) {
+			case 's' :
+				timer->it_sigev_notify = SIGEV_SIGNAL;
+				break;
+			case 't' :
+				timer->it_sigev_notify = SIGEV_THREAD;
+				break;
+			default :
+				timer->it_sigev_notify = SIGEV_NONE;
+				break;
+		}
+		if ( tidpid[0] == 't') {
+			timer->it_tid = timer->it_pid;
+			timer->it_pid = 0;
+		} else {
+			timer->it_tid = 0;
+		}
+
+		ret = sscanf(line4, "%s %d", str_name, &timer->clock_id);
+		if (ret != 2 || str_name[0] != 'C')
+			goto parse_err_posix;
+		list_add(&timer->list, &args->timers);
+		timer = NULL;
+		args->timer_n++;
+	}
+parse_err_posix:
+	while (!list_empty(&args->timers)) {
+		timer = list_first_entry(&args->timers, struct proc_posix_timer, list);
+		list_del(&timer->list);
+		xfree(timer);
+	}
+	pr_perror("Parse error in posix timers proc file!");
+	ret = -1;
+end_posix:
+	if (line1)
+		free(line1);
+	if (line2)
+		free(line2);
+	if (line3)
+		free(line3);
+	line1 = line2 = line3 = NULL;
+
+	if (file != NULL)
+		fclose(file);
+	return ret;
+}
diff --git a/protobuf.c b/protobuf.c
index ee83c7d..35a981c 100644
--- a/protobuf.c
+++ b/protobuf.c
@@ -38,6 +38,7 @@
 #include "protobuf/sk-packet.pb-c.h"
 #include "protobuf/creds.pb-c.h"
 #include "protobuf/itimer.pb-c.h"
+#include "protobuf/posix-timer.pb-c.h"
 #include "protobuf/utsns.pb-c.h"
 #include "protobuf/ipc-var.pb-c.h"
 #include "protobuf/ipc-shm.pb-c.h"
@@ -118,6 +119,7 @@ void cr_pb_init(void)
 	CR_PB_DESC(INETSK,		InetSk,		inet_sk);
 	CR_PB_DESC(SK_QUEUES,		SkPacket,	sk_packet);
 	CR_PB_DESC(ITIMERS,		Itimer,		itimer);
+	CR_PB_DESC(POSIX_TIMERS,	PosixTimer,	posix_timer);
 	CR_PB_DESC(CREDS,		Creds,		creds);
 	CR_PB_DESC(UTSNS,		Utsns,		utsns);
 	CR_PB_DESC(IPCNS_VAR,		IpcVar,		ipc_var);
diff --git a/protobuf/Makefile b/protobuf/Makefile
index 94a9652..2ee77b9 100644
--- a/protobuf/Makefile
+++ b/protobuf/Makefile
@@ -34,6 +34,7 @@ proto-obj-y	+= mnt.o
 proto-obj-y	+= pipe-data.o
 proto-obj-y	+= sa.o
 proto-obj-y	+= itimer.o
+proto-obj-y	+= posix-timer.o
 proto-obj-y	+= mm.o
 proto-obj-y	+= sk-opts.o
 proto-obj-y	+= sk-unix.o
diff --git a/protobuf/posix-timer.proto b/protobuf/posix-timer.proto
new file mode 100644
index 0000000..86051e0
--- /dev/null
+++ b/protobuf/posix-timer.proto
@@ -0,0 +1,15 @@
+message posix_timer_entry {
+	required uint32 	it_id 		= 1;
+	required uint32		clock_id	= 2;
+	required uint32 	si_signo	= 3;
+	required uint32		it_sigev_notify = 4;
+	required uint64		sival_ptr	= 5;
+	required uint32		it_pid		= 6;
+	required uint32		it_tid		= 7;
+	required uint32		overrun		= 8;
+
+	required uint64		isec		= 9;
+	required uint64		insec		= 10;
+	required uint64		vsec		= 11;
+	required uint64		vnsec		= 12;
+}
-- 
1.7.9.5



More information about the CRIU mailing list