[CRIU] [PATCH cr 09/11] pipes: add functions to restore pipes
Andrey Vagin
avagin at openvz.org
Thu Apr 5 12:02:13 EDT 2012
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
files.c | 19 ++++++++-
include/files.h | 4 ++
pipes.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 132 insertions(+), 2 deletions(-)
diff --git a/files.c b/files.c
index a0673ba..4bc1082 100644
--- a/files.c
+++ b/files.c
@@ -312,6 +312,9 @@ void transport_name_gen(struct sockaddr_un *addr, int *len,
static int should_open_transport(struct fdinfo_entry *fe, struct list_head *fd_list)
{
+ if (fe->type == FDINFO_PIPE)
+ return pipe_should_open_transport(fe, fd_list);
+
return 0;
}
@@ -323,8 +326,15 @@ static int open_transport_fd(int pid, struct fdinfo_entry *fe, struct list_head
int ret, sun_len;
fle = file_master(fd_list);
- if (fle->pid == pid)
- return 0;
+
+ if (fle->pid == pid) {
+ if (fle->fd == fe->addr) {
+ /* file master */
+ if (!should_open_transport(fe, fd_list))
+ return 0;
+ } else
+ return 0;
+ }
transport_name_gen(&saddr, &sun_len, getpid(), fe->addr);
@@ -376,6 +386,9 @@ static int open_fd(int pid, struct fdinfo_entry *fe,
case FDINFO_INETSK:
tmp = open_inet_sk(fd_list);
break;
+ case FDINFO_PIPE:
+ tmp = open_pipe(fd_list);
+ break;
default:
tmp = -1;
break;
@@ -488,6 +501,8 @@ static struct list_head *find_fi_list(struct fdinfo_entry *fe)
{
if (fe->type == FDINFO_REG)
return find_reg_fd(fe->id);
+ if (fe->type == FDINFO_PIPE)
+ return find_pipe_fd(fe->id);
if (fe->type == FDINFO_INETSK)
return find_inetsk_fd(fe->id);
diff --git a/include/files.h b/include/files.h
index 8cd6137..f9980f6 100644
--- a/include/files.h
+++ b/include/files.h
@@ -58,5 +58,9 @@ 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);
+extern int open_pipe(struct list_head *l);
+extern struct list_head *find_pipe_fd(int id);
+extern int pipe_should_open_transport(struct fdinfo_entry *fe,
+ struct list_head *fd_list);
#endif /* FILES_H_ */
diff --git a/pipes.c b/pipes.c
index 070b5f4..ecac8a3 100644
--- a/pipes.c
+++ b/pipes.c
@@ -163,3 +163,114 @@ void mark_pipe_master()
list_splice(&head, &pipes);
}
+
+int pipe_should_open_transport(struct fdinfo_entry *fe,
+ struct list_head *fd_list)
+{
+ struct pipe_info *pi = container_of(fd_list, struct pipe_info, fd_head);
+
+ return !pi->create;
+}
+
+static int recv_pipe_fd(struct pipe_info *pi)
+{
+ struct fdinfo_list_entry *fle;
+ char path[PATH_MAX];
+ int tmp, fd;
+
+ fle = list_first_entry(&pi->fd_head, struct fdinfo_list_entry, list);
+ fd = fle->fd;
+
+ pr_info("\tWaiting fd for %d\n", fd);
+
+ tmp = recv_fd(fd);
+ if (tmp < 0) {
+ pr_err("Can't get fd %d\n", tmp);
+ return -1;
+ }
+ close(fd);
+
+ snprintf(path, PATH_MAX, "/proc/self/fd/%d", tmp);
+ fd = open(path, pi->pe.flags);
+ close(tmp);
+
+ return fd;
+}
+
+#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
+static int set_fd_flags(int fd, int flags)
+{
+ int old;
+
+ old = fcntl(fd, F_GETFL, 0);
+ if (old < 0)
+ return old;
+
+ flags = (SETFL_MASK & flags) | (old & ~SETFL_MASK);
+
+ return fcntl(fd, F_SETFL, flags);
+}
+
+int open_pipe(struct list_head *l)
+{
+ unsigned long time = 1000;
+ struct pipe_info *pi, *pc, *p;
+ int ret, tmp;
+ int pfd[2];
+ int sock;
+ int create;
+
+ pi = container_of(l, struct pipe_info, fd_head);
+
+ pr_info("\tCreating pipe pipe_id=%x id=%x\n", pi->pe.pipe_id, pi->pe.id);
+
+ if (!pi->create)
+ return recv_pipe_fd(pi);
+
+ if (pipe(pfd) < 0) {
+ pr_perror("Can't create pipe");
+ return -1;
+ }
+
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ pr_perror("Can't create socket");
+ return -1;
+ }
+
+ list_for_each_entry(p, &pi->pipe_list, pipe_list) {
+ int len, fd;
+ struct sockaddr_un saddr;
+ struct fdinfo_list_entry *fle;
+
+ BUG_ON(list_empty(&p->fd_head));
+ fle = list_first_entry(&p->fd_head,
+ struct fdinfo_list_entry, list);
+
+ pr_info("\t\tWait fdinfo pid=%d fd=%d\n", fle->pid, fle->fd);
+ futex_wait_while(&fle->real_pid, 0);
+
+ transport_name_gen(&saddr, &len,
+ futex_get(&fle->real_pid), fle->fd);
+
+ fd = pfd[p->pe.flags & O_WRONLY];
+
+ pr_info("\t\tSend fd %d to %s\n", fd, saddr.sun_path + 1);
+
+ if (send_fd(sock, &saddr, len, fd) < 0) {
+ pr_perror("Can't send file descriptor");
+ return -1;
+ }
+ }
+
+ close(sock);
+
+out:
+ close(pfd[!(pi->pe.flags & O_WRONLY)]);
+ tmp = pfd[pi->pe.flags & O_WRONLY];
+ ret = set_fd_flags(tmp, pi->pe.flags);
+ if (ret < 0)
+ return -1;
+
+ return tmp;
+}
--
1.7.1
More information about the CRIU
mailing list