[CRIU] [PATCH] [RFC] support for dumping anon:[timerfd]

Shawn Landden shawn at churchofgit.com
Tue Feb 4 16:51:15 PST 2014


How do I properly pack arguments for cr_exec()?

Signed-off-by: Shawn Landden <shawn at churchofgit.com>
---
 .gitignore              |   1 +
 Makefile.crtools        |   1 +
 eventfd.c               |   2 +-
 eventpoll.c             |   2 +-
 fifo.c                  |   2 +-
 files-ext.c             |   2 +-
 files-reg.c             |   2 +-
 files.c                 |   5 +-
 fsnotify.c              |   4 +-
 image-desc.c            |   1 +
 include/files.h         |   2 +-
 include/image-desc.h    |   1 +
 include/magic.h         |   1 +
 include/proc_parse.h    |   2 +
 include/protobuf-desc.h |   1 +
 namespaces.c            |   2 +-
 pipes.c                 |   2 +-
 proc_parse.c            |  16 ++++++
 protobuf-desc.c         |   1 +
 protobuf/Makefile       |   1 +
 protobuf/fdinfo.proto   |   1 +
 protobuf/timer.proto    |   1 +
 protobuf/timerfd.proto  |  10 ++++
 signalfd.c              |   4 +-
 sk-inet.c               |   4 +-
 sk-netlink.c            |   2 +-
 sk-packet.c             |   2 +-
 sk-unix.c               |   2 +-
 timerfd.c               | 150 ++++++++++++++++++++++++++++++++++++++++++++++++
 tty.c                   |   4 +-
 tun.c                   |   4 +-
 31 files changed, 213 insertions(+), 22 deletions(-)
 create mode 100644 protobuf/timerfd.proto
 create mode 100644 timerfd.c

diff --git a/.gitignore b/.gitignore
index 9e403ce..6394161 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+*~
 *.o
 *.d
 *.img
diff --git a/Makefile.crtools b/Makefile.crtools
index 094013e..cf8bcba 100644
--- a/Makefile.crtools
+++ b/Makefile.crtools
@@ -39,6 +39,7 @@ obj-y	+= ipc_ns.o
 obj-y	+= netfilter.o
 obj-y	+= shmem.o
 obj-y	+= eventfd.o
+obj-y	+= timerfd.o
 obj-y	+= eventpoll.o
 obj-y	+= mount.o
 obj-y	+= fsnotify.o
diff --git a/eventfd.c b/eventfd.c
index d4e7bf8..761bcc2 100644
--- a/eventfd.c
+++ b/eventfd.c
@@ -80,7 +80,7 @@ const struct fdtype_ops eventfd_dump_ops = {
 	.dump		= dump_one_eventfd,
 };
 
