[CRIU] [PATCH 3/9] page-xfer: Write holes and non-holes in sorted way

Pavel Emelyanov xemul at parallels.com
Thu Apr 11 09:50:11 EDT 2013


The pagemap.img contains sorted iovs. Need to keep this array also
sorted even if holes are in there for simpler read on restore.

Separate ->write_hole callback since dump of hole and non-hole
will differ significantly.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 include/page-xfer.h |  1 +
 page-xfer.c         | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/include/page-xfer.h b/include/page-xfer.h
index 16a13d4..73ee119 100644
--- a/include/page-xfer.h
+++ b/include/page-xfer.h
@@ -4,6 +4,7 @@ int cr_page_server(void);
 
 struct page_xfer {
 	int (*write_pagemap)(struct page_xfer *self, struct iovec *iov, int pipe);
+	int (*write_hole)(struct page_xfer *self, struct iovec *iov);
 	void (*close)(struct page_xfer *self);
 	int fd;
 	union {
diff --git a/page-xfer.c b/page-xfer.c
index b60f1ce..0f3c26a 100644
--- a/page-xfer.c
+++ b/page-xfer.c
@@ -240,6 +240,12 @@ static int write_pagemap_to_server(struct page_xfer *xfer,
 	return 0;
 }
 
+static int write_hole_to_server(struct page_xfer *xfer, struct iovec *iov)
+{
+	pr_err("Writing holes to server not implemented.\n");
+	return -1;
+}
+
 static void close_server_xfer(struct page_xfer *xfer)
 {
 	xfer->fd = -1;
@@ -249,6 +255,7 @@ int open_page_server_xfer(struct page_xfer *xfer, int fd_type, long id)
 {
 	xfer->fd = page_server_sk;
 	xfer->write_pagemap = write_pagemap_to_server;
+	xfer->write_hole = write_hole_to_server;
 	xfer->close = close_server_xfer;
 	xfer->dst_id = encode_pm_id(fd_type, id);
 
@@ -273,6 +280,19 @@ static int write_pagemap_loc(struct page_xfer *xfer,
 	return 0;
 }
 
+static int write_pagehole_loc(struct page_xfer *xfer, struct iovec *iov)
+{
+	PagemapEntry pe = PAGEMAP_ENTRY__INIT;
+
+	pe.vaddr = encode_pointer(iov->iov_base);
+	pe.nr_pages = iov->iov_len / PAGE_SIZE;
+
+	if (pb_write_one(xfer->fd, &pe, PB_PAGEMAP) < 0)
+		return -1;
+
+	return 0;
+}
+
 static void close_page_xfer(struct page_xfer *xfer)
 {
 	close(xfer->fd_pg);
@@ -283,6 +303,10 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
 		unsigned long off)
 {
 	struct page_pipe_buf *ppb;
+	struct iovec *hole = NULL;
+
+	if (pp->free_hole)
+		hole = &pp->holes[0];
 
 	list_for_each_entry(ppb, &pp->bufs, l) {
 		int i;
@@ -292,6 +316,17 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
 		for (i = 0; i < ppb->nr_segs; i++) {
 			struct iovec *iov = &ppb->iov[i];
 
+			while (hole && (hole->iov_base < iov->iov_base)) {
+				pr_debug("\th %p [%u]\n", hole->iov_base,
+						(unsigned int)(hole->iov_len / PAGE_SIZE));
+				if (xfer->write_hole(xfer, hole))
+					return -1;
+
+				hole++;
+				if (hole >= &pp->holes[pp->free_hole])
+					hole = NULL;
+			}
+
 			BUG_ON(iov->iov_base < (void *)off);
 			iov->iov_base -= off;
 			pr_debug("\t%p [%u]\n", iov->iov_base,
@@ -302,6 +337,17 @@ int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp,
 		}
 	}
 
+	while (hole) {
+		pr_debug("\th* %p [%u]\n", hole->iov_base,
+				(unsigned int)(hole->iov_len / PAGE_SIZE));
+		if (xfer->write_hole(xfer, hole))
+			return -1;
+
+		hole++;
+		if (hole >= &pp->holes[pp->free_hole])
+			hole = NULL;
+	}
+
 	return 0;
 }
 
@@ -321,6 +367,7 @@ int open_page_xfer(struct page_xfer *xfer, int fd_type, long id)
 	}
 
 	xfer->write_pagemap = write_pagemap_loc;
+	xfer->write_hole = write_pagehole_loc;
 	xfer->close = close_page_xfer;
 	return 0;
 }
-- 
1.7.11.7


More information about the CRIU mailing list