[CRIU] [RFC PATCH 03/16] criu: lazy-pages: introduce collect_lazy_iovecs

Mike Rapoport rppt at linux.vnet.ibm.com
Tue Sep 27 06:42:04 PDT 2016


Instead of tracking memory handled by userfaultfd on the page basis we can
use IOVs for continious chunks. Start conversion by introducing
collect_lazy_iovecs function.

Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/uffd.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/criu/uffd.c b/criu/uffd.c
index 81dc7ae..063ce4f 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -45,11 +45,17 @@
 
 static mutex_t *lazy_sock_mutex;
 
+struct lazy_iovec {
+	struct iovec iov;
+	struct list_head l;
+};
+
 struct lazy_pages_info {
 	int pid;
 	int uffd;
 
 	struct list_head pages;
+	struct list_head iovs;
 
 	struct page_read pr;
 
@@ -74,6 +80,7 @@ static struct lazy_pages_info *lpi_init(void)
 
 	memset(lpi, 0, sizeof(*lpi));
 	INIT_LIST_HEAD(&lpi->pages);
+	INIT_LIST_HEAD(&lpi->iovs);
 	INIT_HLIST_NODE(&lpi->hash);
 
 	return lpi;
@@ -81,8 +88,12 @@ static struct lazy_pages_info *lpi_init(void)
 
 static void lpi_fini(struct lazy_pages_info *lpi)
 {
+	struct lazy_iovec *p, *n;
+
 	if (!lpi)
 		return;
+	list_for_each_entry_safe(p, n, &lpi->iovs, l)
+		xfree(p);
 	if (lpi->uffd > 0)
 		close(lpi->uffd);
 	if (lpi->pr.close)
@@ -314,6 +325,42 @@ out:
 
 static int find_vmas(struct lazy_pages_info *lpi);
 
+static int collect_lazy_iovecs(struct lazy_pages_info *lpi)
+{
+	struct page_read *pr = &lpi->pr;
+	struct lazy_iovec *lazy_iov, *n;
+	int nr_pages = 0;
+
+	pr->reset(pr);
+
+	while (pr->advance(pr)) {
+		PagemapEntry *pe = pr->pe;
+
+		if (!pagemap_lazy(pe))
+			continue;
+
+		lazy_iov = xzalloc(sizeof(*lazy_iov));
+		if (!lazy_iov) {
+			pr_err("Out of memory\n");
+			goto free_iovs;
+		}
+
+		pagemap2iovec(pe, &lazy_iov->iov);
+		list_add_tail(&lazy_iov->l, &lpi->iovs);
+		nr_pages += pe->nr_pages;
+
+		pr_debug("adding IOV: %p:%lx (%d)\n", lazy_iov->iov.iov_base, lazy_iov->iov.iov_len, pe->nr_pages);
+	}
+
+	return nr_pages;
+
+free_iovs:
+	list_for_each_entry_safe(lazy_iov, n, &lpi->iovs, l)
+		xfree(lazy_iov);
+
+	return -1;
+}
+
 static struct lazy_pages_info *ud_open(int client)
 {
 	struct lazy_pages_info *lpi;
@@ -353,6 +400,12 @@ static struct lazy_pages_info *ud_open(int client)
 
 	hlist_add_head(&lpi->hash, &lpi_hash[lpi->uffd % LPI_HASH_SIZE]);
 
+	ret = collect_lazy_iovecs(lpi);
+	if (ret != lpi->total_pages) {
+		pr_err("collect_lazy_iovecs=%d\n", ret);
+		goto out;
+	}
+
 	return lpi;
 
 out:
-- 
1.9.1



More information about the CRIU mailing list