-static int eventfd_open(struct file_desc *d)
+static int eventfd_open(struct file_desc *d, int pid)
 {
 	struct eventfd_file_info *info;
 	int tmp;
diff --git a/eventpoll.c b/eventpoll.c
index d82c19e..7f66c05 100644
--- a/eventpoll.c
+++ b/eventpoll.c
@@ -88,7 +88,7 @@ const struct fdtype_ops eventpoll_dump_ops = {
 	.dump		= dump_one_eventpoll,
 };
 
-static int eventpoll_open(struct file_desc *d)
+static int eventpoll_open(struct file_desc *d, int pid)
 {
 	struct eventpoll_file_info *info;
 	int tmp;
diff --git a/fifo.c b/fifo.c
index 67d7f56..f025995 100644
--- a/fifo.c
+++ b/fifo.c
@@ -105,7 +105,7 @@ out:
 	return new_fifo;
 }
 
-static int open_fifo_fd(struct file_desc *d)
+static int open_fifo_fd(struct file_desc *d, int pid)
 {
 	struct fifo_info *info = container_of(d, struct fifo_info, d);
 
diff --git a/files-ext.c b/files-ext.c
index cd434ee..c6ab60e 100644
--- a/files-ext.c
+++ b/files-ext.c
@@ -37,7 +37,7 @@ struct ext_file_info {
 	ExtFileEntry		*xfe;
 };
 
-static int open_fd(struct file_desc *d)
+static int open_fd(struct file_desc *d, int pid)
 {
 	struct ext_file_info *xfi;
 	int fd;
diff --git a/files-reg.c b/files-reg.c
index f98c792..31d1a1d 100644
--- a/files-reg.c
+++ b/files-reg.c
@@ -653,7 +653,7 @@ static int do_open_reg(struct reg_file_info *rfi, void *arg)
 	return fd;
 }
 
-static int open_fe_fd(struct file_desc *fd)
+static int open_fe_fd(struct file_desc *fd, int pid)
 {
 	return open_path(fd, do_open_reg, NULL);
 }
diff --git a/files.c b/files.c
index df0e2f1..84b19c0 100644
--- a/files.c
+++ b/files.c
@@ -27,6 +27,7 @@
 #include "pipes.h"
 #include "fifo.h"
 #include "eventfd.h"
+#include "timerfd.h"
 #include "eventpoll.h"
 #include "fsnotify.h"
 #include "signalfd.h"
@@ -326,6 +327,8 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
 			ops = &fanotify_dump_ops;
 		else if (is_signalfd_link(lfd))
 			ops = &signalfd_dump_ops;
+		else if (is_timerfd_link(lfd))
+			ops = &timerfd_dump_ops;
 		else {
 			char more[64];
 
@@ -856,7 +859,7 @@ static int open_fd(int pid, struct fdinfo_list_entry *fle)
 	if (fle != file_master(d))
 		return 0;
 
-	new_fd = d->ops->open(d);
+	new_fd = d->ops->open(d, pid);
 	if (new_fd < 0)
 		return -1;
 
diff --git a/fsnotify.c b/fsnotify.c
index a9412a0..f339f1b 100644
--- a/fsnotify.c
+++ b/fsnotify.c
@@ -429,7 +429,7 @@ err:
 	return ret;
 }
 
-static int open_inotify_fd(struct file_desc *d)
+static int open_inotify_fd(struct file_desc *d, int pid)
 {
 	struct fsnotify_file_info *info;
 	struct fsnotify_mark_info *wd_info;
@@ -457,7 +457,7 @@ static int open_inotify_fd(struct file_desc *d)
 	return tmp;
 }
 
-static int open_fanotify_fd(struct file_desc *d)
+static int open_fanotify_fd(struct file_desc *d, int pid)
 {
 	struct fsnotify_file_info *info;
 	struct fsnotify_mark_info *mark;
diff --git a/image-desc.c b/image-desc.c
index aa879e6..1e8950e 100644
--- a/image-desc.c
+++ b/image-desc.c
@@ -26,6 +26,7 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
 	FD_ENTRY(EXT_FILES,	"ext-files"),
 	FD_ENTRY(NS_FILES,	"ns-files"),
 	FD_ENTRY(EVENTFD_FILE,	"eventfd"),
+	FD_ENTRY(TIMERFD_FILE,	"timerfd"),
 	FD_ENTRY(EVENTPOLL_FILE,"eventpoll"),
 	FD_ENTRY(EVENTPOLL_TFD,	"eventpoll-tfd"),
 	FD_ENTRY(SIGNALFD,	"signalfd"),
diff --git a/include/files.h b/include/files.h
index 975470f..9128f5b 100644
--- a/include/files.h
+++ b/include/files.h
@@ -83,7 +83,7 @@ struct file_desc_ops {
 	 * The returned descriptor may be closed (dup2-ed to another)
 	 * so it shouldn't be saved for any post-actions.
 	 */
-	int			(*open)(struct file_desc *d);
+	int			(*open)(struct file_desc *d, int pid);
 	/*
 	 * Called on a file when all files of that type are opened
 	 * and with the fd being the "restored" one.
diff --git a/include/image-desc.h b/include/image-desc.h
index f43ad43..32b1177 100644
--- a/include/image-desc.h
+++ b/include/image-desc.h
@@ -72,6 +72,7 @@ enum {
 	CR_FD_EVENTPOLL_FILE,
 	CR_FD_EVENTPOLL_TFD,
 	CR_FD_SIGNALFD,
+	CR_FD_TIMERFD_FILE,
 	CR_FD_INOTIFY_FILE,
 	CR_FD_INOTIFY_WD,
 	CR_FD_FANOTIFY_FILE,
diff --git a/include/magic.h b/include/magic.h
index dfcf31d..e4460cb 100644
--- a/include/magic.h
+++ b/include/magic.h
@@ -53,6 +53,7 @@
 #define GHOST_FILE_MAGIC	0x52583605 /* Oryol */
 #define TCP_STREAM_MAGIC	0x51465506 /* Orenburg */
 #define EVENTFD_FILE_MAGIC	0x44523722 /* Anapa */
+#define TIMERFD_FILE_MAGIC	0x48551221 /* Nooksack WA USA */
 #define EVENTPOLL_FILE_MAGIC	0x45023858 /* Krasnodar */
 #define EVENTPOLL_TFD_MAGIC	0x44433746 /* Novorossiysk */
 #define SIGNALFD_MAGIC		0x57323820 /* Uglich */
diff --git a/include/proc_parse.h b/include/proc_parse.h
index 7fbf4aa..d684764 100644
--- a/include/proc_parse.h
+++ b/include/proc_parse.h
@@ -9,6 +9,7 @@
 #include "protobuf/eventpoll.pb-c.h"
 #include "protobuf/signalfd.pb-c.h"
 #include "protobuf/fsnotify.pb-c.h"
+#include "protobuf/timerfd.pb-c.h"
 
 #define PROC_TASK_COMM_LEN	32
 #define PROC_TASK_COMM_LEN_FMT	"(%31s"
@@ -145,6 +146,7 @@ extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
 
 union fdinfo_entries {
 	EventfdFileEntry efd;
+	TimerfdFileEntry tfd;
 	EventpollTfdEntry epl;
 	SignalfdEntry sfd;
 	InotifyWdEntry ify;
diff --git a/include/protobuf-desc.h b/include/protobuf-desc.h
index fa9dd61..5bb8452 100644
--- a/include/protobuf-desc.h
+++ b/include/protobuf-desc.h
@@ -13,6 +13,7 @@ enum {
 	PB_VMA,
 	PB_ITIMER,
 	PB_POSIX_TIMER,
+	PB_TIMERFD_FILE,
 	PB_CREDS,
 	PB_FS,
 	PB_UTSNS,		/* 10 */
diff --git a/namespaces.c b/namespaces.c
index 37e232c..60a439b 100644
--- a/namespaces.c
+++ b/namespaces.c
@@ -227,7 +227,7 @@ struct ns_file_info {
 	NsFileEntry		*nfe;
 };
 
-static int open_ns_fd(struct file_desc *d)
+static int open_ns_fd(struct file_desc *d, int pid)
 {
 	struct ns_file_info *nfi = container_of(d, struct ns_file_info, d);
 	struct pstree_item *item, *t;
diff --git a/pipes.c b/pipes.c
index ef260aa..05d01e3 100644
--- a/pipes.c
+++ b/pipes.c
@@ -292,7 +292,7 @@ static int recv_pipe_fd(struct pipe_info *pi)
 	return fd;
 }
 
-static int open_pipe(struct file_desc *d)
+static int open_pipe(struct file_desc *d, int pid)
 {
 	struct pipe_info *pi, *p;
 	int ret, tmp;
diff --git a/proc_parse.c b/proc_parse.c
index 55d7c78..0ebe11b 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -1002,6 +1002,22 @@ static int parse_fdinfo_pid_s(char *pid, int fd, int type,
 			entry_met = true;
 			continue;
 		}
+		if (fdinfo_field(str, "clockid")) {
+			timerfd_file_entry__init(&entry.tfd);
+
+			if (type != FD_TYPES__TIMERFD)
+				goto parse_err;
+			ret = sscanf(str, "clockid: %d",
+					(int *)&entry.tfd.clockid);
+			if (ret != 1)
+				goto parse_err;
+			ret = cb(&entry, arg);
+			if (ret)
+				goto out;
+
+			entry_met = true;
+			continue;
+		}
 		if (fdinfo_field(str, "fanotify flags")) {
 			struct fsnotify_params *p = arg;
 
diff --git a/protobuf-desc.c b/protobuf-desc.c
index a86ec38..9da2feb 100644
--- a/protobuf-desc.c
+++ b/protobuf-desc.c
@@ -38,6 +38,7 @@
 #include "protobuf/sk-packet.pb-c.h"
 #include "protobuf/creds.pb-c.h"
 #include "protobuf/timer.pb-c.h"
+#include "protobuf/timerfd.pb-c.h"
 #include "protobuf/utsns.pb-c.h"
 #include "protobuf/ipc-var.pb-c.h"
 #include "protobuf/ipc-shm.pb-c.h"
diff --git a/protobuf/Makefile b/protobuf/Makefile
index 2bfd696..85a6a92 100644
--- a/protobuf/Makefile
+++ b/protobuf/Makefile
@@ -35,6 +35,7 @@ proto-obj-y	+= mnt.o
 proto-obj-y	+= pipe-data.o
 proto-obj-y	+= sa.o
 proto-obj-y	+= timer.o
+proto-obj-y	+= timerfd.o
 proto-obj-y	+= mm.o
 proto-obj-y	+= sk-opts.o
 proto-obj-y	+= sk-unix.o
diff --git a/protobuf/fdinfo.proto b/protobuf/fdinfo.proto
index 2eb7986..2324c28 100644
--- a/protobuf/fdinfo.proto
+++ b/protobuf/fdinfo.proto
@@ -16,6 +16,7 @@ enum fd_types {
 	NS		= 14;
 	TUN		= 15;
 	EXT		= 16;
+	TIMERFD		= 17;
 }
 
 message fdinfo_entry {
diff --git a/protobuf/timer.proto b/protobuf/timer.proto
index d11f7ef..1383a53 100644
--- a/protobuf/timer.proto
+++ b/protobuf/timer.proto
@@ -1,3 +1,4 @@
+// with timerfd these "usec"s are actually nsecs
 message itimer_entry {
 	required uint64		isec		= 1;
 	required uint64		iusec		= 2;
diff --git a/protobuf/timerfd.proto b/protobuf/timerfd.proto
new file mode 100644
index 0000000..708c957
--- /dev/null
+++ b/protobuf/timerfd.proto
@@ -0,0 +1,10 @@
+import "fown.proto";
+import "timer.proto";
+
+message timerfd_file_entry {
+	required uint32		id		= 1;
+	required uint32		flags		= 2;
+	required fown_entry	fown		= 3;
+	required itimer_entry	timer		= 4;
+	required int32		clockid		= 5;
+}
diff --git a/signalfd.c b/signalfd.c
index 48816ed..72e4f1e 100644
--- a/signalfd.c
+++ b/signalfd.c
@@ -73,7 +73,7 @@ static void sigset_fill(sigset_t *to, unsigned long long from)
 		}
 }
 
-static int signalfd_open(struct file_desc *d)
+static int open_signalfd(struct file_desc *d, int pid)
 {
 	struct signalfd_info *info;
 	int tmp;
@@ -104,7 +104,7 @@ err_close:
 
 static struct file_desc_ops signalfd_desc_ops = {
 	.type = FD_TYPES__SIGNALFD,
-	.open = signalfd_open,
+	.open = open_signalfd,
 };
 
 static int collect_one_sigfd(void *o, ProtobufCMessage *msg)
diff --git a/sk-inet.c b/sk-inet.c
index 02c653f..b00bbad 100644
--- a/sk-inet.c
+++ b/sk-inet.c
@@ -370,7 +370,7 @@ int inet_collect_one(struct nlmsghdr *h, int family, int type)
 	return ret;
 }
 
-static int open_inet_sk(struct file_desc *d);
+static int open_inet_sk(struct file_desc *d, int pid);
 static int post_open_inet_sk(struct file_desc *d, int sk);
 
 static struct file_desc_ops inet_desc_ops = {
@@ -467,7 +467,7 @@ static int post_open_inet_sk(struct file_desc *d, int sk)
 	return 0;
 }
 
-static int open_inet_sk(struct file_desc *d)
+static int open_inet_sk(struct file_desc *d, int pid)
 {
 	struct inet_sk_info *ii;
 	InetSkEntry *ie;
diff --git a/sk-netlink.c b/sk-netlink.c
index 83a2090..f562408 100644
--- a/sk-netlink.c
+++ b/sk-netlink.c
@@ -159,7 +159,7 @@ struct netlink_sock_info {
 	struct file_desc d;
 };
 
-static int open_netlink_sk(struct file_desc *d)
+static int open_netlink_sk(struct file_desc *d, int pid)
 {
 	struct netlink_sock_info *nsi;
 	NetlinkSkEntry *nse;
diff --git a/sk-packet.c b/sk-packet.c
index 2ed7ca6..ed9353b 100644
--- a/sk-packet.c
+++ b/sk-packet.c
@@ -393,7 +393,7 @@ static int restore_rings(int sk, PacketSockEntry *psk)
 	return 0;
 }
 
-static int open_packet_sk(struct file_desc *d)
+static int open_packet_sk(struct file_desc *d, int pid)
 {
 	struct packet_sock_info *psi;
 	PacketSockEntry *pse;
diff --git a/sk-unix.c b/sk-unix.c
index aa6d22f..bff1836 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -950,7 +950,7 @@ out:
 	return sk;
 }
 
-static int open_unix_sk(struct file_desc *d)
+static int open_unix_sk(struct file_desc *d, int pid)
 {
 	struct unix_sk_info *ui;
 
diff --git a/timerfd.c b/timerfd.c
new file mode 100644
index 0000000..9d32da8
--- /dev/null
+++ b/timerfd.c
@@ -0,0 +1,150 @@
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <inttypes.h>
+#include <sys/timerfd.h>
+
+
+#include "compiler.h"
+#include "asm/types.h"
+#include "proc_parse.h"
+#include "fdset.h"
+#include "image.h"
+#include "util.h"
+#include "log.h"
+#include "files.h"
+#include "crtools.h"
+
+#include "timerfd.h"
+
+#include "protobuf.h"
+#include "protobuf/timerfd.pb-c.h"
+
+#undef	LOG_PREFIX
+#define LOG_PREFIX "timerfd: "
+
+struct timerfd_file_info {
+	TimerfdFileEntry		*tfe;
+	struct file_desc		d;
+};
+
+/* Checks if file descriptor @lfd is eventfd */
+int is_timerfd_link(int lfd)
+{
+	return is_anon_link_type(lfd, "[timerfd]");
+}
+
+static void pr_info_timerfd(char *action, TimerfdFileEntry *tfe)
+{
+	pr_info("%s: id %#08x flags %#04x isec %"PRIu64" iusec %"PRIu64" vsec %"PRIu64" uvsec %"PRIu64"\n",
+		action, tfe->id, tfe->flags, tfe->timer->isec,
+		tfe->timer->iusec, tfe->timer->vsec, tfe->timer->vusec);
+}
+
+struct timerfd_dump_arg {
+	u32 id;
+	const struct fd_parms *p;
+	bool dumped;
+};
+
+
+/* UGLY: global */
+struct itimerspec itimer = {{0,0},{0,0}};
+
+static int dump_timerfd_entry(union fdinfo_entries *e, void *arg)
+{
+	struct timerfd_dump_arg *da = arg;
+
+	if (da->dumped) {
+		pr_err("Several counters in a file?\n");
+		return -1;
+	}
+
+	da->dumped = true;
+	e->efd.id = da->id;
+	e->efd.flags = da->p->flags;
+	e->efd.fown = (FownEntry *)&da->p->fown;
+
+	e->tfd.timer->isec = itimer.it_interval.tv_sec;
+	e->tfd.timer->iusec = itimer.it_interval.tv_nsec;
+	e->tfd.timer->vsec = itimer.it_value.tv_sec;
+	e->tfd.timer->vusec = itimer.it_value.tv_nsec;
+
+	pr_info_timerfd("Dumping ", &e->tfd);
+	return pb_write_one(fdset_fd(glob_fdset, CR_FD_TIMERFD_FILE),
+			&e->tfd, PB_TIMERFD_FILE);
+}
+
+static int pre_dump_one_timerfd(int pid, int lfd) {
+	int r;
+
+	r = cr_exec(pid, (char **){"timerfd_gettime", (char *)lfd, (char *)&itimer});
+	if (r < 0) {
+		pr_err("timerfd_gettime failed: %m\n");
+		return -errno;
+	}
+	return 0;
+}
+
+static int dump_one_timerfd(int lfd, u32 id, const struct fd_parms *p)
+{
+	struct timerfd_dump_arg da = { .id = id, .p = p, };
+	return parse_fdinfo(lfd, FD_TYPES__TIMERFD, dump_timerfd_entry, &da);
+}
+
+const struct fdtype_ops timerfd_dump_ops = {
+	.type		= FD_TYPES__TIMERFD,
+	.dump		= dump_one_timerfd,
+	.dump_pre	= pre_dump_one_timerfd,
+};
+
+static int timerfd_open(struct file_desc *d, int pid)
+{
+	struct timerfd_file_info *info;
+	int tmp;
+
+	info = container_of(d, struct timerfd_file_info, d);
+	struct itimerspec itimer = {{info->tfe->timer->isec, info->tfe->timer->iusec}, {info->tfe->timer->vsec, info->tfe->timer->vusec}};
+
+	tmp = cr_exec(pid, (char **){"timerfd_create", (char *)info->tfe->clockid, (char *)0});
+	if (tmp < 0) {
+		pr_perror("Can't create timerfd %#08x",
+			  info->tfe->id);
+		return -1;
+	}
+
+	cr_exec(pid, (char **){"timerfd_settime", (char *)tmp, 0, (char *)&itimer, NULL});
+
+	if (rst_file_params(tmp, info->tfe->fown, info->tfe->flags)) {
+		pr_perror("Can't restore params on timerfd %#08x",
+			  info->tfe->id);
+		goto err_close;
+	}
+
+	return tmp;
+
+err_close:
+	close(tmp);
+	return -1;
+}
+
+static struct file_desc_ops timerfd_desc_ops = {
+	.type = FD_TYPES__TIMERFD,
+	.open = timerfd_open,
+};
+
+static int collect_one_tfd(void *obj, ProtobufCMessage *msg)
+{
+	struct timerfd_file_info *info = obj;
+
+	info->tfe = pb_msg(msg, TimerfdFileEntry);
+	pr_info_timerfd("Collected ", info->tfe);
+	return file_desc_add(&info->d, info->tfe->id, &timerfd_desc_ops);
+}
+
+struct collect_image_info timerfd_cinfo = {
+	.fd_type = CR_FD_TIMERFD_FILE,
+	.pb_type = PB_TIMERFD_FILE,
+	.priv_size = sizeof(struct timerfd_file_info),
+	.collect = collect_one_tfd,
+};
diff --git a/tty.c b/tty.c
index 2ad76cb..553d64f 100644
--- a/tty.c
+++ b/tty.c
@@ -645,7 +645,7 @@ err:
 	return -1;
 }
 
-static int tty_open(struct file_desc *d)
+static int open_tty(struct file_desc *d, int pid)
 {
 	struct tty_info *info = container_of(d, struct tty_info, d);
 
@@ -682,7 +682,7 @@ static struct list_head *tty_select_pslist(struct file_desc *d, struct rst_info
 
 static struct file_desc_ops tty_desc_ops = {
 	.type		= FD_TYPES__TTY,
-	.open		= tty_open,
+	.open		= open_tty,
 	.post_open	= tty_restore_ctl_terminal,
 	.want_transport = tty_transport,
 	.select_ps_list	= tty_select_pslist,
diff --git a/tun.c b/tun.c
index d453015..194585d 100644
--- a/tun.c
+++ b/tun.c
@@ -318,7 +318,7 @@ struct tunfile_info {
 	TunfileEntry *tfe;
 };
 
-static int tunfile_open(struct file_desc *d)
+static int open_tunfile(struct file_desc *d, int pid)
 {
 	int fd;
 	struct tunfile_info *ti;
@@ -375,7 +375,7 @@ err:
 
 static struct file_desc_ops tunfile_desc_ops = {
 	.type = FD_TYPES__TUN,
-	.open = tunfile_open,
+	.open = open_tunfile,
 };
 
 static int collect_one_tunfile(void *o, ProtobufCMessage *base)
-- 
1.9.rc0.143.g6fd479e



More information about the CRIU mailing list