forked from luck/tmp_suning_uos_patched
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 <viro@zeniv.linux.org.uk> Signed-off-by: Mike Marshall <hubcap@omnibond.com>
This commit is contained in:
parent
0071ed1ec6
commit
74f68fce2a
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user