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>
This commit is contained in:
Родитель
23faa7b8db
Коммит
ed978a811e
|
@ -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);
|
||||
|
|
|
@ -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 *,
|
||||
|
|
103
mm/filemap.c
103
mm/filemap.c
|
@ -1663,6 +1663,56 @@ out:
|
|||
return written ? written : error;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
ssize_t retval = 0;
|
||||
loff_t *ppos = &iocb->ki_pos;
|
||||
loff_t pos = *ppos;
|
||||
|
||||
/* coalesce the iovecs and go direct-to-BIO for 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;
|
||||
|
||||
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 = *iter;
|
||||
retval = mapping->a_ops->direct_IO(READ, iocb, &data, pos);
|
||||
}
|
||||
|
||||
if (retval > 0) {
|
||||
*ppos = pos + retval;
|
||||
iov_iter_advance(iter, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Btrfs can have a short DIO read if we encounter
|
||||
* compressed extents, so if there was an error, or if
|
||||
* we've already read everything we wanted to, or if
|
||||
* there was a short read because we hit EOF, go ahead
|
||||
* and return. Otherwise fallthrough to buffered io for
|
||||
* the rest of the read.
|
||||
*/
|
||||
if (retval < 0 || !iov_iter_count(iter) || *ppos >= size) {
|
||||
file_accessed(file);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -1677,60 +1727,11 @@ ssize_t
|
|||
generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
struct file *filp = iocb->ki_filp;
|
||||
ssize_t retval = 0;
|
||||
size_t count;
|
||||
loff_t *ppos = &iocb->ki_pos;
|
||||
size_t count = iov_length(iov, nr_segs);
|
||||
struct iov_iter i;
|
||||
|
||||
count = iov_length(iov, nr_segs);
|
||||
iov_iter_init(&i, iov, nr_segs, count, 0);
|
||||
|
||||
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
|
||||
if (filp->f_flags & O_DIRECT) {
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Btrfs can have a short DIO read if we encounter
|
||||
* compressed extents, so if there was an error, or if
|
||||
* we've already read everything we wanted to, or if
|
||||
* there was a short read because we hit EOF, go ahead
|
||||
* and return. Otherwise fallthrough to buffered io for
|
||||
* the rest of the read.
|
||||
*/
|
||||
if (retval < 0 || !count || *ppos >= size) {
|
||||
file_accessed(filp);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
retval = do_generic_file_read(filp, ppos, &i, retval);
|
||||
out:
|
||||
return retval;
|
||||
return generic_file_read_iter(iocb, &i);
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_aio_read);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче