Commit c53972cd authored by Andrey Vagin's avatar Andrey Vagin Committed by Cyrill Gorcunov

pipe: change calculation of pipes users

This patch removed stange logic about minusers.
Now we calculate foreign users only.

The main idea of this patch, that we bind a pipe ends to correct
descriptos immediately.

When a process X creates a pipe, we have two cases:
1. Both ends belongs to this process. It's simple, we bind both ends
   to their descriptors and we go further.
2. Only one end of a pipe belongs to this process. In this case we are
   waiting all foreign users and we go futher.
In second case we should wait, because a end which doesn't belong to
this process occupies a file descriptor, which may be used by another
pipe.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Acked-by: 's avatarPavel Emelianov <xemul@parallels.com>
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
parent 4c479da2
...@@ -249,18 +249,24 @@ static int collect_pipe(int pid, struct pipe_entry *e, int p_fd) ...@@ -249,18 +249,24 @@ static int collect_pipe(int pid, struct pipe_entry *e, int p_fd)
if (pipes[i].pid > pid && !pipe_is_rw(&pipes[i])) { if (pipes[i].pid > pid && !pipe_is_rw(&pipes[i])) {
pipes[i].pid = pid; pipes[i].pid = pid;
} else if (pipes[i].pid == pid) { pipes[i].status = 0;
pipes[i].read_fd = -1;
pipes[i].write_fd = -1;
}
if (pipes[i].pid == pid) {
switch (e->flags & O_ACCMODE) { switch (e->flags & O_ACCMODE) {
case O_RDONLY: case O_RDONLY:
pipes[i].status |= PIPE_RDONLY; pipes[i].status |= PIPE_RDONLY;
pipes[i].read_fd = e->fd;
break; break;
case O_WRONLY: case O_WRONLY:
pipes[i].status |= PIPE_WRONLY; pipes[i].status |= PIPE_WRONLY;
pipes[i].write_fd = e->fd;
break; break;
} }
} } else
pipes[i].users++;
pipes[i].users++;
return 0; return 0;
} }
...@@ -274,14 +280,16 @@ static int collect_pipe(int pid, struct pipe_entry *e, int p_fd) ...@@ -274,14 +280,16 @@ static int collect_pipe(int pid, struct pipe_entry *e, int p_fd)
pipes[nr_pipes].pipeid = e->pipeid; pipes[nr_pipes].pipeid = e->pipeid;
pipes[nr_pipes].pid = pid; pipes[nr_pipes].pid = pid;
pipes[nr_pipes].users = 1; pipes[nr_pipes].users = 0;
switch (e->flags & O_ACCMODE) { switch (e->flags & O_ACCMODE) {
case O_RDONLY: case O_RDONLY:
pipes[nr_pipes].status = PIPE_RDONLY; pipes[nr_pipes].status = PIPE_RDONLY;
pipes[i].read_fd = e->fd;
break; break;
case O_WRONLY: case O_WRONLY:
pipes[nr_pipes].status = PIPE_WRONLY; pipes[nr_pipes].status = PIPE_WRONLY;
pipes[i].write_fd = e->fd;
break; break;
} }
...@@ -926,9 +934,8 @@ static int create_pipe(int pid, struct pipe_entry *e, struct pipe_info *pi, int ...@@ -926,9 +934,8 @@ static int create_pipe(int pid, struct pipe_entry *e, struct pipe_info *pi, int
{ {
unsigned long time = 1000; unsigned long time = 1000;
int pfd[2], tmp; int pfd[2], tmp;
int minusers = 1;
pr_info("\t%d: Creating pipe %x\n", pid, e->pipeid); pr_info("\t%d: Creating pipe %x%s\n", pid, e->pipeid, pipe_is_rw(pi) ? "(rw)" : "");
if (pipe(pfd) < 0) { if (pipe(pfd) < 0) {
pr_perror("%d: Can't create pipe\n", pid); pr_perror("%d: Can't create pipe\n", pid);
...@@ -948,52 +955,64 @@ static int create_pipe(int pid, struct pipe_entry *e, struct pipe_info *pi, int ...@@ -948,52 +955,64 @@ static int create_pipe(int pid, struct pipe_entry *e, struct pipe_info *pi, int
} }
} }
pi->read_fd = pfd[0]; if (pi->read_fd != -1)
pi->write_fd = pfd[1]; tmp = reopen_fd_as(pi->read_fd, pfd[0]);
pi->real_pid = getpid(); else
pi->read_fd = pfd[0];
if (tmp < 0)
return 1;
/* if (pi->write_fd != -1)
* FIXME: xemul@ reported that this actually tmp = reopen_fd_as(pi->write_fd, pfd[1]);
* would not work if a task keeps pipe many times else
* not just two. Need to review and fix propery. pi->write_fd = pfd[1];
*/ if (tmp < 0)
if (pipe_is_rw(pi)) return 1;
minusers = 2;
pi->real_pid = getpid();
pi->status |= PIPE_CREATED; pi->status |= PIPE_CREATED;
if (pi->write_fd != e->fd && pi->read_fd != e->fd) {
switch (e->flags & O_ACCMODE) {
case O_WRONLY:
tmp = dup2(pi->write_fd, e->fd);
break;
case O_RDONLY:
tmp = dup2(pi->read_fd, e->fd);
break;
}
}
if (tmp < 0)
return 1;
pr_info("\t%d: Done, waiting for others (users %d) on %d pid with r:%d w:%d\n", pr_info("\t%d: Done, waiting for others (users %d) on %d pid with r:%d w:%d\n",
pid, pi->users - minusers, pi->real_pid, pi->read_fd, pi->write_fd); pid, pi->users, pi->real_pid, pi->read_fd, pi->write_fd);
while (1) { while (1) {
if (pi->users <= minusers) /* only I left here, no need to wait */ if (pipe_is_rw(pi) || !pi->users)
break; break;
pr_info("\t%d: Waiting for %x pipe to attach (%d users left)\n", pr_info("\t%d: Waiting for %x pipe to attach (%d users left)\n",
pid, e->pipeid, pi->users - minusers); pid, e->pipeid, pi->users);
if (time < 20000000) if (time < 20000000)
time <<= 1; time <<= 1;
usleep(time); usleep(time);
} }
pr_info("\t%d: All is ok - reopening pipe for %d\n", pid, e->fd); if (!pipe_is_rw(pi)) {
if (e->flags & O_WRONLY) { if ((e->flags & O_ACCMODE) == O_WRONLY)
if (!pipe_is_rw(pi))
close_safe(&pi->read_fd); close_safe(&pi->read_fd);
tmp = reopen_fd_as(e->fd, pi->write_fd); else
} else {
if (!pipe_is_rw(pi))
close_safe(&pi->write_fd); close_safe(&pi->write_fd);
tmp = reopen_fd_as(e->fd, pi->read_fd);
} }
if (tmp < 0)
return 1;
tmp = set_fd_flags(e->fd, e->flags); tmp = set_fd_flags(e->fd, e->flags);
if (tmp < 0) if (tmp < 0)
return 1; return 1;
pr_info("\t%d: All is ok - reopening pipe for %d\n", pid, e->fd);
return 0; return 0;
} }
...@@ -1008,14 +1027,22 @@ static int attach_pipe(int pid, struct pipe_entry *e, struct pipe_info *pi, int ...@@ -1008,14 +1027,22 @@ static int attach_pipe(int pid, struct pipe_entry *e, struct pipe_info *pi, int
while (pi->real_pid == 0) while (pi->real_pid == 0)
usleep(1000); usleep(1000);
if (e->flags & O_WRONLY) if ((e->flags & O_ACCMODE) == O_WRONLY)
tmp = pi->write_fd; tmp = pi->write_fd;
else else
tmp = pi->read_fd; tmp = pi->read_fd;
if (tmp == -1) { if (pid == pi->pid) {
pr_panic("Attaching closed pipe\n"); if (tmp != e->fd)
return 1; tmp = dup2(tmp, e->fd);
if (tmp < 0) {
pr_perror("%d: Can't duplicate %d->%d\n",
pid, tmp, e->fd);
return 1;
}
goto out;
} }
sprintf(path, "/proc/%d/fd/%d", pi->real_pid, tmp); sprintf(path, "/proc/%d/fd/%d", pi->real_pid, tmp);
...@@ -1032,10 +1059,10 @@ static int attach_pipe(int pid, struct pipe_entry *e, struct pipe_info *pi, int ...@@ -1032,10 +1059,10 @@ static int attach_pipe(int pid, struct pipe_entry *e, struct pipe_info *pi, int
tmp = reopen_fd_as(e->fd, fd); tmp = reopen_fd_as(e->fd, fd);
if (tmp < 0) if (tmp < 0)
return 1; return 1;
pi->users--;
lseek(pipes_fd, e->bytes, SEEK_CUR); lseek(pipes_fd, e->bytes, SEEK_CUR);
pi->users--;
out:
tmp = set_fd_flags(e->fd, e->flags); tmp = set_fd_flags(e->fd, e->flags);
if (tmp < 0) if (tmp < 0)
return 1; return 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