[2/4] parasite: remove restriction to a number of iovec-s

Submitted by Andrei Vagin on Nov. 7, 2017, 12:02 a.m.

Details

Message ID 20171107000237.27668-3-avagin@openvz.org
State New
Series "Optimize a number of pipes to splice memory"
Headers show

Commit Message

Andrei Vagin Nov. 7, 2017, 12:02 a.m.
From: Andrei Vagin <avagin@virtuozzo.com>

vmsplice can't splice more than UIO_MAXIOV, but we can
call it a few times from a parasite.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
---
 criu/page-pipe.c    |  8 +-------
 criu/pie/parasite.c | 25 +++++++++++++++++++++----
 2 files changed, 22 insertions(+), 11 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/page-pipe.c b/criu/page-pipe.c
index 7da8bebc3..4eabb5ed5 100644
--- a/criu/page-pipe.c
+++ b/criu/page-pipe.c
@@ -207,15 +207,9 @@  static inline int try_add_page_to(struct page_pipe *pp, struct page_pipe_buf *pp
 			return 1; /* need to add another buf */
 	}
 
-	if (ppb->nr_segs) {
-		if (iov_grow_page(&ppb->iov[ppb->nr_segs - 1], addr))
+	if (ppb->nr_segs && iov_grow_page(&ppb->iov[ppb->nr_segs - 1], addr))
 			goto out;
 
-		if (ppb->nr_segs == UIO_MAXIOV)
-			/* XXX -- shrink pipe back? */
-			return 1;
-	}
-
 	pr_debug("Add iov to page pipe (%u iovs, %u/%u total)\n",
 			ppb->nr_segs, pp->free_iov, pp->nr_iovs);
 	iov_init(&ppb->iov[ppb->nr_segs++], addr);
diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c
index db2a75f59..6ab3f78f6 100644
--- a/criu/pie/parasite.c
+++ b/criu/pie/parasite.c
@@ -66,6 +66,7 @@  static int dump_pages(struct parasite_dump_pages_args *args)
 {
 	int p, ret, tsock;
 	struct iovec *iovs;
+	int off = 0, nr = args->nr_segs, nr_pages;
 
 	tsock = parasite_get_rpc_sock();
 	p = recv_fd(tsock);
@@ -73,11 +74,27 @@  static int dump_pages(struct parasite_dump_pages_args *args)
 		return -1;
 
 	iovs = pargs_iovs(args);
-	ret = sys_vmsplice(p, &iovs[args->off], args->nr_segs,
-				SPLICE_F_GIFT | SPLICE_F_NONBLOCK);
-	if (ret != PAGE_SIZE * args->nr_pages) {
+	nr_pages = 0;
+	if (nr > UIO_MAXIOV)
+		nr = UIO_MAXIOV;
+	while (1) {
+		ret = sys_vmsplice(p, &iovs[args->off + off], nr,
+					SPLICE_F_GIFT | SPLICE_F_NONBLOCK);
+		if (ret < 0) {
+			sys_close(p);
+			pr_err("Can't splice pages to pipe (%d/%d/%d)\n", ret, nr, off);
+			return -1;
+		}
+		nr_pages += ret;
+		off += nr;
+		if (off == args->nr_segs)
+			break;
+		if (off + nr > args->nr_segs)
+			nr = args->nr_segs - off;
+	}
+	if (nr_pages != args->nr_pages * PAGE_SIZE) {
 		sys_close(p);
-		pr_err("Can't splice pages to pipe (%d/%d)\n", ret, args->nr_pages);
+		pr_err("Can't splice pages to pipe (%d/%d)\n", nr_pages, args->nr_pages);
 		return -1;
 	}
 

Comments

Mike Rapoport Nov. 7, 2017, 1:08 p.m.
On Tue, Nov 07, 2017 at 03:02:35AM +0300, Andrei Vagin wrote:
> From: Andrei Vagin <avagin@virtuozzo.com>
> 
> vmsplice can't splice more than UIO_MAXIOV, but we can
> call it a few times from a parasite.
> 
> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
> ---
>  criu/page-pipe.c    |  8 +-------
>  criu/pie/parasite.c | 25 +++++++++++++++++++++----
>  2 files changed, 22 insertions(+), 11 deletions(-)
> 
> diff --git a/criu/page-pipe.c b/criu/page-pipe.c
> index 7da8bebc3..4eabb5ed5 100644
> --- a/criu/page-pipe.c
> +++ b/criu/page-pipe.c
> @@ -207,15 +207,9 @@ static inline int try_add_page_to(struct page_pipe *pp, struct page_pipe_buf *pp
>  			return 1; /* need to add another buf */
>  	}
> 
> -	if (ppb->nr_segs) {
> -		if (iov_grow_page(&ppb->iov[ppb->nr_segs - 1], addr))
> +	if (ppb->nr_segs && iov_grow_page(&ppb->iov[ppb->nr_segs - 1], addr))
>  			goto out;
> 
> -		if (ppb->nr_segs == UIO_MAXIOV)
> -			/* XXX -- shrink pipe back? */
> -			return 1;
> -	}
> -
>  	pr_debug("Add iov to page pipe (%u iovs, %u/%u total)\n",
>  			ppb->nr_segs, pp->free_iov, pp->nr_iovs);
>  	iov_init(&ppb->iov[ppb->nr_segs++], addr);
> diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c
> index db2a75f59..6ab3f78f6 100644
> --- a/criu/pie/parasite.c
> +++ b/criu/pie/parasite.c
> @@ -66,6 +66,7 @@ static int dump_pages(struct parasite_dump_pages_args *args)
>  {
>  	int p, ret, tsock;
>  	struct iovec *iovs;
> +	int off = 0, nr = args->nr_segs, nr_pages;

nr_segs = args->nr_segs?

C is a spartan language, but still...
> 
>  	tsock = parasite_get_rpc_sock();
>  	p = recv_fd(tsock);
> @@ -73,11 +74,27 @@ static int dump_pages(struct parasite_dump_pages_args *args)
>  		return -1;
> 
>  	iovs = pargs_iovs(args);
> -	ret = sys_vmsplice(p, &iovs[args->off], args->nr_segs,
> -				SPLICE_F_GIFT | SPLICE_F_NONBLOCK);
> -	if (ret != PAGE_SIZE * args->nr_pages) {
> +	nr_pages = 0;
> +	if (nr > UIO_MAXIOV)
> +		nr = UIO_MAXIOV;
> +	while (1) {
> +		ret = sys_vmsplice(p, &iovs[args->off + off], nr,
> +					SPLICE_F_GIFT | SPLICE_F_NONBLOCK);
> +		if (ret < 0) {
> +			sys_close(p);
> +			pr_err("Can't splice pages to pipe (%d/%d/%d)\n", ret, nr, off);
> +			return -1;
> +		}
> +		nr_pages += ret;
> +		off += nr;
> +		if (off == args->nr_segs)
> +			break;
> +		if (off + nr > args->nr_segs)
> +			nr = args->nr_segs - off;
> +	}
> +	if (nr_pages != args->nr_pages * PAGE_SIZE) {
>  		sys_close(p);
> -		pr_err("Can't splice pages to pipe (%d/%d)\n", ret, args->nr_pages);
> +		pr_err("Can't splice pages to pipe (%d/%d)\n", nr_pages, args->nr_pages);
>  		return -1;
>  	}
> 
> -- 
> 2.13.6
> 
> _______________________________________________
> CRIU mailing list
> CRIU@openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
>