new helper: generic_file_read_iter()
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 6 Mar 2014 03:53:04 +0000 (22:53 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Tue, 6 May 2014 21:32:49 +0000 (17:32 -0400)
iov_iter-using variant of generic_file_aio_read().  Some callers
converted.  Note that it's still not quite there for use as ->read_iter() -
we depend on having zero iter->iov_offset in O_DIRECT case.  Fortunately,
that's true for all converted callers (and for generic_file_aio_read() itself).

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/ceph/file.c
fs/nfs/file.c
include/linux/fs.h
mm/filemap.c

index d8f383d..910a302 100644 (file)
@@ -833,24 +833,11 @@ again:
                /* hmm, this isn't really async... */
                ret = ceph_sync_read(iocb, &i, &checkeof);
        } else {
-               /*
-                * We can't modify the content of iov,
-                * so we only read from beginning.
-                *
-                * When we switch generic_file_aio_read() to iov_iter, the
-                * if () below will be removed -- AV
-                */
-               if (read) {
-                       iocb->ki_pos = pos;
-                       len = iocb->ki_nbytes;
-                       read = 0;
-                       iov_iter_init(&i, iov, nr_segs, len, 0);
-               }
                dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n",
                     inode, ceph_vinop(inode), pos, (unsigned)len,
                     ceph_cap_string(got));
 
-               ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
+               ret = generic_file_read_iter(iocb, &i);
        }
        dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n",
             inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret);
index 3d01b15..a352bc6 100644 (file)
@@ -184,7 +184,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
 
        result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
        if (!result) {
-               result = generic_file_aio_read(iocb, iov, nr_segs, pos);
+               result = generic_file_read_iter(iocb, &to);
                if (result > 0)
                        nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, result);
        }
index 946a948..d096ebc 100644 (file)
@@ -2404,6 +2404,7 @@ extern int generic_file_remap_pages(struct vm_area_struct *, unsigned long addr,
                unsigned long size, pgoff_t pgoff);
 int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk);
 extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *);
 extern ssize_t __generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long);
 extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
 extern ssize_t generic_file_direct_write(struct kiocb *, struct iov_iter *,
index 866f4ae..a7f79e9 100644 (file)
@@ -1663,55 +1663,34 @@ out:
        return written ? written : error;
 }
 
-/**
- * generic_file_aio_read - generic filesystem read routine
- * @iocb:      kernel I/O control block
- * @iov:       io vector request
- * @nr_segs:   number of segments in the iovec
- * @pos:       current file position
- *
- * This is the "read()" routine for all filesystems
- * that can use the page cache directly.
- */
 ssize_t
-generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
-               unsigned long nr_segs, loff_t pos)
+generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
 {
-       struct file *filp = iocb->ki_filp;
+       struct file *file = iocb->ki_filp;
        ssize_t retval = 0;
-       size_t count;
        loff_t *ppos = &iocb->ki_pos;
-       struct iov_iter i;
-
-       count = iov_length(iov, nr_segs);
-       iov_iter_init(&i, iov, nr_segs, count, 0);
+       loff_t pos = *ppos;
 
        /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
-       if (filp->f_flags & O_DIRECT) {
+       if (file->f_flags & O_DIRECT) {
+               struct address_space *mapping = file->f_mapping;
+               struct inode *inode = mapping->host;
+               size_t count = iov_iter_count(iter);
                loff_t size;
-               struct address_space *mapping;
-               struct inode *inode;
 
-               mapping = filp->f_mapping;
-               inode = mapping->host;
                if (!count)
                        goto out; /* skip atime */
                size = i_size_read(inode);
                retval = filemap_write_and_wait_range(mapping, pos,
                                        pos + count - 1);
                if (!retval) {
-                       struct iov_iter data = i;
+                       struct iov_iter data = *iter;
                        retval = mapping->a_ops->direct_IO(READ, iocb, &data, pos);
                }
 
                if (retval > 0) {
                        *ppos = pos + retval;
-                       count -= retval;
-                       /*
-                        * If we did a short DIO read we need to skip the
-                        * section of the iov that we've already read data into.
-                        */
-                       iov_iter_advance(&i, retval);
+                       iov_iter_advance(iter, retval);
                }
 
                /*
@@ -1722,16 +1701,38 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                 * and return.  Otherwise fallthrough to buffered io for
                 * the rest of the read.
                 */
-               if (retval < 0 || !count || *ppos >= size) {
-                       file_accessed(filp);
+               if (retval < 0 || !iov_iter_count(iter) || *ppos >= size) {
+                       file_accessed(file);
                        goto out;
                }
        }
 
-       retval = do_generic_file_read(filp, ppos, &i, retval);
+       retval = do_generic_file_read(file, ppos, iter, retval);
 out:
        return retval;
 }
+EXPORT_SYMBOL(generic_file_read_iter);
+
+/**
+ * generic_file_aio_read - generic filesystem read routine
+ * @iocb:      kernel I/O control block
+ * @iov:       io vector request
+ * @nr_segs:   number of segments in the iovec
+ * @pos:       current file position
+ *
+ * This is the "read()" routine for all filesystems
+ * that can use the page cache directly.
+ */
+ssize_t
+generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+               unsigned long nr_segs, loff_t pos)
+{
+       size_t count = iov_length(iov, nr_segs);
+       struct iov_iter i;
+
+       iov_iter_init(&i, iov, nr_segs, count, 0);
+       return generic_file_read_iter(iocb, &i);
+}
 EXPORT_SYMBOL(generic_file_aio_read);
 
 #ifdef CONFIG_MMU