[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