aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/pipe.c72
1 files changed, 51 insertions, 21 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index 357471db890d..abaa9234d27b 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -718,23 +718,30 @@ pipe_poll(struct file *filp, poll_table *wait)
718static int 718static int
719pipe_release(struct inode *inode, struct file *file) 719pipe_release(struct inode *inode, struct file *file)
720{ 720{
721 struct pipe_inode_info *pipe; 721 struct pipe_inode_info *pipe = inode->i_pipe;
722 int kill = 0;
722 723
723 mutex_lock(&inode->i_mutex); 724 pipe_lock(pipe);
724 pipe = inode->i_pipe;
725 if (file->f_mode & FMODE_READ) 725 if (file->f_mode & FMODE_READ)
726 pipe->readers--; 726 pipe->readers--;
727 if (file->f_mode & FMODE_WRITE) 727 if (file->f_mode & FMODE_WRITE)
728 pipe->writers--; 728 pipe->writers--;
729 729
730 if (!pipe->readers && !pipe->writers) { 730 if (pipe->readers || pipe->writers) {
731 free_pipe_info(inode);
732 } else {
733 wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM | POLLERR | POLLHUP); 731 wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM | POLLERR | POLLHUP);
734 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); 732 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
735 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); 733 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
736 } 734 }
737 mutex_unlock(&inode->i_mutex); 735 spin_lock(&inode->i_lock);
736 if (!--pipe->files) {
737 inode->i_pipe = NULL;
738 kill = 1;
739 }
740 spin_unlock(&inode->i_lock);
741 pipe_unlock(pipe);
742
743 if (kill)
744 __free_pipe_info(pipe);
738 745
739 return 0; 746 return 0;
740} 747}
@@ -827,8 +834,9 @@ static struct inode * get_pipe_inode(void)
827 pipe = alloc_pipe_info(inode); 834 pipe = alloc_pipe_info(inode);
828 if (!pipe) 835 if (!pipe)
829 goto fail_iput; 836 goto fail_iput;
830 inode->i_pipe = pipe;
831 837
838 inode->i_pipe = pipe;
839 pipe->files = 2;
832 pipe->readers = pipe->writers = 1; 840 pipe->readers = pipe->writers = 1;
833 inode->i_fop = &pipefifo_fops; 841 inode->i_fop = &pipefifo_fops;
834 842
@@ -999,18 +1007,36 @@ static int fifo_open(struct inode *inode, struct file *filp)
999{ 1007{
1000 struct pipe_inode_info *pipe; 1008 struct pipe_inode_info *pipe;
1001 bool is_pipe = inode->i_sb->s_magic == PIPEFS_MAGIC; 1009 bool is_pipe = inode->i_sb->s_magic == PIPEFS_MAGIC;
1010 int kill = 0;
1002 int ret; 1011 int ret;
1003 1012
1004 mutex_lock(&inode->i_mutex); 1013 filp->f_version = 0;
1005 pipe = inode->i_pipe; 1014
1006 if (!pipe) { 1015 spin_lock(&inode->i_lock);
1007 ret = -ENOMEM; 1016 if (inode->i_pipe) {
1017 pipe = inode->i_pipe;
1018 pipe->files++;
1019 spin_unlock(&inode->i_lock);
1020 } else {
1021 spin_unlock(&inode->i_lock);
1008 pipe = alloc_pipe_info(inode); 1022 pipe = alloc_pipe_info(inode);
1009 if (!pipe) 1023 if (!pipe)
1010 goto err_nocleanup; 1024 return -ENOMEM;
1011 inode->i_pipe = pipe; 1025 pipe->files = 1;
1026 spin_lock(&inode->i_lock);
1027 if (unlikely(inode->i_pipe)) {
1028 inode->i_pipe->files++;
1029 spin_unlock(&inode->i_lock);
1030 __free_pipe_info(pipe);
1031 pipe = inode->i_pipe;
1032 } else {
1033 inode->i_pipe = pipe;
1034 spin_unlock(&inode->i_lock);
1035 }
1012 } 1036 }
1013 filp->f_version = 0; 1037 /* OK, we have a pipe and it's pinned down */
1038
1039 pipe_lock(pipe);
1014 1040
1015 /* We can only do regular read/write on fifos */ 1041 /* We can only do regular read/write on fifos */
1016 filp->f_mode &= (FMODE_READ | FMODE_WRITE); 1042 filp->f_mode &= (FMODE_READ | FMODE_WRITE);
@@ -1080,7 +1106,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
1080 } 1106 }
1081 1107
1082 /* Ok! */ 1108 /* Ok! */
1083 mutex_unlock(&inode->i_mutex); 1109 pipe_unlock(pipe);
1084 return 0; 1110 return 0;
1085 1111
1086err_rd: 1112err_rd:
@@ -1096,11 +1122,15 @@ err_wr:
1096 goto err; 1122 goto err;
1097 1123
1098err: 1124err:
1099 if (!pipe->readers && !pipe->writers) 1125 spin_lock(&inode->i_lock);
1100 free_pipe_info(inode); 1126 if (!--pipe->files) {
1101 1127 inode->i_pipe = NULL;
1102err_nocleanup: 1128 kill = 1;
1103 mutex_unlock(&inode->i_mutex); 1129 }
1130 spin_unlock(&inode->i_lock);
1131 pipe_unlock(pipe);
1132 if (kill)
1133 __free_pipe_info(pipe);
1104 return ret; 1134 return ret;
1105} 1135}
1106 1136