]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/fuse/file.c
Merge remote-tracking branch 'fuse/for-next'
[karo-tx-linux.git] / fs / fuse / file.c
index 7e70506297bc4f6ca4c7afd61ca457627a9d1b3b..26c33f36179af2061fd57641da00fdf0f60a0a92 100644 (file)
@@ -1179,9 +1179,10 @@ static inline void fuse_page_descs_length_init(struct fuse_req *req,
                        req->page_descs[i].offset;
 }
 
-static inline unsigned long fuse_get_user_addr(const struct iov_iter *ii)
+static inline unsigned long fuse_get_user_addr(struct iov_iter *ii)
 {
-       return (unsigned long)ii->iov->iov_base + ii->iov_offset;
+       struct iovec *iov = iov_iter_iovec(ii);
+       return (unsigned long)iov->iov_base + ii->iov_offset;
 }
 
 static inline size_t fuse_get_frag_size(const struct iov_iter *ii,
@@ -1270,9 +1271,8 @@ static inline int fuse_iter_npages(const struct iov_iter *ii_p)
        return min(npages, FUSE_MAX_PAGES_PER_REQ);
 }
 
-ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
-                      unsigned long nr_segs, size_t count, loff_t *ppos,
-                      int write)
+ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *ii,
+                      size_t count, loff_t *ppos, int write)
 {
        struct file *file = io->file;
        struct fuse_file *ff = file->private_data;
@@ -1281,14 +1281,11 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
        loff_t pos = *ppos;
        ssize_t res = 0;
        struct fuse_req *req;
-       struct iov_iter ii;
-
-       iov_iter_init(&ii, iov, nr_segs, count, 0);
 
        if (io->async)
-               req = fuse_get_req_for_background(fc, fuse_iter_npages(&ii));
+               req = fuse_get_req_for_background(fc, fuse_iter_npages(ii));
        else
-               req = fuse_get_req(fc, fuse_iter_npages(&ii));
+               req = fuse_get_req(fc, fuse_iter_npages(ii));
        if (IS_ERR(req))
                return PTR_ERR(req);
 
@@ -1296,7 +1293,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
                size_t nres;
                fl_owner_t owner = current->files;
                size_t nbytes = min(count, nmax);
-               int err = fuse_get_user_pages(req, &ii, &nbytes, write);
+               int err = fuse_get_user_pages(req, ii, &nbytes, write);
                if (err) {
                        res = err;
                        break;
@@ -1326,9 +1323,9 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
                        fuse_put_request(fc, req);
                        if (io->async)
                                req = fuse_get_req_for_background(fc,
-                                       fuse_iter_npages(&ii));
+                                       fuse_iter_npages(ii));
                        else
-                               req = fuse_get_req(fc, fuse_iter_npages(&ii));
+                               req = fuse_get_req(fc, fuse_iter_npages(ii));
                        if (IS_ERR(req))
                                break;
                }
@@ -1342,10 +1339,8 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
 }
 EXPORT_SYMBOL_GPL(fuse_direct_io);
 
