mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-02 23:35:21 +00:00
pipes: add functions to restore pipes
[xemul: This check in open_transport_fd should go away once we implement opening files with peers. ] Signed-off-by: Andrey Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
373a93248f
commit
7b10ef0761
17
files.c
17
files.c
@@ -294,6 +294,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)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,8 +308,15 @@ static int open_transport_fd(int pid, struct fdinfo_entry *fe, struct list_head
|
|||||||
int ret, sun_len;
|
int ret, sun_len;
|
||||||
|
|
||||||
fle = file_master(fd_list);
|
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);
|
transport_name_gen(&saddr, &sun_len, getpid(), fe->addr);
|
||||||
|
|
||||||
@@ -358,6 +368,9 @@ static int open_fd(int pid, struct fdinfo_entry *fe,
|
|||||||
case FDINFO_INETSK:
|
case FDINFO_INETSK:
|
||||||
tmp = open_inet_sk(fd_list);
|
tmp = open_inet_sk(fd_list);
|
||||||
break;
|
break;
|
||||||
|
case FDINFO_PIPE:
|
||||||
|
tmp = open_pipe(fd_list);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
tmp = -1;
|
tmp = -1;
|
||||||
break;
|
break;
|
||||||
|
@@ -57,6 +57,9 @@ extern int self_exe_fd;
|
|||||||
|
|
||||||
extern int collect_pipes(void);
|
extern int collect_pipes(void);
|
||||||
extern void mark_pipe_master(void);
|
extern void mark_pipe_master(void);
|
||||||
|
extern int open_pipe(struct list_head *l);
|
||||||
struct list_head *find_pipe_fd(int id);
|
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_ */
|
#endif /* FILES_H_ */
|
||||||
|
111
pipes.c
111
pipes.c
@@ -144,3 +144,114 @@ void mark_pipe_master()
|
|||||||
|
|
||||||
list_splice(&head, &pipes);
|
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;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user