Make checkpatch.pl shut up on fs/inode.c
[safe/jmp/linux-2.6] / fs / splice.c
index dd727d4..666953d 100644 (file)
@@ -182,8 +182,7 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
        do_wakeup = 0;
        page_nr = 0;
 
-       if (pipe->inode)
-               mutex_lock(&pipe->inode->i_mutex);
+       pipe_lock(pipe);
 
        for (;;) {
                if (!pipe->readers) {
@@ -245,15 +244,13 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
                pipe->waiting_writers--;
        }
 
-       if (pipe->inode) {
-               mutex_unlock(&pipe->inode->i_mutex);
+       pipe_unlock(pipe);
 
-               if (do_wakeup) {
-                       smp_mb();
-                       if (waitqueue_active(&pipe->wait))
-                               wake_up_interruptible(&pipe->wait);
-                       kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
-               }
+       if (do_wakeup) {
+               smp_mb();
+               if (waitqueue_active(&pipe->wait))
+                       wake_up_interruptible(&pipe->wait);
+               kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
        }
 
        while (page_nr < spd_pages)
@@ -555,8 +552,8 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe,
  * SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create
  * a new page in the output file page cache and fill/dirty that.
  */
-static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
-                       struct splice_desc *sd)
+int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+                struct splice_desc *sd)
 {
        struct file *file = sd->u.file;
        struct address_space *mapping = file->f_mapping;
@@ -600,108 +597,177 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
 out:
        return ret;
 }
+EXPORT_SYMBOL(pipe_to_file);
+
+static void wakeup_pipe_writers(struct pipe_inode_info *pipe)
+{
+       smp_mb();
+       if (waitqueue_active(&pipe->wait))
+               wake_up_interruptible(&pipe->wait);
+       kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
+}
 
 /**
- * __splice_from_pipe - splice data from a pipe to given actor
+ * splice_from_pipe_feed - feed available data from a pipe to a file
  * @pipe:      pipe to splice from
  * @sd:                information to @actor
  * @actor:     handler that splices the data
  *
  * Description:
- *    This function does little more than loop over the pipe and call
- *    @actor to do the actual moving of a single struct pipe_buffer to
- *    the desired destination. See pipe_to_file, pipe_to_sendpage, or
- *    pipe_to_user.
+ *    This function loops over the pipe and calls @actor to do the
+ *    actual moving of a single struct pipe_buffer to the desired
+ *    destination.  It returns when there's no more buffers left in
+ *    the pipe or if the requested number of bytes (@sd->total_len)
+ *    have been copied.  It returns a positive number (one) if the
+ *    pipe needs to be filled with more data, zero if the required
+ *    number of bytes have been copied and -errno on error.
  *
+ *    This, together with splice_from_pipe_{begin,end,next}, may be
+ *    used to implement the functionality of __splice_from_pipe() when
+ *    locking is required around copying the pipe buffers to the
+ *    destination.
  */
-ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
-                          splice_actor *actor)
+int splice_from_pipe_feed(struct pipe_inode_info *pipe, struct splice_desc *sd,
+                         splice_actor *actor)
 {
-       int ret, do_wakeup, err;
-
-       ret = 0;
-       do_wakeup = 0;
-
-       for (;;) {
-               if (pipe->nrbufs) {
-                       struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
-                       const struct pipe_buf_operations *ops = buf->ops;
+       int ret;
 
-                       sd->len = buf->len;
-                       if (sd->len > sd->total_len)
-                               sd->len = sd->total_len;
+       while (pipe->nrbufs) {
+               struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
+               const struct pipe_buf_operations *ops = buf->ops;
 
-                       err = actor(pipe, buf, sd);
-                       if (err <= 0) {
-                               if (!ret && err != -ENODATA)
-                                       ret = err;
+               sd->len = buf->len;
+               if (sd->len > sd->total_len)
+                       sd->len = sd->total_len;
 
-                               break;
-                       }
+               ret = actor(pipe, buf, sd);
+               if (ret <= 0) {
+                       if (ret == -ENODATA)
+                               ret = 0;
+                       return ret;
+               }
+               buf->offset += ret;
+               buf->len -= ret;
 
-                       ret += err;
-                       buf->offset += err;
-                       buf->len -= err;
+               sd->num_spliced += ret;
+               sd->len -= ret;
+               sd->pos += ret;
+               sd->total_len -= ret;
 
-                       sd->len -= err;
-                       sd->pos += err;
-                       sd->total_len -= err;
-                       if (sd->len)
-                               continue;
+               if (!buf->len) {
+                       buf->ops = NULL;
+                       ops->release(pipe, buf);
+                       pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
+                       pipe->nrbufs--;
+                       if (pipe->inode)
+                               sd->need_wakeup = true;
+               }
 
-                       if (!buf->len) {
-                               buf->ops = NULL;
-                               ops->release(pipe, buf);
-                               pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
-                               pipe->nrbufs--;
-                               if (pipe->inode)
-                                       do_wakeup = 1;
-                       }
+               if (!sd->total_len)
+                       return 0;
+       }
 
-                       if (!sd->total_len)
-                               break;
-               }
+       return 1;
+}
+EXPORT_SYMBOL(splice_from_pipe_feed);
 
-               if (pipe->nrbufs)
-                       continue;
+/**
+ * splice_from_pipe_next - wait for some data to splice from
+ * @pipe:      pipe to splice from
+ * @sd:                information about the splice operation
+ *
+ * Description:
+ *    This function will wait for some data and return a positive
+ *    value (one) if pipe buffers are available.  It will return zero
+ *    or -errno if no more data needs to be spliced.
+ */
+int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_desc *sd)
+{
+       while (!pipe->nrbufs) {
                if (!pipe->writers)
-                       break;
-               if (!pipe->waiting_writers) {
-                       if (ret)
-                               break;
-               }
+                       return 0;
 
-               if (sd->flags & SPLICE_F_NONBLOCK) {
-                       if (!ret)
-                               ret = -EAGAIN;
-                       break;
-               }
+               if (!pipe->waiting_writers && sd->num_spliced)
+                       return 0;
 
-               if (signal_pending(current)) {
-                       if (!ret)
-                               ret = -ERESTARTSYS;
-                       break;
-               }
+               if (sd->flags & SPLICE_F_NONBLOCK)
+                       return -EAGAIN;
 
-               if (do_wakeup) {
-                       smp_mb();
-                       if (waitqueue_active(&pipe->wait))
-                               wake_up_interruptible_sync(&pipe->wait);
-                       kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
-                       do_wakeup = 0;
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+
+               if (sd->need_wakeup) {
+                       wakeup_pipe_writers(pipe);
+                       sd->need_wakeup = false;
                }
 
                pipe_wait(pipe);
        }
 
-       if (do_wakeup) {
-               smp_mb();
-               if (waitqueue_active(&pipe->wait))
-                       wake_up_interruptible(&pipe->wait);
-               kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
-       }
+       return 1;
+}
+EXPORT_SYMBOL(splice_from_pipe_next);
 
-       return ret;
+/**
+ * splice_from_pipe_begin - start splicing from pipe
+ * @sd:                information about the splice operation
+ *
+ * Description:
+ *    This function should be called before a loop containing
+ *    splice_from_pipe_next() and splice_from_pipe_feed() to
+ *    initialize the necessary fields of @sd.
+ */
+void splice_from_pipe_begin(struct splice_desc *sd)
+{
+       sd->num_spliced = 0;
+       sd->need_wakeup = false;
+}
+EXPORT_SYMBOL(splice_from_pipe_begin);
+
+/**
+ * splice_from_pipe_end - finish splicing from pipe
+ * @pipe:      pipe to splice from
+ * @sd:                information about the splice operation
+ *
+ * Description:
+ *    This function will wake up pipe writers if necessary.  It should
+ *    be called after a loop containing splice_from_pipe_next() and
+ *    splice_from_pipe_feed().
+ */
+void splice_from_pipe_end(struct pipe_inode_info *pipe, struct splice_desc *sd)
+{
+       if (sd->need_wakeup)
+               wakeup_pipe_writers(pipe);
+}
+EXPORT_SYMBOL(splice_from_pipe_end);
+
+/**
+ * __splice_from_pipe - splice data from a pipe to given actor
+ * @pipe:      pipe to splice from
+ * @sd:                information to @actor
+ * @actor:     handler that splices the data
+ *
+ * Description:
+ *    This function does little more than loop over the pipe and call
+ *    @actor to do the actual moving of a single struct pipe_buffer to
+ *    the desired destination. See pipe_to_file, pipe_to_sendpage, or
+ *    pipe_to_user.
+ *
+ */
+ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
+                          splice_actor *actor)
+{
+       int ret;
+
+       splice_from_pipe_begin(sd);
+       do {
+               ret = splice_from_pipe_next(pipe, sd);
+               if (ret > 0)
+                       ret = splice_from_pipe_feed(pipe, sd, actor);
+       } while (ret > 0);
+       splice_from_pipe_end(pipe, sd);
+
+       return sd->num_spliced ? sd->num_spliced : ret;
 }
 EXPORT_SYMBOL(__splice_from_pipe);
 
@@ -715,7 +781,7 @@ EXPORT_SYMBOL(__splice_from_pipe);
  * @actor:     handler that splices the data
  *
  * Description:
- *    See __splice_from_pipe. This function locks the input and output inodes,
+ *    See __splice_from_pipe. This function locks the pipe inode,
  *    otherwise it's identical to __splice_from_pipe().
  *
  */
@@ -724,7 +790,6 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
                         splice_actor *actor)
 {
        ssize_t ret;
-       struct inode *inode = out->f_mapping->host;
        struct splice_desc sd = {
                .total_len = len,
                .flags = flags,
@@ -732,21 +797,15 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
                .u.file = out,
        };
 
-       /*
-        * The actor worker might be calling ->write_begin and
-        * ->write_end. Most of the time, these expect i_mutex to
-        * be held. Since this may result in an ABBA deadlock with
-        * pipe->inode, we have to order lock acquiry here.
-        */
-       inode_double_lock(inode, pipe->inode);
+       pipe_lock(pipe);
        ret = __splice_from_pipe(pipe, &sd, actor);
-       inode_double_unlock(inode, pipe->inode);
+       pipe_unlock(pipe);
 
        return ret;
 }
 
 /**
- * generic_file_splice_write_nolock - generic_file_splice_write without mutexes
+ * generic_file_splice_write - splice data from a pipe to a file
  * @pipe:      pipe info
  * @out:       file to write to
  * @ppos:      position in @out
@@ -755,13 +814,12 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
  *
  * Description:
  *    Will either move or copy pages (determined by @flags options) from
- *    the given pipe inode to the given file. The caller is responsible
- *    for acquiring i_mutex on both inodes.
+ *    the given pipe inode to the given file.
  *
  */
 ssize_t
-generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
-                                loff_t *ppos, size_t len, unsigned int flags)
+generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
+                         loff_t *ppos, size_t len, unsigned int flags)
 {
        struct address_space *mapping = out->f_mapping;
        struct inode *inode = mapping->host;
@@ -772,70 +830,28 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
                .u.file = out,
        };
        ssize_t ret;
-       int err;
-
-       err = file_remove_suid(out);
-       if (unlikely(err))
-               return err;
-
-       ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
-       if (ret > 0) {
-               unsigned long nr_pages;
 
-               *ppos += ret;
-               nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       pipe_lock(pipe);
 
-               /*
-                * If file or inode is SYNC and we actually wrote some data,
-                * sync it.
-                */
-               if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
-                       err = generic_osync_inode(inode, mapping,
-                                                 OSYNC_METADATA|OSYNC_DATA);
-
-                       if (err)
-                               ret = err;
-               }
-               balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
-       }
+       splice_from_pipe_begin(&sd);
+       do {
+               ret = splice_from_pipe_next(pipe, &sd);
+               if (ret <= 0)
+                       break;
 
-       return ret;
-}
+               mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
+               ret = file_remove_suid(out);
+               if (!ret)
+                       ret = splice_from_pipe_feed(pipe, &sd, pipe_to_file);
+               mutex_unlock(&inode->i_mutex);
+       } while (ret > 0);
+       splice_from_pipe_end(pipe, &sd);
 
