[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