[CRIU] [PATCH v3 1/2] page-pipe: correctly split page-pipe-buffers
Adrian Reber
adrian at lisas.de
Tue Sep 20 09:54:10 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