Commit ed978a81 authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 23faa7b8
......@@ -833,24 +833,11 @@ static ssize_t ceph_aio_read(struct kiocb *iocb, const struct iovec *iov,
/* 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);
......
......@@ -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);
}
......
......@@ -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 *,
......
......@@ -1663,55 +1663,34 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos,
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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment