From 4f2bd3770496b35b4080a97104f4eb41e1649ff4 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Thu, 5 Apr 2012 20:02:00 +0400 Subject: [PATCH] pipes: add functions for collecting pipes 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 Signed-off-by: Pavel Emelyanov --- cr-restore.c | 5 ++ files.c | 2 + include/files.h | 4 ++ pipes.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+) diff --git a/cr-restore.c b/cr-restore.c index 66d659729..ef7cfb545 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -284,6 +284,9 @@ static int prepare_shared(void) if (collect_reg_files()) return -1; + if (collect_pipes()) + return -1; + if (collect_inet_sockets()) return -1; @@ -301,6 +304,8 @@ static int prepare_shared(void) break; } + mark_pipe_master(); + if (!ret) { show_saved_shmems(); show_saved_files(); diff --git a/files.c b/files.c index 13f538046..3a33dc659 100644 --- a/files.c +++ b/files.c @@ -88,6 +88,8 @@ static struct list_head *find_fi_list(struct fdinfo_entry *fe) return find_reg_fd(fe->id); if (fe->type == FDINFO_INETSK) return find_inetsk_fd(fe->id); + if (fe->type == FDINFO_PIPE) + return find_pipe_fd(fe->id); BUG_ON(1); return NULL; diff --git a/include/files.h b/include/files.h index 1d9edad79..841cfa03d 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 void mark_pipe_master(void); +struct list_head *find_pipe_fd(int id); + #endif /* FILES_H_ */ diff --git a/pipes.c b/pipes.c index c1c1a547b..7269af60f 100644 --- a/pipes.c +++ b/pipes.c @@ -1,4 +1,146 @@ +#include +#include +#include +#include + #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; + 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; +} + +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); +}