[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