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

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
...@@ -369,22 +369,17 @@ static ssize_t do_readv_writev(enum PVFS_io_type type, struct file *file, ...@@ -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. * Data may be placed either in a user or kernel buffer.
*/ */
ssize_t pvfs2_inode_read(struct inode *inode, ssize_t pvfs2_inode_read(struct inode *inode,
char __user *buf, struct iov_iter *iter,
size_t count,
loff_t *offset, loff_t *offset,
loff_t readahead_size) loff_t readahead_size)
{ {
struct pvfs2_inode_s *pvfs2_inode = PVFS2_I(inode); struct pvfs2_inode_s *pvfs2_inode = PVFS2_I(inode);
size_t count = iov_iter_count(iter);
size_t bufmap_size; size_t bufmap_size;
struct iovec vec;
struct iov_iter iter;
ssize_t ret = -EINVAL; ssize_t ret = -EINVAL;
g_pvfs2_stats.reads++; g_pvfs2_stats.reads++;
vec.iov_base = buf;
vec.iov_len = count;
bufmap_size = pvfs_bufmap_size_query(); bufmap_size = pvfs_bufmap_size_query();
if (count > bufmap_size) { if (count > bufmap_size) {
gossip_debug(GOSSIP_FILE_DEBUG, gossip_debug(GOSSIP_FILE_DEBUG,
...@@ -400,8 +395,7 @@ ssize_t pvfs2_inode_read(struct inode *inode, ...@@ -400,8 +395,7 @@ ssize_t pvfs2_inode_read(struct inode *inode,
count, count,
llu(*offset)); 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); count, readahead_size);
if (ret > 0) if (ret > 0)
*offset += ret; *offset += ret;
......
...@@ -14,18 +14,20 @@ ...@@ -14,18 +14,20 @@
static int read_one_page(struct page *page) static int read_one_page(struct page *page)
{ {
void *page_data;
int ret; int ret;
int max_block; int max_block;
ssize_t bytes_read = 0; ssize_t bytes_read = 0;
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
const __u32 blocksize = PAGE_CACHE_SIZE; /* inode->i_blksize */ const __u32 blocksize = PAGE_CACHE_SIZE; /* inode->i_blksize */
const __u32 blockbits = PAGE_CACHE_SHIFT; /* inode->i_blkbits */ 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, gossip_debug(GOSSIP_INODE_DEBUG,
"pvfs2_readpage called with page %p\n", "pvfs2_readpage called with page %p\n",
page); page);
page_data = pvfs2_kmap(page);
max_block = ((inode->i_size / blocksize) + 1); max_block = ((inode->i_size / blocksize) + 1);
...@@ -33,16 +35,12 @@ static int read_one_page(struct page *page) ...@@ -33,16 +35,12 @@ static int read_one_page(struct page *page)
loff_t blockptr_offset = (((loff_t) page->index) << blockbits); loff_t blockptr_offset = (((loff_t) page->index) << blockbits);
bytes_read = pvfs2_inode_read(inode, bytes_read = pvfs2_inode_read(inode,
(char __user *) page_data, &to,
blocksize,
&blockptr_offset, &blockptr_offset,
inode->i_size); inode->i_size);
} }
/* only zero remaining unread portions of the page data */ /* this will only zero remaining unread portions of the page data */
if (bytes_read > 0) iov_iter_zero(~0U, &to);
memset(page_data + bytes_read, 0, blocksize - bytes_read);
else
memset(page_data, 0, blocksize);
/* takes care of potential aliasing */ /* takes care of potential aliasing */
flush_dcache_page(page); flush_dcache_page(page);
if (bytes_read < 0) { if (bytes_read < 0) {
...@@ -54,7 +52,6 @@ static int read_one_page(struct page *page) ...@@ -54,7 +52,6 @@ static int read_one_page(struct page *page)
ClearPageError(page); ClearPageError(page);
ret = 0; ret = 0;
} }
pvfs2_kunmap(page);
/* unlock the page after the ->readpage() routine completes */ /* unlock the page after the ->readpage() routine completes */
unlock_page(page); unlock_page(page);
return ret; return ret;
......
...@@ -605,8 +605,7 @@ struct inode *pvfs2_iget(struct super_block *sb, ...@@ -605,8 +605,7 @@ struct inode *pvfs2_iget(struct super_block *sb,
struct pvfs2_object_kref *ref); struct pvfs2_object_kref *ref);
ssize_t pvfs2_inode_read(struct inode *inode, ssize_t pvfs2_inode_read(struct inode *inode,
char __user *buf, struct iov_iter *iter,
size_t count,
loff_t *offset, loff_t *offset,
loff_t readahead_size); loff_t readahead_size);
......
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