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

Andrew Vagin avagin at parallels.com
Mon May 20 06:01:13 EDT 2013


On Mon, May 20, 2013 at 02:24:26AM +0400, Pavel Tikhomirov wrote:
> 
> 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 :

What is about SIGEV_THREAD_ID?

> +				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;

This function is hard for reading.

> +}
> 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;

Do we really need both it_pid and it_tid?

> +	required uint32		overrun		= 8;
> +
> +	required uint64		isec		= 9;
> +	required uint64		insec		= 10;
> +	required uint64		vsec		= 11;
> +	required uint64		vnsec		= 12;
> +}
> -- 
> 1.7.9.5
> 
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu


More information about the CRIU mailing list