From 74f68fce2a395a188d454a488ea167affa4d7cf5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Oct 2015 18:31:05 -0400 Subject: [PATCH] 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: Al Viro Signed-off-by: Mike Marshall --- fs/orangefs/file.c | 12 +++--------- fs/orangefs/inode.c | 17 +++++++---------- fs/orangefs/pvfs2-kernel.h | 3 +-- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c index 8dae04dc9df4..78d296bb870e 100644 --- a/fs/orangefs/file.c +++ b/fs/orangefs/file.c @@ -369,22 +369,17 @@ out: * 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; diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c index 4f7c45a44c1f..70d1c1925ea3 100644 --- a/fs/orangefs/inode.c +++ b/fs/orangefs/inode.c @@ -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; diff --git a/fs/orangefs/pvfs2-kernel.h b/fs/orangefs/pvfs2-kernel.h index 29b4a48b3a25..916a35513419 100644 --- a/fs/orangefs/pvfs2-kernel.h +++ b/fs/orangefs/pvfs2-kernel.h @@ -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); -- 2.39.5