diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-03-05 22:53:04 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-05-06 17:32:49 -0400 |
commit | ed978a811ec528dbe40243605c3afab55892f722 (patch) | |
tree | 7b8b83a755286192b98bb7921fa4d6957709216e /mm/filemap.c | |
parent | 23faa7b8db9be0be4f158cfc558460bb95d9b245 (diff) |
new helper: generic_file_read_iter()
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>
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 67 |
1 files changed, 34 insertions, 33 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 866f4ae8223b..a7f79e90209c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -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 |