-static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
-                                 const struct iovec *iov,
-                                 unsigned long nr_segs, loff_t *ppos,
-                                 size_t count)
+static ssize_t __fuse_direct_read(struct fuse_io_priv *io, struct iov_iter *ii,
+                                 loff_t *ppos, size_t count)
 {
        ssize_t res;
        struct file *file = io->file;
@@ -1354,7 +1349,7 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
        if (is_bad_inode(inode))
                return -EIO;
 
-       res = fuse_direct_io(io, iov, nr_segs, count, ppos, 0);
+       res = fuse_direct_io(io, ii, count, ppos, 0);
 
        fuse_invalidate_attr(inode);
 
@@ -1366,21 +1361,24 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
 {
        struct fuse_io_priv io = { .async = 0, .file = file };
        struct iovec iov = { .iov_base = buf, .iov_len = count };
-       return __fuse_direct_read(&io, &iov, 1, ppos, count);
+       struct iov_iter ii;
+
+       iov_iter_init(&ii, &iov, 1, count, 0);
+
+       return __fuse_direct_read(&io, &ii, ppos, count);
 }
 
-static ssize_t __fuse_direct_write(struct fuse_io_priv *io,
-                                  const struct iovec *iov,
-                                  unsigned long nr_segs, loff_t *ppos)
+static ssize_t __fuse_direct_write(struct fuse_io_priv *io, struct iov_iter *ii,
+                                  loff_t *ppos)
 {
        struct file *file = io->file;
        struct inode *inode = file_inode(file);
-       size_t count = iov_length(iov, nr_segs);
+       size_t count = iov_iter_count(ii);
        ssize_t res;
 
        res = generic_write_checks(file, ppos, &count, 0);
        if (!res)
-               res = fuse_direct_io(io, iov, nr_segs, count, ppos, 1);
+               res = fuse_direct_io(io, ii, count, ppos, 1);
 
        fuse_invalidate_attr(inode);
 
@@ -1391,6 +1389,7 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 {
        struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
+       struct iov_iter ii;
        struct inode *inode = file_inode(file);
        ssize_t res;
        struct fuse_io_priv io = { .async = 0, .file = file };
@@ -1398,9 +1397,11 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
        if (is_bad_inode(inode))
                return -EIO;
 
+       iov_iter_init(&ii, &iov, 1, count, 0);
+
        /* Don't allow parallel writes to the same file */
        mutex_lock(&inode->i_mutex);
-       res = __fuse_direct_write(&io, &iov, 1, ppos);
+       res = __fuse_direct_write(&io, &ii, ppos);
        if (res > 0)
                fuse_write_update_size(inode, *ppos);
        mutex_unlock(&inode->i_mutex);
@@ -2176,30 +2177,17 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
        while (iov_iter_count(&ii)) {
                struct page *page = pages[page_idx++];
                size_t todo = min_t(size_t, PAGE_SIZE, iov_iter_count(&ii));
-               void *kaddr;
+               size_t left;
 
-               kaddr = kmap(page);
-
-               while (todo) {
-                       char __user *uaddr = ii.iov->iov_base + ii.iov_offset;
-                       size_t iov_len = ii.iov->iov_len - ii.iov_offset;
-                       size_t copy = min(todo, iov_len);
-                       size_t left;
-
-                       if (!to_user)
-                               left = copy_from_user(kaddr, uaddr, copy);
-                       else
-                               left = copy_to_user(uaddr, kaddr, copy);
-
-                       if (unlikely(left))
-                               return -EFAULT;
+               if (!to_user)
+                       left = iov_iter_copy_from_user(page, &ii, 0, todo);
+               else
+                       left = iov_iter_copy_to_user(page, &ii, 0, todo);
 
-                       iov_iter_advance(&ii, copy);
-                       todo -= copy;
-                       kaddr += copy;
-               }
+               if (unlikely(left))
+                       return -EFAULT;
 
-               kunmap(page);
+               iov_iter_advance(&ii, todo);
        }
 
        return 0;
@@ -2693,8 +2681,8 @@ static inline loff_t fuse_round_up(loff_t off)
 }
 
 static ssize_t
-fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
-                       loff_t offset, unsigned long nr_segs)
+fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *ii,
+                       loff_t offset)
 {
        ssize_t ret = 0;
        struct file *file = iocb->ki_filp;
@@ -2703,7 +2691,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        loff_t pos = 0;
        struct inode *inode;
        loff_t i_size;
-       size_t count = iov_length(iov, nr_segs);
+       size_t count = iov_iter_count(ii);
        struct fuse_io_priv *io;
 
        pos = offset;
@@ -2744,9 +2732,9 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
                io->async = false;
 
        if (rw == WRITE)
-               ret = __fuse_direct_write(io, iov, nr_segs, &pos);
+               ret = __fuse_direct_write(io, ii, &pos);
        else
-               ret = __fuse_direct_read(io, iov, nr_segs, &pos, count);
+               ret = __fuse_direct_read(io, ii, &pos, count);
 
        if (io->async) {
                fuse_aio_complete(io, ret < 0 ? ret : 0, -1);