nfsd4: set shorter timeout
[safe/jmp/linux-2.6] / fs / pipe.c
index 68e8206..13414ec 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_CHILD);
+               pipe_lock_nested(pipe1, I_MUTEX_PARENT);
+       }
+}
+
 /* 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
@@ -667,10 +701,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 +715,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,32 +727,26 @@ 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;
 }
 
 
 static int
 pipe_read_release(struct inode *inode, struct file *filp)
 {
-       pipe_read_fasync(-1, filp, 0);
        return pipe_release(inode, 1, 0);
 }
 
 static int
 pipe_write_release(struct inode *inode, struct file *filp)
 {
-       pipe_write_fasync(-1, filp, 0);
        return pipe_release(inode, 0, 1);
 }
 
@@ -733,7 +755,6 @@ pipe_rdwr_release(struct inode *inode, struct file *filp)
 {
        int decr, decw;
 
-       pipe_rdwr_fasync(-1, filp, 0);
        decr = (filp->f_mode & FMODE_READ) != 0;
        decw = (filp->f_mode & FMODE_WRITE) != 0;
        return pipe_release(inode, decr, decw);
@@ -777,45 +798,10 @@ pipe_rdwr_open(struct inode *inode, struct file *filp)
 /*
  * The file_operations structs are not static because they
  * are also used in linux/fs/fifo.c to do operations on FIFOs.
+ *
+ * Pipes reuse fifos' file_operations structs.
  */
