mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-29 21:38:16 +00:00
pipe: don't reopen pipes via /proc, if it's not required
The system call open can add O_LARGEFILE. A point is reopend for unsharing a file descriptor. So here are two types of points. One is returned by pipe() and all other ones are got via opening /proc/PID/fd. Currently I know only one difference between these types, it's O_LARGEFILE. Signed-off-by: Andrey Vagin <avagin@openvz.org> Tested-by: Alexander Kartashov <alekskartashov@parallels.com Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
74053de77d
commit
f2664d6524
55
pipes.c
55
pipes.c
@ -28,7 +28,8 @@ struct pipe_info {
|
|||||||
* This is pure circular list without head */
|
* This is pure circular list without head */
|
||||||
struct list_head list; /* list head for fdinfo_list_entry-s */
|
struct list_head list; /* list head for fdinfo_list_entry-s */
|
||||||
struct file_desc d;
|
struct file_desc d;
|
||||||
int create;
|
unsigned int create : 1,
|
||||||
|
reopen : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static LIST_HEAD(pipes);
|
static LIST_HEAD(pipes);
|
||||||
@ -117,6 +118,7 @@ void mark_pipe_master(void)
|
|||||||
while (1) {
|
while (1) {
|
||||||
struct fdinfo_list_entry *fle;
|
struct fdinfo_list_entry *fle;
|
||||||
struct pipe_info *pi, *pic, *p;
|
struct pipe_info *pi, *pic, *p;
|
||||||
|
struct pipe_info *pr = NULL, *pw = NULL;
|
||||||
|
|
||||||
if (list_empty(&pipes))
|
if (list_empty(&pipes))
|
||||||
break;
|
break;
|
||||||
@ -129,6 +131,15 @@ void mark_pipe_master(void)
|
|||||||
|
|
||||||
fle = file_master(&pi->d);
|
fle = file_master(&pi->d);
|
||||||
p = pi;
|
p = pi;
|
||||||
|
if (!(pi->pe->flags & O_LARGEFILE)) {
|
||||||
|
if (pi->pe->flags & O_WRONLY) {
|
||||||
|
if (pw == NULL)
|
||||||
|
pw = pi;
|
||||||
|
} else {
|
||||||
|
if (pr == NULL)
|
||||||
|
pr = pi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
list_for_each_entry(pic, &pi->pipe_list, pipe_list) {
|
list_for_each_entry(pic, &pi->pipe_list, pipe_list) {
|
||||||
struct fdinfo_list_entry *f;
|
struct fdinfo_list_entry *f;
|
||||||
@ -140,9 +151,23 @@ void mark_pipe_master(void)
|
|||||||
fle = f;
|
fle = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(pic->pe->flags & O_LARGEFILE)) {
|
||||||
|
if (pic->pe->flags & O_WRONLY) {
|
||||||
|
if (pw == NULL)
|
||||||
|
pw = pic;
|
||||||
|
} else {
|
||||||
|
if (pr == NULL)
|
||||||
|
pr = pic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
show_saved_pipe_fds(pic);
|
show_saved_pipe_fds(pic);
|
||||||
}
|
}
|
||||||
p->create = 1;
|
p->create = 1;
|
||||||
|
if (pr)
|
||||||
|
pr->reopen = 0;
|
||||||
|
if (pw)
|
||||||
|
pw->reopen = 0;
|
||||||
pr_info(" by %#x\n", p->pe->id);
|
pr_info(" by %#x\n", p->pe->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,10 +247,22 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int reopen_pipe(int fd, int flags, struct pipe_info *pi)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char path[32];
|
||||||
|
|
||||||
|
pr_err("%s %p %d\n", __func__, pi, fd);
|
||||||
|
snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
|
||||||
|
ret = open(path, flags);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int recv_pipe_fd(struct pipe_info *pi)
|
static int recv_pipe_fd(struct pipe_info *pi)
|
||||||
{
|
{
|
||||||
struct fdinfo_list_entry *fle;
|
struct fdinfo_list_entry *fle;
|
||||||
char path[32];
|
|
||||||
int tmp, fd;
|
int tmp, fd;
|
||||||
|
|
||||||
fle = file_master(&pi->d);
|
fle = file_master(&pi->d);
|
||||||
@ -240,12 +277,12 @@ static int recv_pipe_fd(struct pipe_info *pi)
|
|||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/proc/self/fd/%d", tmp);
|
if (pi->reopen)
|
||||||
fd = open(path, pi->pe->flags);
|
fd = reopen_pipe(tmp, pi->pe->flags, pi);
|
||||||
close(tmp);
|
else
|
||||||
|
fd = tmp;
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
if (restore_fown(fd, pi->pe->fown)) {
|
if (rst_file_params(fd, pi->pe->fown, pi->pe->flags)) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -302,6 +339,9 @@ static int open_pipe(struct file_desc *d)
|
|||||||
close(pfd[!(pi->pe->flags & O_WRONLY)]);
|
close(pfd[!(pi->pe->flags & O_WRONLY)]);
|
||||||
tmp = pfd[pi->pe->flags & O_WRONLY];
|
tmp = pfd[pi->pe->flags & O_WRONLY];
|
||||||
|
|
||||||
|
if (pi->reopen)
|
||||||
|
tmp = reopen_pipe(tmp, pi->pe->flags, pi);
|
||||||
|
|
||||||
if (rst_file_params(tmp, pi->pe->fown, pi->pe->flags))
|
if (rst_file_params(tmp, pi->pe->fown, pi->pe->flags))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -329,6 +369,7 @@ static int collect_one_pipe(void *o, ProtobufCMessage *base)
|
|||||||
pi->pe = pb_msg(base, PipeEntry);
|
pi->pe = pb_msg(base, PipeEntry);
|
||||||
|
|
||||||
pi->create = 0;
|
pi->create = 0;
|
||||||
|
pi->reopen = 1;
|
||||||
pr_info("Collected pipe entry ID %#x PIPE ID %#x\n",
|
pr_info("Collected pipe entry ID %#x PIPE ID %#x\n",
|
||||||
pi->pe->id, pi->pe->pipe_id);
|
pi->pe->id, pi->pe->pipe_id);
|
||||||
|
|
||||||
|
@ -40,16 +40,6 @@ static void fill_pipe_params(struct params *p, int *pipes)
|
|||||||
p->pipe_flags[0] = fcntl(pipes[0], F_GETFL);
|
p->pipe_flags[0] = fcntl(pipes[0], F_GETFL);
|
||||||
p->pipe_flags[1] = fcntl(pipes[1], F_GETFL);
|
p->pipe_flags[1] = fcntl(pipes[1], F_GETFL);
|
||||||
|
|
||||||
/*
|
|
||||||
* The kernel's O_LARGEFILE set automatically
|
|
||||||
* on open() in x86-64, so unmask it explicitly
|
|
||||||
* we restore pipes via open call while the former
|
|
||||||
* pipes are created with pipe() and have no O_LARGEFILE
|
|
||||||
* set.
|
|
||||||
*/
|
|
||||||
p->pipe_flags[0] &= ~00100000;
|
|
||||||
p->pipe_flags[1] &= ~00100000;
|
|
||||||
|
|
||||||
test_msg("pipe_flags0 %08o\n", p->pipe_flags[0]);
|
test_msg("pipe_flags0 %08o\n", p->pipe_flags[0]);
|
||||||
test_msg("pipe_flags1 %08o\n", p->pipe_flags[1]);
|
test_msg("pipe_flags1 %08o\n", p->pipe_flags[1]);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user