reiserfs: Don't call reiserfs_get_acl() with the reiserfs lock
[safe/jmp/linux-2.6] / fs / pipe.c
index 3a48ba5..ae17d02 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
  * -- Manfred Spraul <manfred@colorfullife.com> 2002-05-09
  */
 
+static void pipe_lock_nested(struct pipe_inode_info *pipe, int subclass)
+{
+       if (pipe->inode)
+               mutex_lock_nested(&pipe->inode->i_mutex, subclass);
+}
+
+void pipe_lock(struct pipe_inode_info *pipe)
+{
+       /*
+        * pipe_lock() nests non-pipe inode locks (for writing to a file)
+        */
+       pipe_lock_nested(pipe, I_MUTEX_PARENT);
+}
+EXPORT_SYMBOL(pipe_lock);
+
+void pipe_unlock(struct pipe_inode_info *pipe)
+{
+       if (pipe->inode)
+               mutex_unlock(&pipe->inode->i_mutex);
+}
+EXPORT_SYMBOL(pipe_unlock);
+
+void pipe_double_lock(struct pipe_inode_info *pipe1,
+                     struct pipe_inode_info *pipe2)
+{
+       BUG_ON(pipe1 == pipe2);
+
+       if (pipe1 < pipe2) {
+               pipe_lock_nested(pipe1, I_MUTEX_PARENT);
+               pipe_lock_nested(pipe2, I_MUTEX_CHILD);
+       } else {
+               pipe_lock_nested(pipe2, I_MUTEX_PARENT);
+               pipe_lock_nested(pipe1, I_MUTEX_CHILD);
+       }
+}
+
 /* Drop the inode semaphore and wait for a pipe event, atomically */
 void pipe_wait(struct pipe_inode_info *pipe)
 {
@@ -47,12 +83,10 @@ void pipe_wait(struct pipe_inode_info *pipe)
         * is considered a noninteractive wait:
         */
        prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE);
-       if (pipe->inode)
-               mutex_unlock(&pipe->inode->i_mutex);
+       pipe_unlock(pipe);
        schedule();
        finish_wait(&pipe->wait, &wait);
-       if (pipe->inode)
-               mutex_lock(&pipe->inode->i_mutex);
+       pipe_lock(pipe);
 }
 
 static int
@@ -268,6 +302,20 @@ int generic_pipe_buf_confirm(struct pipe_inode_info *info,
        return 0;
 }
 
+/**
+ * generic_pipe_buf_release - put a reference to a &struct pipe_buffer
+ * @pipe:      the pipe that the buffer belongs to
+ * @buf:       the buffer to put a reference to
+ *
+ * Description:
+ *     This function releases a reference to @buf.
+ */
+void generic_pipe_buf_release(struct pipe_inode_info *pipe,
+                             struct pipe_buffer *buf)
+{
+       page_cache_release(buf->page);
+}
+
 static const struct pipe_buf_operations anon_pipe_buf_ops = {
        .can_merge = 1,
        .map = generic_pipe_buf_map,
@@ -667,10 +715,7 @@ pipe_read_fasync(int fd, struct file *filp, int on)
        retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers);
        mutex_unlock(&inode->i_mutex);
 
-       if (retval < 0)
-               return retval;
-
-       return 0;
+       return retval;
 }
 
 
@@ -684,10 +729,7 @@ pipe_write_fasync(int fd, struct file *filp, int on)
        retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers);
        mutex_unlock(&inode->i_mutex);
 
-       if (retval < 0)
-               return retval;
-
-       return 0;
+       return retval;
 }
 
 
@@ -699,18 +741,14 @@ pipe_rdwr_fasync(int fd, struct file *filp, int on)
        int retval;
 
        mutex_lock(&inode->i_mutex);
-
        retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
-
-       if (retval >= 0)
+       if (retval >= 0) {
                retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
-
+               if (retval < 0) /* this can happen only if on == T */
+                       fasync_helper(-1, filp, 0, &pipe->fasync_readers);
+       }
        mutex_unlock(&inode->i_mutex);
-
-       if (retval < 0)
-               return retval;
-
-       return 0;
+       return retval;
 }
 
 
@@ -739,36 +777,55 @@ pipe_rdwr_release(struct inode *inode, struct file *filp)
 static int
 pipe_read_open(struct inode *inode, struct file *filp)
 {
-       /* We could have perhaps used atomic_t, but this and friends
-          below are the only places.  So it doesn't seem worthwhile.  */
+       int ret = -ENOENT;
+
        mutex_lock(&inode->i_mutex);
-       inode->i_pipe->readers++;
+
+       if (inode->i_pipe) {
+               ret = 0;
+               inode->i_pipe->readers++;
+       }
+
        mutex_unlock(&inode->i_mutex);
 
-       return 0;
+       return ret;
 }
 
 static int
 pipe_write_open(struct inode *inode, struct file *filp)
 {
+       int ret = -ENOENT;
+
        mutex_lock(&inode->i_mutex);
-       inode->i_pipe->writers++;
+
+       if (inode->i_pipe) {
+               ret = 0;
+               inode->i_pipe->writers++;
+       }
+
        mutex_unlock(&inode->i_mutex);
 
-       return 0;
+       return ret;
 }
 
 static int
 pipe_rdwr_open(struct inode *inode, struct file *filp)
 {
+       int ret = -ENOENT;
+
        mutex_lock(&inode->i_mutex);
-       if (filp->f_mode & FMODE_READ)
-               inode->i_pipe->readers++;
-       if (filp->f_mode & FMODE_WRITE)
-               inode->i_pipe->writers++;
+
+       if (inode->i_pipe) {
+               ret = 0;
+               if (filp->f_mode & FMODE_READ)
+                       inode->i_pipe->readers++;
+               if (filp->f_mode & FMODE_WRITE)
+                       inode->i_pipe->writers++;
+       }
+
        mutex_unlock(&inode->i_mutex);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -870,7 +927,7 @@ static char *pipefs_dname(struct dentry *dentry, char *buffer, int buflen)
                                dentry->d_inode->i_ino);
 }
 
-static struct dentry_operations pipefs_dentry_operations = {
+static const struct dentry_operations pipefs_dentry_operations = {
        .d_delete       = pipefs_delete_dentry,
        .d_dname        = pipefs_dname,
 };
@@ -1034,11 +1091,6 @@ int do_pipe_flags(int *fd, int flags)
        return error;
 }
 
-int do_pipe(int *fd)
-{
-       return do_pipe_flags(fd, 0);
-}
-
 /*
  * sys_pipe() is the normal C calling standard for creating
  * a pipe. It's not the way Unix traditionally does this, though.