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

Commit 2b777c9d authored by Al Viro's avatar Al Viro
Browse files

ceph_sync_read: stop poking into iov_iter guts



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent f0d1bec9
Loading
Loading
Loading
Loading
+18 −28
Original line number Original line Diff line number Diff line
@@ -418,7 +418,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
	struct page **pages;
	struct page **pages;
	u64 off = iocb->ki_pos;
	u64 off = iocb->ki_pos;
	int num_pages, ret;
	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,
	dout("sync_read on file %p %llu~%u %s\n", file, off,
	     (unsigned)len,
	     (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) {
	if (file->f_flags & O_DIRECT) {
		while (iov_iter_count(i)) {
		while (iov_iter_count(i)) {
			void __user *data = i->iov[0].iov_base + i->iov_offset;
			size_t start;
			size_t len = i->iov[0].iov_len - i->iov_offset;
			ssize_t n;


			num_pages = calc_pages_for((unsigned long)data, len);
			n = iov_iter_get_pages_alloc(i, &pages, INT_MAX, &start);
			pages = ceph_get_direct_page_vector(data,
			if (n < 0)
							    num_pages, true);
				return n;
			if (IS_ERR(pages))

				return PTR_ERR(pages);
			num_pages = (n + start + PAGE_SIZE - 1) / PAGE_SIZE;


			ret = striped_read(inode, off, len,
			ret = striped_read(inode, off, n,
					   pages, num_pages, checkeof,
					   pages, num_pages, checkeof,
					   1, (unsigned long)data & ~PAGE_MASK);
					   1, start);

			ceph_put_page_vector(pages, num_pages, true);
			ceph_put_page_vector(pages, num_pages, true);


			if (ret <= 0)
			if (ret <= 0)
				break;
				break;
			off += ret;
			off += ret;
			iov_iter_advance(i, ret);
			iov_iter_advance(i, ret);
			if (ret < len)
			if (ret < n)
				break;
				break;
		}
		}
	} else {
	} else {
@@ -466,25 +467,14 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
					num_pages, checkeof, 0, 0);
					num_pages, checkeof, 0, 0);
		if (ret > 0) {
		if (ret > 0) {
			int l, k = 0;
			int l, k = 0;
			size_t left = len = ret;
			size_t left = ret;


			while (left) {
			while (left) {
				void __user *data = i->iov[0].iov_base
				int copy = min_t(size_t, PAGE_SIZE, left);
							+ i->iov_offset;
				l = copy_page_to_iter(pages[k++], 0, copy, i);
				l = min(i->iov[0].iov_len - i->iov_offset,
				off += l;
					left);
				left -= l;

				if (l < copy)
				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
					break;
					break;
			}
			}
		}
		}
+0 −2
Original line number Original line Diff line number Diff line
@@ -222,8 +222,6 @@ extern void ceph_copy_to_page_vector(struct page **pages,
extern void ceph_copy_from_page_vector(struct page **pages,
extern void ceph_copy_from_page_vector(struct page **pages,
				    void *data,
				    void *data,
				    loff_t off, size_t len);
				    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);
extern void ceph_zero_page_vector_range(int off, int len, struct page **pages);




+4 −31
Original line number Original line Diff line number Diff line
@@ -53,6 +53,9 @@ void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty)
			set_page_dirty_lock(pages[i]);
			set_page_dirty_lock(pages[i]);
		put_page(pages[i]);
		put_page(pages[i]);
	}
	}
	if (is_vmalloc_addr(pages))
		vfree(pages);
	else
		kfree(pages);
		kfree(pages);
}
}
EXPORT_SYMBOL(ceph_put_page_vector);
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);
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
 * Zero an extent within a page vector.  Offset is relative to the
 * start of the first page.
 * start of the first page.