diff mbox series

[34/44] fold __pipe_get_pages() into pipe_get_pages()

Message ID 20220622041552.737754-34-viro@zeniv.linux.org.uk (mailing list archive)
State New, archived
Headers show
Series [01/44] 9p: handling Rerror without copy_from_iter_full() | expand

Commit Message

Al Viro June 22, 2022, 4:15 a.m. UTC
... and don't mangle maxsize there - turn the loop into counting
one instead.  Easier to see that we won't run out of array that
way.  Note that special treatment of the partial buffer in that
thing is an artifact of the non-advancing semantics of
iov_iter_get_pages() - if not for that, it would be append_pipe(),
same as the body of the loop that follows it.  IOW, once we make
iov_iter_get_pages() advancing, the whole thing will turn into
	calculate how many pages do we want
	allocate an array (if needed)
	call append_pipe() that many times.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 lib/iov_iter.c | 75 +++++++++++++++++++++++++-------------------------
 1 file changed, 38 insertions(+), 37 deletions(-)

Comments

Jeff Layton June 28, 2022, 12:11 p.m. UTC | #1
On Wed, 2022-06-22 at 05:15 +0100, Al Viro wrote:
> ... and don't mangle maxsize there - turn the loop into counting
> one instead.  Easier to see that we won't run out of array that
> way.  Note that special treatment of the partial buffer in that
> thing is an artifact of the non-advancing semantics of
> iov_iter_get_pages() - if not for that, it would be append_pipe(),
> same as the body of the loop that follows it.  IOW, once we make
> iov_iter_get_pages() advancing, the whole thing will turn into
> 	calculate how many pages do we want
> 	allocate an array (if needed)
> 	call append_pipe() that many times.
> 
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
>  lib/iov_iter.c | 75 +++++++++++++++++++++++++-------------------------
>  1 file changed, 38 insertions(+), 37 deletions(-)
> 
> diff --git a/lib/iov_iter.c b/lib/iov_iter.c
> index f455b8ee0d76..9280f865fd6a 100644
> --- a/lib/iov_iter.c
> +++ b/lib/iov_iter.c
> @@ -1192,60 +1192,61 @@ static struct page **get_pages_array(size_t n)
>  	return kvmalloc_array(n, sizeof(struct page *), GFP_KERNEL);
>  }
>  
> -static inline ssize_t __pipe_get_pages(struct iov_iter *i,
> -				size_t maxsize,
> -				struct page **pages,
> -				size_t off)
> -{
> -	struct pipe_inode_info *pipe = i->pipe;
> -	ssize_t left = maxsize;
> -
> -	if (off) {
> -		struct pipe_buffer *buf = pipe_buf(pipe, pipe->head - 1);
> -
> -		get_page(*pages++ = buf->page);
> -		left -= PAGE_SIZE - off;
> -		if (left <= 0) {
> -			buf->len += maxsize;
> -			return maxsize;
> -		}
> -		buf->len = PAGE_SIZE;
> -	}
> -	while (!pipe_full(pipe->head, pipe->tail, pipe->max_usage)) {
> -		struct page *page = push_anon(pipe,
> -					      min_t(ssize_t, left, PAGE_SIZE));
> -		if (!page)
> -			break;
> -		get_page(*pages++ = page);
> -		left -= PAGE_SIZE;
> -		if (left <= 0)
> -			return maxsize;
> -	}
> -	return maxsize - left ? : -EFAULT;
> -}
> -
>  static ssize_t pipe_get_pages(struct iov_iter *i,
>  		   struct page ***pages, size_t maxsize, unsigned maxpages,
>  		   size_t *start)
>  {
> +	struct pipe_inode_info *pipe = i->pipe;
>  	unsigned int npages, off;
>  	struct page **p;
> -	size_t capacity;
> +	ssize_t left;
> +	int count;
>  
>  	if (!sanity(i))
>  		return -EFAULT;
>  
>  	*start = off = pipe_npages(i, &npages);
> -	capacity = min(npages, maxpages) * PAGE_SIZE - off;
> -	maxsize = min(maxsize, capacity);
> +	count = DIV_ROUND_UP(maxsize + off, PAGE_SIZE);
> +	if (count > npages)
> +		count = npages;
> +	if (count > maxpages)
> +		count = maxpages;
>  	p = *pages;
>  	if (!p) {
> -		*pages = p = get_pages_array(DIV_ROUND_UP(maxsize + off, PAGE_SIZE));
> +		*pages = p = get_pages_array(count);
>  		if (!p)
>  			return -ENOMEM;
>  	}
>  
> -	return __pipe_get_pages(i, maxsize, p, off);
> +	left = maxsize;
> +	npages = 0;
> +	if (off) {
> +		struct pipe_buffer *buf = pipe_buf(pipe, pipe->head - 1);
> +
> +		get_page(*p++ = buf->page);
> +		left -= PAGE_SIZE - off;
> +		if (left <= 0) {
> +			buf->len += maxsize;
> +			return maxsize;
> +		}
> +		buf->len = PAGE_SIZE;
> +		npages = 1;
> +	}
> +	for ( ; npages < count; npages++) {
> +		struct page *page;
> +		unsigned int size = min_t(ssize_t, left, PAGE_SIZE);
> +
> +		if (pipe_full(pipe->head, pipe->tail, pipe->max_usage))
> +			break;
> +		page = push_anon(pipe, size);
> +		if (!page)
> +			break;
> +		get_page(*p++ = page);
> +		left -= size;
> +	}
> +	if (!npages)
> +		return -EFAULT;
> +	return maxsize - left;
>  }
>  
>  static ssize_t iter_xarray_populate_pages(struct page **pages, struct xarray *xa,

Reviewed-by: Jeff Layton <jlayton@kernel.org>
diff mbox series

Patch

diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index f455b8ee0d76..9280f865fd6a 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -1192,60 +1192,61 @@  static struct page **get_pages_array(size_t n)
 	return kvmalloc_array(n, sizeof(struct page *), GFP_KERNEL);
 }
 
