[CRIU] [PATCH v2 1/2] page-pipe: correctly split page-pipe-buffers

Adrian Reber adrian at lisas.de
Thu Sep 15 01:34:39 PDT 2016


From: Adrian Reber <areber at redhat.com>

Combining pre-copy (pre-dump) and post-copy (lazy-pages) mode showed a
problem in the function page_pipe_split_ppb(). The function is used to
split the page-pipe-buffer so that it only contains the IOVs request
from the restore side during lazy restore.

Unfortunately it only splits the leading IOVs out of the
page-pipe-buffer and not the trailing:

Before split for requested address 0x7f27284d1000:

 page-pipe: ppb->iov 0x7f0f74d93040
 page-pipe: 		0x7f27282bb000 1
 page-pipe: 		0x7f27284d1000 1
 page-pipe: 		0x7f27284dd000 2

After split:

 page-pipe: ppb->iov 0x7f0f74d93050
 page-pipe: 		0x7f27284d1000 1
 page-pipe: 		0x7f27284dd000 2

and:

 page-pipe: ppb->iov 0x7f0f74d93040
 page-pipe: 		0x7f27282bb000 1

This patch keeps on splitting the page-pipe-buffer until it contains
only the requested address with the requested length.

After split (still trying to load 0x7f27284d1000):

 page-pipe: ppb->iov 0x7f0f74d93050
 page-pipe: 		0x7f27284d1000 1

and:

 page-pipe: ppb->iov 0x7f0f74d93040
 page-pipe: 		0x7f27282bb000 1

and:

 page-pipe: ppb->iov 0x7f0f74d93060
 page-pipe: 		0x7f27284dd000 2

v2:
 - moved declarations to the declaration block

Signed-off-by: Adrian Reber <areber at redhat.com>
---
 criu/page-pipe.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/criu/page-pipe.c b/criu/page-pipe.c
index df028dc..90597f8 100644
--- a/criu/page-pipe.c
+++ b/criu/page-pipe.c
@@ -393,6 +393,8 @@ static int page_pipe_split_iov(struct page_pipe *pp, struct page_pipe_buf *ppb,
 static int page_pipe_split_ppb(struct page_pipe *pp, struct page_pipe_buf *ppb,
 			       struct iovec *iov, unsigned long len)
 {
+	struct page_pipe_buf *ppb_tmp;
+	struct iovec *iov_tmp = iov;
 	struct page_pipe_buf *ppb_new;
 	int ret;
 
@@ -412,6 +414,34 @@ static int page_pipe_split_ppb(struct page_pipe *pp, struct page_pipe_buf *ppb,
 
 	list_move(&ppb->l, &pp->bufs);
 
+	/*
+	 * Only the leading iov's are split from the page_pipe_buffer.
+	 * The complete page_pipe_buffer at the start of the page_pipe
+	 * list will be deleted and therefore it is necessary to also
+	 * move unrelated iov's to their own page_pipe_buffers.
+	 */
+
+	if (ppb->nr_segs <= len / PAGE_SIZE)
+		return 0;
+
+	/* Move to the iov after the current request */
+	iov += len / PAGE_SIZE;
+	ret = page_pipe_split_ppb(pp, ppb, iov, len);
+	if (ret)
+		return -1;
+
+	/*
+	 * Rotate until correct head pointer. The function transmitting
+	 * the page data expects that the head points to the right
+	 * page_pipe_buffer. The complete first page_pipe_buffer is
+	 * deleted even it contains additional elements.
+	 */
+	ppb_tmp = list_first_entry(&pp->bufs, struct page_pipe_buf, l);
+	while (ppb_tmp->iov != iov_tmp) {
+		list_rotate_left(&pp->bufs);
+		ppb_tmp = list_first_entry(&pp->bufs, struct page_pipe_buf, l);
+	}
+
 	return 0;
 }
 
-- 
2.7.4



More information about the CRIU mailing list