Merge tag 'compat-ioctl-5.5' of git://git.kernel.org:/pub/scm/linux/kernel/git/arnd...
[linux-2.6-block.git] / fs / fuse / dev.c
index 23b089e6880a61d936053ea40e340668d285ac6b..d4e6691d2d92ccbd0e022c43478d4e46038aa985 100644 (file)
@@ -276,10 +276,12 @@ static void flush_bg_queue(struct fuse_conn *fc)
 void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req)
 {
        struct fuse_iqueue *fiq = &fc->iq;
-       bool async = req->args->end;
+       bool async;
 
        if (test_and_set_bit(FR_FINISHED, &req->flags))
                goto put_request;
+
+       async = req->args->end;
        /*
         * test_and_set_bit() implies smp_mb() between bit
         * changing and below intr_entry check. Pairs with
@@ -703,7 +705,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
                        cs->pipebufs++;
                        cs->nr_segs--;
                } else {
-                       if (cs->nr_segs == cs->pipe->buffers)
+                       if (cs->nr_segs >= cs->pipe->max_usage)
                                return -EIO;
 
                        page = alloc_page(GFP_HIGHUSER);
@@ -879,7 +881,7 @@ static int fuse_ref_page(struct fuse_copy_state *cs, struct page *page,
        struct pipe_buffer *buf;
        int err;
 
-       if (cs->nr_segs == cs->pipe->buffers)
+       if (cs->nr_segs >= cs->pipe->max_usage)
                return -EIO;
 
        err = unlock_request(cs->req);
@@ -1341,7 +1343,7 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
        if (!fud)
                return -EPERM;
 
-       bufs = kvmalloc_array(pipe->buffers, sizeof(struct pipe_buffer),
+       bufs = kvmalloc_array(pipe->max_usage, sizeof(struct pipe_buffer),
                              GFP_KERNEL);
        if (!bufs)
                return -ENOMEM;
@@ -1353,7 +1355,7 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
        if (ret < 0)
                goto out;
 
-       if (pipe->nrbufs + cs.nr_segs > pipe->buffers) {
+       if (pipe_occupancy(pipe->head, pipe->tail) + cs.nr_segs > pipe->max_usage) {
                ret = -EIO;
                goto out;
        }
@@ -1935,6 +1937,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
                                     struct file *out, loff_t *ppos,
                                     size_t len, unsigned int flags)
 {
+       unsigned int head, tail, mask, count;
        unsigned nbuf;
        unsigned idx;
        struct pipe_buffer *bufs;
@@ -1949,8 +1952,12 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 
        pipe_lock(pipe);
 
-       bufs = kvmalloc_array(pipe->nrbufs, sizeof(struct pipe_buffer),
-                             GFP_KERNEL);
+       head = pipe->head;
+       tail = pipe->tail;
+       mask = pipe->ring_size - 1;
+       count = head - tail;
+
+       bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL);
        if (!bufs) {
                pipe_unlock(pipe);
                return -ENOMEM;
@@ -1958,8 +1965,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 
        nbuf = 0;
        rem = 0;
-       for (idx = 0; idx < pipe->nrbufs && rem < len; idx++)
-               rem += pipe->bufs[(pipe->curbuf + idx) & (pipe->buffers - 1)].len;
+       for (idx = tail; idx < head && rem < len; idx++)
+               rem += pipe->bufs[idx & mask].len;
 
        ret = -EINVAL;
        if (rem < len)
@@ -1970,16 +1977,16 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
                struct pipe_buffer *ibuf;
                struct pipe_buffer *obuf;
 
-               BUG_ON(nbuf >= pipe->buffers);
-               BUG_ON(!pipe->nrbufs);
-               ibuf = &pipe->bufs[pipe->curbuf];
+               BUG_ON(nbuf >= pipe->ring_size);
+               BUG_ON(tail == head);
+               ibuf = &pipe->bufs[tail & mask];
                obuf = &bufs[nbuf];
 
                if (rem >= ibuf->len) {
                        *obuf = *ibuf;
                        ibuf->ops = NULL;
-                       pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1);
-                       pipe->nrbufs--;
+                       tail++;
+                       pipe->tail = tail;
                } else {
                        if (!pipe_buf_get(pipe, ibuf))
                                goto out_free;