forked from mirrors/linux
		
	ceph_sync_read: stop poking into iov_iter guts
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									f0d1bec9d5
								
							
						
					
					
						commit
						2b777c9dd9
					
				
					 3 changed files with 22 additions and 61 deletions
				
			
		| 
						 | 
				
			
			@ -418,7 +418,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
 | 
			
		|||
	struct page **pages;
 | 
			
		||||
	u64 off = iocb->ki_pos;
 | 
			
		||||
	int num_pages, ret;
 | 
			
		||||
	size_t len = i->count;
 | 
			
		||||
	size_t len = iov_iter_count(i);
 | 
			
		||||
 | 
			
		||||
	dout("sync_read on file %p %llu~%u %s\n", file, off,
 | 
			
		||||
	     (unsigned)len,
 | 
			
		||||
| 
						 | 
				
			
			@ -436,25 +436,26 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
 | 
			
		|||
 | 
			
		||||
	if (file->f_flags & O_DIRECT) {
 | 
			
		||||
		while (iov_iter_count(i)) {
 | 
			
		||||
			void __user *data = i->iov[0].iov_base + i->iov_offset;
 | 
			
		||||
			size_t len = i->iov[0].iov_len - i->iov_offset;
 | 
			
		||||
			size_t start;
 | 
			
		||||
			ssize_t n;
 | 
			
		||||
 | 
			
		||||
			num_pages = calc_pages_for((unsigned long)data, len);
 | 
			
		||||
			pages = ceph_get_direct_page_vector(data,
 | 
			
		||||
							    num_pages, true);
 | 
			
		||||
			if (IS_ERR(pages))
 | 
			
		||||
				return PTR_ERR(pages);
 | 
			
		||||
			n = iov_iter_get_pages_alloc(i, &pages, INT_MAX, &start);
 | 
			
		||||
			if (n < 0)
 | 
			
		||||
				return n;
 | 
			
		||||
 | 
			
		||||
			ret = striped_read(inode, off, len,
 | 
			
		||||
			num_pages = (n + start + PAGE_SIZE - 1) / PAGE_SIZE;
 | 
			
		||||
 | 
			
		||||
			ret = striped_read(inode, off, n,
 | 
			
		||||
					   pages, num_pages, checkeof,
 | 
			
		||||
					   1, (unsigned long)data & ~PAGE_MASK);
 | 
			
		||||
					   1, start);
 | 
			
		||||
 | 
			
		||||
			ceph_put_page_vector(pages, num_pages, true);
 | 
			
		||||
 | 
			
		||||
			if (ret <= 0)
 | 
			
		||||
				break;
 | 
			
		||||
			off += ret;
 | 
			
		||||
			iov_iter_advance(i, ret);
 | 
			
		||||
			if (ret < len)
 | 
			
		||||
			if (ret < n)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -466,25 +467,14 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
 | 
			
		|||
					num_pages, checkeof, 0, 0);
 | 
			
		||||
		if (ret > 0) {
 | 
			
		||||
			int l, k = 0;
 | 
			
		||||
			size_t left = len = ret;
 | 
			
		||||
			size_t left = ret;
 | 
			
		||||
 | 
			
		||||
			while (left) {
 | 
			
		||||
				void __user *data = i->iov[0].iov_base
 | 
			
		||||
							+ i->iov_offset;
 | 
			
		||||
				l = min(i->iov[0].iov_len - i->iov_offset,
 | 
			
		||||
					left);
 | 
			
		||||
 | 
			
		||||
				ret = ceph_copy_page_vector_to_user(&pages[k],
 | 
			
		||||
								    data, off,
 | 
			
		||||
								    l);
 | 
			
		||||
				if (ret > 0) {
 | 
			
		||||
					iov_iter_advance(i, ret);
 | 
			
		||||
					left -= ret;
 | 
			
		||||
					off += ret;
 | 
			
		||||
					k = calc_pages_for(iocb->ki_pos,
 | 
			
		||||
							   len - left + 1) - 1;
 | 
			
		||||
					BUG_ON(k >= num_pages && left);
 | 
			
		||||
				} else
 | 
			
		||||
				int copy = min_t(size_t, PAGE_SIZE, left);
 | 
			
		||||
				l = copy_page_to_iter(pages[k++], 0, copy, i);
 | 
			
		||||
				off += l;
 | 
			
		||||
				left -= l;
 | 
			
		||||
				if (l < copy)
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -222,8 +222,6 @@ extern void ceph_copy_to_page_vector(struct page **pages,
 | 
			
		|||
extern void ceph_copy_from_page_vector(struct page **pages,
 | 
			
		||||
				    void *data,
 | 
			
		||||
				    loff_t off, size_t len);
 | 
			
		||||
extern int ceph_copy_page_vector_to_user(struct page **pages, void __user *data,
 | 
			
		||||
				    loff_t off, size_t len);
 | 
			
		||||
extern void ceph_zero_page_vector_range(int off, int len, struct page **pages);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,7 +53,10 @@ void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty)
 | 
			
		|||
			set_page_dirty_lock(pages[i]);
 | 
			
		||||
		put_page(pages[i]);
 | 
			
		||||
	}
 | 
			
		||||
	kfree(pages);
 | 
			
		||||
	if (is_vmalloc_addr(pages))
 | 
			
		||||
		vfree(pages);
 | 
			
		||||
	else
 | 
			
		||||
		kfree(pages);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_put_page_vector);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -164,36 +167,6 @@ void ceph_copy_from_page_vector(struct page **pages,
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_copy_from_page_vector);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * copy user data from a page vector into a user pointer
 | 
			
		||||
 */
 | 
			
		||||
int ceph_copy_page_vector_to_user(struct page **pages,
 | 
			
		||||
					 void __user *data,
 | 
			
		||||
					 loff_t off, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	int po = off & ~PAGE_CACHE_MASK;
 | 
			
		||||
	int left = len;
 | 
			
		||||
	int l, bad;
 | 
			
		||||
 | 
			
		||||
	while (left > 0) {
 | 
			
		||||
		l = min_t(int, left, PAGE_CACHE_SIZE-po);
 | 
			
		||||
		bad = copy_to_user(data, page_address(pages[i]) + po, l);
 | 
			
		||||
		if (bad == l)
 | 
			
		||||
			return -EFAULT;
 | 
			
		||||
		data += l - bad;
 | 
			
		||||
		left -= l - bad;
 | 
			
		||||
		if (po) {
 | 
			
		||||
			po += l - bad;
 | 
			
		||||
			if (po == PAGE_CACHE_SIZE)
 | 
			
		||||
				po = 0;
 | 
			
		||||
		}
 | 
			
		||||
		i++;
 | 
			
		||||
	}
 | 
			
		||||
	return len;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(ceph_copy_page_vector_to_user);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Zero an extent within a page vector.  Offset is relative to the
 | 
			
		||||
 * start of the first page.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue