Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed978a81 authored by Al Viro's avatar Al Viro
Browse files

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
Loading
Loading
Loading
Loading
+1 −14
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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);
	}
+1 −0
Original line number Diff line number Diff line
@@ -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 *,
+34 −33
Original line number Diff line number Diff line
@@ -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