Merge branch 'work.splice_read' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / fs / fuse / dev.c
index c41bde2..70ea57c 100644 (file)
@@ -728,7 +728,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
                struct pipe_buffer *buf = cs->pipebufs;
 
                if (!cs->write) {
-                       err = buf->ops->confirm(cs->pipe, buf);
+                       err = pipe_buf_confirm(cs->pipe, buf);
                        if (err)
                                return err;
 
@@ -827,7 +827,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
 
        fuse_copy_finish(cs);
 
-       err = buf->ops->confirm(cs->pipe, buf);
+       err = pipe_buf_confirm(cs->pipe, buf);
        if (err)
                return err;
 
@@ -840,7 +840,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
        if (cs->len != PAGE_SIZE)
                goto out_fallback;
 
-       if (buf->ops->steal(cs->pipe, buf) != 0)
+       if (pipe_buf_steal(cs->pipe, buf) != 0)
                goto out_fallback;
 
        newpage = buf->page;
@@ -1341,9 +1341,8 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
                                    struct pipe_inode_info *pipe,
                                    size_t len, unsigned int flags)
 {
-       int ret;
+       int total, ret;
        int page_nr = 0;
-       int do_wakeup = 0;
        struct pipe_buffer *bufs;
        struct fuse_copy_state cs;
        struct fuse_dev *fud = fuse_get_dev(in);
@@ -1362,52 +1361,23 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
        if (ret < 0)
                goto out;
 
-       ret = 0;
-       pipe_lock(pipe);
-
-       if (!pipe->readers) {
-               send_sig(SIGPIPE, current, 0);
-               if (!ret)
-                       ret = -EPIPE;
-               goto out_unlock;
-       }
-
        if (pipe->nrbufs + cs.nr_segs > pipe->buffers) {
                ret = -EIO;
-               goto out_unlock;
+               goto out;
        }
 
-       while (page_nr < cs.nr_segs) {
-               int newbuf = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
-               struct pipe_buffer *buf = pipe->bufs + newbuf;
-
-               buf->page = bufs[page_nr].page;
-               buf->offset = bufs[page_nr].offset;
-               buf->len = bufs[page_nr].len;
+       for (ret = total = 0; page_nr < cs.nr_segs; total += ret) {
                /*
                 * Need to be careful about this.  Having buf->ops in module
                 * code can Oops if the buffer persists after module unload.
                 */
-               buf->ops = &nosteal_pipe_buf_ops;
-
-               pipe->nrbufs++;
-               page_nr++;
-               ret += buf->len;
-
-               if (pipe->files)
-                       do_wakeup = 1;
-       }
-
-out_unlock:
-       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);
+               bufs[page_nr].ops = &nosteal_pipe_buf_ops;
+               ret = add_to_pipe(pipe, &bufs[page_nr++]);
+               if (unlikely(ret < 0))
+                       break;
        }
-
+       if (total)
+               ret = total;
 out:
        for (; page_nr < cs.nr_segs; page_nr++)
                put_page(bufs[page_nr].page);
@@ -1992,7 +1962,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
                        pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1);
                        pipe->nrbufs--;
                } else {
-                       ibuf->ops->get(pipe, ibuf);
+                       pipe_buf_get(pipe, ibuf);
                        *obuf = *ibuf;
                        obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
                        obuf->len = rem;
@@ -2014,10 +1984,9 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 
        ret = fuse_dev_do_write(fud, &cs, len);
 
-       for (idx = 0; idx < nbuf; idx++) {
-               struct pipe_buffer *buf = &bufs[idx];
-               buf->ops->release(pipe, buf);
-       }
+       for (idx = 0; idx < nbuf; idx++)
+               pipe_buf_release(pipe, &bufs[idx]);
+
 out:
        kfree(bufs);
        return ret;