-EXPORT_SYMBOL(generic_file_splice_write_nolock);
+       pipe_unlock(pipe);
 
-/**
- * generic_file_splice_write - splice data from a pipe to a file
- * @pipe:      pipe info
- * @out:       file to write to
- * @ppos:      position in @out
- * @len:       number of bytes to splice
- * @flags:     splice modifier flags
- *
- * Description:
- *    Will either move or copy pages (determined by @flags options) from
- *    the given pipe inode to the given file.
- *
- */
-ssize_t
-generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
-                         loff_t *ppos, size_t len, unsigned int flags)
-{
-       struct address_space *mapping = out->f_mapping;
-       struct inode *inode = mapping->host;
-       struct splice_desc sd = {
-               .total_len = len,
-               .flags = flags,
-               .pos = *ppos,
-               .u.file = out,
-       };
-       ssize_t ret;
+       if (sd.num_spliced)
+               ret = sd.num_spliced;
 
-       inode_double_lock(inode, pipe->inode);
-       ret = file_remove_suid(out);
-       if (likely(!ret))
-               ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
-       inode_double_unlock(inode, pipe->inode);
        if (ret > 0) {
                unsigned long nr_pages;
 
@@ -1324,8 +1340,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
        if (!pipe)
                return -EBADF;
 
-       if (pipe->inode)
-               mutex_lock(&pipe->inode->i_mutex);
+       pipe_lock(pipe);
 
        error = ret = 0;
        while (nr_segs) {
@@ -1380,8 +1395,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
                iov++;
        }
 
-       if (pipe->inode)
-               mutex_unlock(&pipe->inode->i_mutex);
+       pipe_unlock(pipe);
 
        if (!ret)
                ret = error;
@@ -1509,7 +1523,7 @@ static int link_ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags)
                return 0;
 
        ret = 0;
-       mutex_lock(&pipe->inode->i_mutex);
+       pipe_lock(pipe);
 
        while (!pipe->nrbufs) {
                if (signal_pending(current)) {
@@ -1527,7 +1541,7 @@ static int link_ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags)
                pipe_wait(pipe);
        }
 
-       mutex_unlock(&pipe->inode->i_mutex);
+       pipe_unlock(pipe);
        return ret;
 }
 
@@ -1547,7 +1561,7 @@ static int link_opipe_prep(struct pipe_inode_info *pipe, unsigned int flags)
                return 0;
 
        ret = 0;
-       mutex_lock(&pipe->inode->i_mutex);
+       pipe_lock(pipe);
 
        while (pipe->nrbufs >= PIPE_BUFFERS) {
                if (!pipe->readers) {
@@ -1568,7 +1582,7 @@ static int link_opipe_prep(struct pipe_inode_info *pipe, unsigned int flags)
                pipe->waiting_writers--;
        }
 
-       mutex_unlock(&pipe->inode->i_mutex);
+       pipe_unlock(pipe);
        return ret;
 }
 
@@ -1584,10 +1598,10 @@ static int link_pipe(struct pipe_inode_info *ipipe,
 
        /*
         * Potential ABBA deadlock, work around it by ordering lock
-        * grabbing by inode address. Otherwise two different processes
+        * grabbing by pipe info address. Otherwise two different processes
         * could deadlock (one doing tee from A -> B, the other from B -> A).
         */
-       inode_double_lock(ipipe->inode, opipe->inode);
+       pipe_double_lock(ipipe, opipe);
 
        do {
                if (!opipe->readers) {
@@ -1638,7 +1652,8 @@ static int link_pipe(struct pipe_inode_info *ipipe,
        if (!ret && ipipe->waiting_writers && (flags & SPLICE_F_NONBLOCK))
                ret = -EAGAIN;
 
-       inode_double_unlock(ipipe->inode, opipe->inode);
+       pipe_unlock(ipipe);
+       pipe_unlock(opipe);
 
        /*
         * If we put data in the output pipe, wakeup any potential readers.