[CRIU] [PATCH cr 07/11] pipes: add functions for collecting pipes

Andrey Vagin avagin at openvz.org
Thu Apr 5 12:02:11 EDT 2012


pipe_entry is encapsulated in pipe_info.
All pipe_info-s connects in the list pipes.
All pipe_info-s with the same piep_id connects to pipe_list,
it a circular list without a defined head.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-restore.c    |    5 ++
 files.c         |    2 +
 include/files.h |    4 ++
 pipes.c         |  161 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+), 0 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index 5621bae..74ae7d8 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -247,6 +247,9 @@ static int prepare_shared(int ps_fd)
 	if (collect_reg_files())
 		return -1;
 
+	if (collect_pipes())
+		return -1;
+
 	if (collect_inet_sockets())
 		return -1;
 
@@ -276,6 +279,8 @@ static int prepare_shared(int ps_fd)
 		pstree_skip(ps_fd, &e);
 	}
 
+	mark_pipe_master();
+
 	if (!ret) {
 		futex_set(&task_entries->nr_in_progress, task_entries->nr);
 
diff --git a/files.c b/files.c
index a34f15d..6b5ca12 100644
--- a/files.c
+++ b/files.c
@@ -173,6 +173,8 @@ static int collect_fd(int pid, struct fdinfo_entry *e)
 
 	if (e->type == FDINFO_REG)
 		return collect_fd_reg(e->id, le);
+	if (e->type == FDINFO_PIPE)
+		return collect_fd_pipe(e->id, le);
 	if (e->type == FDINFO_INETSK)
 		return collect_fd_inetsk(e->id, le);
 
diff --git a/include/files.h b/include/files.h
index 1d9edad..8cd6137 100644
--- a/include/files.h
+++ b/include/files.h
@@ -55,4 +55,8 @@ extern int get_filemap_fd(int pid, struct vma_entry *vma_entry);
 
 extern int self_exe_fd;
 
+extern int collect_pipes(void);
+extern int collect_fd_pipe(int id, struct fdinfo_list_entry *le);
+extern void mark_pipe_master(void);
+
 #endif /* FILES_H_ */
diff --git a/pipes.c b/pipes.c
index c1c1a54..070b5f4 100644
--- a/pipes.c
+++ b/pipes.c
@@ -1,4 +1,165 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 #include "crtools.h"
 #include "image.h"
 #include "files.h"
+#include "util-net.h"
+
+/* The sequence of objects which should be restored:
+ * pipe -> files struct-s -> fd-s.
+ * pipe_entry describes  pipe's file structs-s.
+ * A pipe has not own properties, so it has not own object.
+ */
+
+struct pipe_info {
+	struct pipe_entry pe;
+	struct list_head pipe_list;	/* all pipe_info with the same pipe_id
+					 * This is pure circular list whiout head */
+	struct list_head list;		/* list head for fdinfo_list_entry-s */
+	struct list_head fd_head;
+	int create;
+};
+
+static LIST_HEAD(pipes);
+
+static struct pipe_info *find_pipe(int id)
+{
+	struct pipe_info *pi;
+
+	list_for_each_entry(pi, &pipes, list)
+		if (pi->pe.id == id)
+			return pi;
+	return NULL;
+}
+
+struct list_head *find_pipe_fd(int id)
+{
+	struct pipe_info *pi;
+
+	pi = find_pipe(id);
+	return &pi->fd_head;
+}
+
+int collect_pipes(void)
+{
+	struct pipe_info *pi = NULL, *tmp, *tmp2;
+	int fd, ret = -1;
+
+	fd = open_image_ro(CR_FD_PIPES);
+	if (fd < 0)
+		return -1;
+
+	while (1) {
+		int len;
+
+		pi = xmalloc(sizeof(*pi));
+		ret = -1;
+		if (pi == NULL)
+			break;
+
+		ret = read_img_eof(fd, &pi->pe);
+		if (ret <= 0)
+			break;
+
+		lseek(fd, pi->pe.bytes, SEEK_CUR);
+
+		pr_info("Collected pipe entry ID %x PIPE ID %x\n",
+					pi->pe.id, pi->pe.pipe_id);
+		INIT_LIST_HEAD(&pi->fd_head);
+
+		list_for_each_entry(tmp, &pipes, list)
+			if (pi->pe.pipe_id == tmp->pe.pipe_id)
+				break;
+
+		if (&tmp->list == &pipes)
+			INIT_LIST_HEAD(&pi->pipe_list);
+		else
+			list_add(&pi->pipe_list, &tmp->pipe_list);
+
+		list_add_tail(&pi->list, &pipes);
+	}
+
+	xfree(pi);
+
+	close(fd);
+	return ret;
+}
+
+int collect_fd_pipe(int id, struct fdinfo_list_entry *le)
+{
+	struct pipe_info *pi;
+	struct fdinfo_list_entry *l;
+
+	pi = find_pipe(id);
+	if (pi == NULL) {
+		pr_err("No pipe for fd %d, id %d\n", le->fd, id);
+		return -1;
+	}
+
+	list_for_each_entry(l, &pi->fd_head, list)
+		if (l->pid > le->pid)
+			break;
+
+	list_add_tail(&le->list, &l->list);
+	return 0;
+}
+
+static void show_saved_pipe_fds(struct pipe_info *pi)
+{
+	struct fdinfo_list_entry *fle;
+
+	pr_info("  `- ID %p %xpn", pi, pi->pe.id);
+	list_for_each_entry(fle, &pi->fd_head, list)
+		pr_info("   `- FD %d pid %d\n", fle->fd, fle->pid);
+}
+
+/* Choose who will restore a pipe. */
+void mark_pipe_master()
+{
+	LIST_HEAD(head);
+
+	pr_info("Pipes:\n");
+
+	while (1) {
+		struct fdinfo_list_entry *fle;
+		struct pipe_info *pi, *pic, *p;
+		int fd, pid;
+
+		if (list_empty(&pipes))
+			break;
+
+		pi = list_first_entry(&pipes, struct pipe_info, list);
+		list_move(&pi->list, &head);
+
+		pr_info(" `- PIPE ID %x\n", pi->pe.pipe_id);
+		show_saved_pipe_fds(pi);
+
+		fle = list_first_entry(&pi->fd_head,
+				struct fdinfo_list_entry, list);
+		p = pi;
+		fd = fle->fd;
+		pid = fle->pid;
+
+		list_for_each_entry(pic, &pi->pipe_list, pipe_list) {
+			list_move(&pic->list, &head);
+
+			fle = list_first_entry(&p->fd_head,
+					struct fdinfo_list_entry, list);
+			if (fle->pid < pid ||
+			    (pid == fle->pid && fle->fd < fd)) {
+				p = pic;
+				fd = fle->fd;
+				pid = fle->pid;
+			}
+
+			show_saved_pipe_fds(pic);
+		}
+		p->create = 1;
+		pr_info("    by %x\n", p->pe.id);
+	}
 
+	list_splice(&head, &pipes);
+}
-- 
1.7.1



More information about the CRIU mailing list