Commit f2664d65 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

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: 's avatarAndrey Vagin <avagin@openvz.org>
Tested-by: Alexander Kartashov <alekskartashov@parallels.com
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 74053de7
...@@ -28,7 +28,8 @@ struct pipe_info { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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: ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment