fuse: use iov_iter_get_pages() for non-splice path
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 4 Apr 2015 02:06:08 +0000 (22:06 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 12 Apr 2015 02:29:41 +0000 (22:29 -0400)
store reference to iter instead of that to iovec

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/fuse/dev.c

index 89bf9df..c8b68ab 100644 (file)
@@ -710,28 +710,26 @@ struct fuse_copy_state {
        struct fuse_conn *fc;
        int write;
        struct fuse_req *req;
-       const struct iovec *iov;
+       struct iov_iter *iter;
        struct pipe_buffer *pipebufs;
        struct pipe_buffer *currbuf;
        struct pipe_inode_info *pipe;
        unsigned long nr_segs;
-       unsigned long seglen;
-       unsigned long addr;
        struct page *pg;
        unsigned len;
        unsigned offset;
        unsigned move_pages:1;
 };
 
-static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc,
+static void fuse_copy_init(struct fuse_copy_state *cs,
+                          struct fuse_conn *fc,
                           int write,
-                          const struct iovec *iov, unsigned long nr_segs)
+                          struct iov_iter *iter)
 {
        memset(cs, 0, sizeof(*cs));
        cs->fc = fc;
        cs->write = write;
-       cs->iov = iov;
-       cs->nr_segs = nr_segs;
+       cs->iter = iter;
 }
 
 /* Unmap and put previous page of userspace buffer */
@@ -799,22 +797,16 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
                        cs->nr_segs++;
                }
        } else {
-               if (!cs->seglen) {
-                       BUG_ON(!cs->nr_segs);
-                       cs->seglen = cs->iov[0].iov_len;
-                       cs->addr = (unsigned long) cs->iov[0].iov_base;
-                       cs->iov++;
-                       cs->nr_segs--;
-               }
-               err = get_user_pages_fast(cs->addr, 1, cs->write, &page);
+               size_t off;
+               err = iov_iter_get_pages(cs->iter, &page, PAGE_SIZE, 1, &off);
                if (err < 0)
                        return err;
-               BUG_ON(err != 1);
+               BUG_ON(!err);
+               cs->len = err;
+               cs->offset = off;
                cs->pg = page;
-               cs->offset = cs->addr % PAGE_SIZE;
-               cs->len = min(PAGE_SIZE - cs->offset, cs->seglen);
-               cs->seglen -= cs->len;
-               cs->addr += cs->len;
+               cs->offset = off;
+               iov_iter_advance(cs->iter, err);
        }
 
        return lock_request(cs->fc, cs->req);
@@ -1374,7 +1366,7 @@ static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to)
        if (!iter_is_iovec(to))
                return -EINVAL;
 
-       fuse_copy_init(&cs, fc, 1, to->iov, to->nr_segs);
+       fuse_copy_init(&cs, fc, 1, to);
 
        return fuse_dev_do_read(fc, file, &cs, iov_iter_count(to));
 }
@@ -1396,7 +1388,7 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
        if (!bufs)
                return -ENOMEM;
 
-       fuse_copy_init(&cs, fc, 1, NULL, 0);
+       fuse_copy_init(&cs, fc, 1, NULL);
        cs.pipebufs = bufs;
        cs.pipe = pipe;
        ret = fuse_dev_do_read(fc, in, &cs, len);
@@ -1982,7 +1974,7 @@ static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from)
        if (!iter_is_iovec(from))
                return -EINVAL;
 
-       fuse_copy_init(&cs, fc, 0, from->iov, from->nr_segs);
+       fuse_copy_init(&cs, fc, 0, from);
 
        return fuse_dev_do_write(fc, &cs, iov_iter_count(from));
 }
@@ -2047,8 +2039,9 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
        }
        pipe_unlock(pipe);
 
-       fuse_copy_init(&cs, fc, 0, NULL, nbuf);
+       fuse_copy_init(&cs, fc, 0, NULL);
        cs.pipebufs = bufs;
+       cs.nr_segs = nbuf;
        cs.pipe = pipe;
 
        if (flags & SPLICE_F_MOVE)