-static inline ssize_t __pipe_get_pages(struct iov_iter *i,
-				size_t maxsize,
-				struct page **pages,
-				size_t off)
-{
-	struct pipe_inode_info *pipe = i->pipe;
-	ssize_t left = maxsize;
-
-	if (off) {
-		struct pipe_buffer *buf = pipe_buf(pipe, pipe->head - 1);
-
-		get_page(*pages++ = buf->page);
-		left -= PAGE_SIZE - off;
-		if (left <= 0) {
-			buf->len += maxsize;
-			return maxsize;
-		}
-		buf->len = PAGE_SIZE;
-	}
-	while (!pipe_full(pipe->head, pipe->tail, pipe->max_usage)) {
-		struct page *page = push_anon(pipe,
-					      min_t(ssize_t, left, PAGE_SIZE));
-		if (!page)
-			break;
-		get_page(*pages++ = page);
-		left -= PAGE_SIZE;
-		if (left <= 0)
-			return maxsize;
-	}
-	return maxsize - left ? : -EFAULT;
-}
-
 static ssize_t pipe_get_pages(struct iov_iter *i,
 		   struct page ***pages, size_t maxsize, unsigned maxpages,
 		   size_t *start)
 {
+	struct pipe_inode_info *pipe = i->pipe;
 	unsigned int npages, off;
 	struct page **p;
-	size_t capacity;
+	ssize_t left;
+	int count;
 
 	if (!sanity(i))
 		return -EFAULT;
 
 	*start = off = pipe_npages(i, &npages);
-	capacity = min(npages, maxpages) * PAGE_SIZE - off;
-	maxsize = min(maxsize, capacity);
+	count = DIV_ROUND_UP(maxsize + off, PAGE_SIZE);
+	if (count > npages)
+		count = npages;
+	if (count > maxpages)
+		count = maxpages;
 	p = *pages;
 	if (!p) {
-		*pages = p = get_pages_array(DIV_ROUND_UP(maxsize + off, PAGE_SIZE));
+		*pages = p = get_pages_array(count);
 		if (!p)
 			return -ENOMEM;
 	}
 
-	return __pipe_get_pages(i, maxsize, p, off);
+	left = maxsize;
+	npages = 0;
+	if (off) {
+		struct pipe_buffer *buf = pipe_buf(pipe, pipe->head - 1);
+
+		get_page(*p++ = buf->page);
+		left -= PAGE_SIZE - off;
+		if (left <= 0) {
+			buf->len += maxsize;
+			return maxsize;
+		}
+		buf->len = PAGE_SIZE;
+		npages = 1;
+	}
+	for ( ; npages < count; npages++) {
+		struct page *page;
+		unsigned int size = min_t(ssize_t, left, PAGE_SIZE);
+
+		if (pipe_full(pipe->head, pipe->tail, pipe->max_usage))
+			break;
+		page = push_anon(pipe, size);
+		if (!page)
+			break;
+		get_page(*p++ = page);
+		left -= size;
+	}
+	if (!npages)
+		return -EFAULT;
+	return maxsize - left;
 }
 
 static ssize_t iter_xarray_populate_pages(struct page **pages, struct xarray *xa,