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

Commit 74f68fce authored by Al Viro's avatar Al Viro Committed by Mike Marshall
Browse files

orangefs: make pvfs2_inode_read() take iov_iter



... and make the only caller use page-backed iov_iter,
getting rid of kmap/kunmap *and* of the bug with
attempted use of iovec-backed copy_page_to_iter()
on a kernel pointer.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarMike Marshall <hubcap@omnibond.com>
parent 0071ed1e
Loading
Loading
Loading
Loading
+3 −9
Original line number Diff line number Diff line
@@ -369,22 +369,17 @@ static ssize_t do_readv_writev(enum PVFS_io_type type, struct file *file,
 * Data may be placed either in a user or kernel buffer.
 */
ssize_t pvfs2_inode_read(struct inode *inode,
			 char __user *buf,
			 size_t count,
			 struct iov_iter *iter,
			 loff_t *offset,
			 loff_t readahead_size)
{
	struct pvfs2_inode_s *pvfs2_inode = PVFS2_I(inode);
	size_t count = iov_iter_count(iter);
	size_t bufmap_size;
	struct iovec vec;
	struct iov_iter iter;
	ssize_t ret = -EINVAL;

	g_pvfs2_stats.reads++;

	vec.iov_base = buf;
	vec.iov_len = count;

	bufmap_size = pvfs_bufmap_size_query();
	if (count > bufmap_size) {
		gossip_debug(GOSSIP_FILE_DEBUG,
@@ -400,8 +395,7 @@ ssize_t pvfs2_inode_read(struct inode *inode,
		     count,
		     llu(*offset));

	iov_iter_init(&iter, READ, &vec, 1, count);
	ret = wait_for_direct_io(PVFS_IO_READ, inode, offset, &iter,
	ret = wait_for_direct_io(PVFS_IO_READ, inode, offset, iter,
			count, readahead_size);
	if (ret > 0)
		*offset += ret;
+7 −10
Original line number Diff line number Diff line
@@ -14,18 +14,20 @@

static int read_one_page(struct page *page)
{
	void *page_data;
	int ret;
	int max_block;
	ssize_t bytes_read = 0;
	struct inode *inode = page->mapping->host;
	const __u32 blocksize = PAGE_CACHE_SIZE;	/* inode->i_blksize */
	const __u32 blockbits = PAGE_CACHE_SHIFT;	/* inode->i_blkbits */
	struct iov_iter to;
	struct bio_vec bv = {.bv_page = page, .bv_len = PAGE_SIZE};

	iov_iter_bvec(&to, ITER_BVEC | READ, &bv, 1, PAGE_SIZE);

	gossip_debug(GOSSIP_INODE_DEBUG,
		    "pvfs2_readpage called with page %p\n",
		     page);
	page_data = pvfs2_kmap(page);

	max_block = ((inode->i_size / blocksize) + 1);

@@ -33,16 +35,12 @@ static int read_one_page(struct page *page)
		loff_t blockptr_offset = (((loff_t) page->index) << blockbits);

		bytes_read = pvfs2_inode_read(inode,
					      (char __user *) page_data,
					      blocksize,
					      &to,
					      &blockptr_offset,
					      inode->i_size);
	}
	/* only zero remaining unread portions of the page data */
	if (bytes_read > 0)
		memset(page_data + bytes_read, 0, blocksize - bytes_read);
	else
		memset(page_data, 0, blocksize);
	/* this will only zero remaining unread portions of the page data */
	iov_iter_zero(~0U, &to);
	/* takes care of potential aliasing */
	flush_dcache_page(page);
	if (bytes_read < 0) {
@@ -54,7 +52,6 @@ static int read_one_page(struct page *page)
			ClearPageError(page);
		ret = 0;
	}
	pvfs2_kunmap(page);
	/* unlock the page after the ->readpage() routine completes */
	unlock_page(page);
	return ret;
+1 −2
Original line number Diff line number Diff line
@@ -605,8 +605,7 @@ struct inode *pvfs2_iget(struct super_block *sb,
			 struct pvfs2_object_kref *ref);

ssize_t pvfs2_inode_read(struct inode *inode,
			 char __user *buf,
			 size_t count,
			 struct iov_iter *iter,
			 loff_t *offset,
			 loff_t readahead_size);