[CRIU] [PATCH 2/9] page-pipe: Support holes in page-pipe iov map

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


Holes are regions, that don't have pages in them (i.e. -- no
pages in pipes). These holes are in separate iovs array since
we should have straight arrays of iovs for non-holes, which is
in turd required to push it into vmsplice in _one_ chunk.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 include/page-pipe.h |  5 +++++
 page-pipe.c         | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/include/page-pipe.h b/include/page-pipe.h
index cdf3aec..fbba122 100644
--- a/include/page-pipe.h
+++ b/include/page-pipe.h
@@ -18,9 +18,14 @@ struct page_pipe {
 	unsigned int nr_iovs;
 	unsigned int free_iov;
 	struct iovec *iovs;
+
+	unsigned int nr_holes;
+	unsigned int free_hole;
+	struct iovec *holes;
 };
 
 struct page_pipe *create_page_pipe(unsigned int nr, struct iovec *);
 void destroy_page_pipe(struct page_pipe *p);
 int page_pipe_add_page(struct page_pipe *p, unsigned long addr);
+int page_pipe_add_hole(struct page_pipe *p, unsigned long addr);
 #endif
diff --git a/page-pipe.c b/page-pipe.c
index 5295839..ab2eae7 100644
--- a/page-pipe.c
+++ b/page-pipe.c
@@ -47,6 +47,10 @@ struct page_pipe *create_page_pipe(unsigned int nr_segs, struct iovec *iovs)
 		pp->iovs = iovs;
 		pp->free_iov = 0;
 
+		pp->nr_holes = 0;
+		pp->free_hole = 0;
+		pp->holes = NULL;
+
 		if (page_pipe_grow(pp))
 			return NULL;
 	}
@@ -137,3 +141,34 @@ int page_pipe_add_page(struct page_pipe *pp, unsigned long addr)
 	BUG_ON(ret > 0);
 	return ret;
 }
+
+#define PP_HOLES_BATCH	32
+
+int page_pipe_add_hole(struct page_pipe *pp, unsigned long addr)
+{
+	struct iovec *iov;
+
+	if (pp->free_hole >= pp->nr_holes) {
+		pp->holes = xrealloc(pp->holes,
+				(pp->nr_holes + PP_HOLES_BATCH) * sizeof(struct iovec));
+		if (!pp->holes)
+			return -1;
+
+		pp->nr_holes += PP_HOLES_BATCH;
+	}
+
+	if (pp->free_hole) {
+		iov = &pp->holes[pp->free_hole - 1];
+		if ((unsigned long)iov->iov_base + iov->iov_len == addr) {
+			iov->iov_len += PAGE_SIZE;
+			goto out;
+		}
+	}
+
+	iov = &pp->holes[pp->free_hole];
+	iov->iov_base = (void *)addr;
+	iov->iov_len = PAGE_SIZE;
+	pp->free_hole++;
+out:
+	return 0;
+}
-- 
1.7.11.7


More information about the CRIU mailing list