-const struct file_operations read_fifo_fops = {
-       .llseek         = no_llseek,
-       .read           = do_sync_read,
-       .aio_read       = pipe_read,
-       .write          = bad_pipe_w,
-       .poll           = pipe_poll,
-       .unlocked_ioctl = pipe_ioctl,
-       .open           = pipe_read_open,
-       .release        = pipe_read_release,
-       .fasync         = pipe_read_fasync,
-};
-
-const struct file_operations write_fifo_fops = {
-       .llseek         = no_llseek,
-       .read           = bad_pipe_r,
-       .write          = do_sync_write,
-       .aio_write      = pipe_write,
-       .poll           = pipe_poll,
-       .unlocked_ioctl = pipe_ioctl,
-       .open           = pipe_write_open,
-       .release        = pipe_write_release,
-       .fasync         = pipe_write_fasync,
-};
-
-const struct file_operations rdwr_fifo_fops = {
-       .llseek         = no_llseek,
-       .read           = do_sync_read,
-       .aio_read       = pipe_read,
-       .write          = do_sync_write,
-       .aio_write      = pipe_write,
-       .poll           = pipe_poll,
-       .unlocked_ioctl = pipe_ioctl,
-       .open           = pipe_rdwr_open,
-       .release        = pipe_rdwr_release,
-       .fasync         = pipe_rdwr_fasync,
-};
-
-static const struct file_operations read_pipe_fops = {
+const struct file_operations read_pipefifo_fops = {
        .llseek         = no_llseek,
        .read           = do_sync_read,
        .aio_read       = pipe_read,
@@ -827,7 +813,7 @@ static const struct file_operations read_pipe_fops = {
        .fasync         = pipe_read_fasync,
 };
 
-static const struct file_operations write_pipe_fops = {
+const struct file_operations write_pipefifo_fops = {
        .llseek         = no_llseek,
        .read           = bad_pipe_r,
        .write          = do_sync_write,
@@ -839,7 +825,7 @@ static const struct file_operations write_pipe_fops = {
        .fasync         = pipe_write_fasync,
 };
 
-static const struct file_operations rdwr_pipe_fops = {
+const struct file_operations rdwr_pipefifo_fops = {
        .llseek         = no_llseek,
        .read           = do_sync_read,
        .aio_read       = pipe_read,
@@ -908,7 +894,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,
 };
@@ -927,7 +913,7 @@ static struct inode * get_pipe_inode(void)
        inode->i_pipe = pipe;
 
        pipe->readers = pipe->writers = 1;
-       inode->i_fop = &rdwr_pipe_fops;
+       inode->i_fop = &rdwr_pipefifo_fops;
 
        /*
         * Mark the inode dirty from the very beginning,
@@ -937,8 +923,8 @@ static struct inode * get_pipe_inode(void)
         */
        inode->i_state = I_DIRTY;
        inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;
-       inode->i_uid = current->fsuid;
-       inode->i_gid = current->fsgid;
+       inode->i_uid = current_fsuid();
+       inode->i_gid = current_fsgid();
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 
        return inode;
@@ -950,7 +936,7 @@ fail_inode:
        return NULL;
 }
 
-struct file *create_write_pipe(void)
+struct file *create_write_pipe(int flags)
 {
        int err;
        struct inode *inode;
@@ -978,12 +964,12 @@ struct file *create_write_pipe(void)
        d_instantiate(dentry, inode);
 
        err = -ENFILE;
-       f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipe_fops);
+       f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipefifo_fops);
        if (!f)
                goto err_dentry;
        f->f_mapping = inode->i_mapping;
 
-       f->f_flags = O_WRONLY;
+       f->f_flags = O_WRONLY | (flags & O_NONBLOCK);
        f->f_version = 0;
 
        return f;
@@ -1007,7 +993,7 @@ void free_write_pipe(struct file *f)
        put_filp(f);
 }
 
-struct file *create_read_pipe(struct file *wrf)
+struct file *create_read_pipe(struct file *wrf, int flags)
 {
        struct file *f = get_empty_filp();
        if (!f)
@@ -1019,8 +1005,8 @@ struct file *create_read_pipe(struct file *wrf)
        f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
 
        f->f_pos = 0;
-       f->f_flags = O_RDONLY;
-       f->f_op = &read_pipe_fops;
+       f->f_flags = O_RDONLY | (flags & O_NONBLOCK);
+       f->f_op = &read_pipefifo_fops;
        f->f_mode = FMODE_READ;
        f->f_version = 0;
 
@@ -1033,13 +1019,13 @@ int do_pipe_flags(int *fd, int flags)
        int error;
        int fdw, fdr;
 
-       if (flags & ~O_CLOEXEC)
+       if (flags & ~(O_CLOEXEC | O_NONBLOCK))
                return -EINVAL;
 
-       fw = create_write_pipe();
+       fw = create_write_pipe(flags);
        if (IS_ERR(fw))
                return PTR_ERR(fw);
-       fr = create_read_pipe(fw);
+       fr = create_read_pipe(fw, flags);
        error = PTR_ERR(fr);
        if (IS_ERR(fr))
                goto err_write_pipe;
@@ -1054,10 +1040,7 @@ int do_pipe_flags(int *fd, int flags)
                goto err_fdr;
        fdw = error;
 
-       error = audit_fd_pair(fdr, fdw);
-       if (error < 0)
-               goto err_fdw;
-
+       audit_fd_pair(fdr, fdw);
        fd_install(fdr, fr);
        fd_install(fdw, fw);
        fd[0] = fdr;
@@ -1065,8 +1048,6 @@ int do_pipe_flags(int *fd, int flags)
 
        return 0;
 
- err_fdw:
-       put_unused_fd(fdw);
  err_fdr:
        put_unused_fd(fdr);
  err_read_pipe:
@@ -1077,16 +1058,11 @@ 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.
  */
-asmlinkage long __weak sys_pipe2(int __user *fildes, int flags)
+SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags)
 {
        int fd[2];
        int error;
@@ -1102,7 +1078,7 @@ asmlinkage long __weak sys_pipe2(int __user *fildes, int flags)
        return error;
 }
 
-asmlinkage long __weak sys_pipe(int __user *fildes)
+SYSCALL_DEFINE1(pipe, int __user *, fildes)
 {
        return sys_pipe2(fildes, 0);
 }