[CRIU] [PATCH v3 03/19] uffd: Introduce lazy_pages_fd as preparation for socket polling

Mike Rapoport rppt at linux.vnet.ibm.com
Tue Nov 15 08:57:12 PST 2016


From: Pavel Emelyanov <xemul at virtuozzo.com>

We will want to poll not only a bunch of uffd-s, but also the lazy
socket, so here's "an fd and a callback" object to be pushed into
epoll.

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
Acked-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/uffd.c | 49 +++++++++++++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/criu/uffd.c b/criu/uffd.c
index 750b39e..e9d30ff 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -53,9 +53,13 @@ struct lazy_iovec {
 	unsigned long len;
 };
 
+struct lazy_pages_fd {
+	int fd;
+	int (*event)(struct lazy_pages_fd *, void *dest);
+};
+
 struct lazy_pages_info {
 	int pid;
-	int uffd;
 
 	struct list_head iovs;
 
@@ -64,10 +68,13 @@ struct lazy_pages_info {
 	unsigned long total_pages;
 	unsigned long copied_pages;
 
+	struct lazy_pages_fd lpfd;
+
 	struct list_head l;
 };
 
 static LIST_HEAD(lpis);
+static int handle_user_fault(struct lazy_pages_fd *lpfd, void *dest);
 
 static struct lazy_pages_info *lpi_init(void)
 {
@@ -80,6 +87,7 @@ static struct lazy_pages_info *lpi_init(void)
 	memset(lpi, 0, sizeof(*lpi));
 	INIT_LIST_HEAD(&lpi->iovs);
 	INIT_LIST_HEAD(&lpi->l);
+	lpi->lpfd.event = handle_user_fault;
 
 	return lpi;
 }
@@ -92,8 +100,8 @@ static void lpi_fini(struct lazy_pages_info *lpi)
 		return;
 	list_for_each_entry_safe(p, n, &lpi->iovs, l)
 		xfree(p);
-	if (lpi->uffd > 0)
-		close(lpi->uffd);
+	if (lpi->lpfd.fd > 0)
+		close(lpi->lpfd.fd);
 	if (lpi->pr.close)
 		lpi->pr.close(&lpi->pr);
 	free(lpi);
@@ -457,15 +465,15 @@ static int ud_open(int client, struct lazy_pages_info **_lpi)
 		return 0;
 	}
 
-	lpi->uffd = recv_fd(client);
-	if (lpi->uffd < 0) {
+	lpi->lpfd.fd = recv_fd(client);
+	if (lpi->lpfd.fd < 0) {
 		pr_err("recv_fd error");
 		goto out;
 	}
-	pr_debug("lpi->uffd %d\n", lpi->uffd);
+	pr_debug("lpi->uffd %d\n", lpi->lpfd.fd);
 
-	pr_debug("uffd is 0x%d\n", lpi->uffd);
-	uffd_flags = fcntl(lpi->uffd, F_GETFD, NULL);
+	pr_debug("uffd is 0x%d\n", lpi->lpfd.fd);
+	uffd_flags = fcntl(lpi->lpfd.fd, F_GETFD, NULL);
 	pr_debug("uffd_flags are 0x%x\n", uffd_flags);
 
 	ret = open_page_read(lpi->pid, &lpi->pr, PR_TASK);
@@ -537,7 +545,7 @@ static int uffd_copy_page(struct lazy_pages_info *lpi, __u64 address,
 	uffdio_copy.copy = 0;
 
 	pr_debug("uffdio_copy.dst 0x%llx\n", uffdio_copy.dst);
-	rc = ioctl(lpi->uffd, UFFDIO_COPY, &uffdio_copy);
+	rc = ioctl(lpi->lpfd.fd, UFFDIO_COPY, &uffdio_copy);
 	pr_debug("ioctl UFFDIO_COPY rc 0x%x\n", rc);
 	pr_debug("uffdio_copy.copy 0x%llx\n", uffdio_copy.copy);
 	if (rc) {
@@ -568,7 +576,7 @@ static int uffd_zero_page(struct lazy_pages_info *lpi, __u64 address)
 	uffdio_zeropage.mode = 0;
 
 	pr_debug("uffdio_zeropage.range.start 0x%llx\n", uffdio_zeropage.range.start);
-	rc = ioctl(lpi->uffd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
+	rc = ioctl(lpi->lpfd.fd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
 	pr_debug("ioctl UFFDIO_ZEROPAGE rc 0x%x\n", rc);
 	pr_debug("uffdio_zeropage.zeropage 0x%llx\n", uffdio_zeropage.zeropage);
 	if (rc) {
@@ -634,14 +642,17 @@ static int handle_regular_pages(struct lazy_pages_info *lpi, void *dest,
 	return 0;
 }
 
-static int handle_user_fault(struct lazy_pages_info *lpi, void *dest)
+static int handle_user_fault(struct lazy_pages_fd *lpfd, void *dest)
 {
+	struct lazy_pages_info *lpi;
 	struct uffd_msg msg;
 	__u64 flags;
 	__u64 address;
 	int ret;
 
-	ret = read(lpi->uffd, &msg, sizeof(msg));
+	lpi = container_of(lpfd, struct lazy_pages_info, lpfd);
+
+	ret = read(lpfd->fd, &msg, sizeof(msg));
 	pr_debug("read() ret: 0x%x\n", ret);
 	if (!ret)
 		return 1;
@@ -709,6 +720,8 @@ static int handle_requests(int epollfd, struct epoll_event *events)
 		return ret;
 
 	while (1) {
+		struct lazy_pages_fd *lpfd;
+
 		/*
 		 * Setting the timeout to 5 seconds. If after this time
 		 * no uffd pages are requested the code switches to
@@ -728,8 +741,8 @@ static int handle_requests(int epollfd, struct epoll_event *events)
 		for (i = 0; i < ret; i++) {
 			int err;
 
-			lpi = (struct lazy_pages_info *)events[i].data.ptr;
-			err = handle_user_fault(lpi, dest);
+			lpfd = (struct lazy_pages_fd *)events[i].data.ptr;
+			err = lpfd->event(lpfd, dest);
 			if (err < 0)
 				goto out;
 		}
@@ -789,13 +802,13 @@ free_events:
 	return -1;
 }
 
-static int epoll_add_lpi(int epollfd, struct lazy_pages_info *lpi)
+static int epoll_add_lpfd(int epollfd, struct lazy_pages_fd *lpfd)
 {
 	struct epoll_event ev;
 
 	ev.events = EPOLLIN;
-	ev.data.ptr = lpi;
-	if (epoll_ctl(epollfd, EPOLL_CTL_ADD, lpi->uffd, &ev) == -1) {
+	ev.data.ptr = lpfd;
+	if (epoll_ctl(epollfd, EPOLL_CTL_ADD, lpfd->fd, &ev) == -1) {
 		pr_perror("epoll_ctl failed");
 		return -1;
 	}
@@ -842,7 +855,7 @@ static int prepare_uffds(int listen, int epollfd)
 			goto close_uffd;
 		if (lpi == NULL)
 			continue;
-		if (epoll_add_lpi(epollfd, lpi))
+		if (epoll_add_lpfd(epollfd, &lpi->lpfd))
 			goto close_uffd;
 	}
 
-- 
1.9.1



More information about the CRIU mailing list