[CRIU] [PATCH 3/5] util: Move epoll aux code from uffd to util (v2)

Pavel Emelyanov xemul at virtuozzo.com
Tue Nov 22 04:10:54 PST 2016


v2: Move epoll_prepare() too

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/include/util.h | 15 +++++++++
 criu/uffd.c         | 97 +++++++++--------------------------------------------
 criu/util.c         | 64 +++++++++++++++++++++++++++++++++++
 3 files changed, 95 insertions(+), 81 deletions(-)

diff --git a/criu/include/util.h b/criu/include/util.h
index 8eaee33..f20490c 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -281,4 +281,19 @@ int setup_tcp_client(char *addr);
 #define LAST_PID_PATH		"sys/kernel/ns_last_pid"
 #define PID_MAX_PATH		"sys/kernel/pid_max"
 
+/*
+ * Helpers to organize asynchronous reading from a bunch
+ * of file descriptors.
+ */
+#include <sys/epoll.h>
+
+struct epoll_rfd {
+	int fd;
+	int (*revent)(struct epoll_rfd *);
+};
+
+extern int epoll_add_rfd(int epfd, struct epoll_rfd *);
+extern int epoll_run_rfds(int epfd, struct epoll_event *evs, int nr_fds, int tmo);
+extern int epoll_prepare(int nr_events, struct epoll_event **evs);
+
 #endif /* __CR_UTIL_H__ */
diff --git a/criu/uffd.c b/criu/uffd.c
index 5697708..301e3f4 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -14,7 +14,6 @@
 #include <sys/ioctl.h>
 #include <sys/un.h>
 #include <sys/socket.h>
-#include <sys/epoll.h>
 #include <sys/wait.h>
 
 #include "linux/userfaultfd.h"
@@ -39,6 +38,7 @@
 #include "page-xfer.h"
 #include "common/lock.h"
 #include "rst-malloc.h"
+#include "util.h"
 
 #undef  LOG_PREFIX
 #define LOG_PREFIX "lazy-pages: "
@@ -55,11 +55,6 @@ struct lazy_iovec {
 
 struct lazy_pages_info;
 
-struct lazy_pages_fd {
-	int fd;
-	int (*event)(struct lazy_pages_fd *);
-};
-
 struct lazy_pages_info {
 	int pid;
 
@@ -70,7 +65,7 @@ struct lazy_pages_info {
 	unsigned long total_pages;
 	unsigned long copied_pages;
 
-	struct lazy_pages_fd lpfd;
+	struct epoll_rfd lpfd;
 
 	struct list_head l;
 
@@ -79,7 +74,7 @@ struct lazy_pages_info {
 };
 
 static LIST_HEAD(lpis);
-static int handle_user_fault(struct lazy_pages_fd *lpfd);
+static int handle_user_fault(struct epoll_rfd *lpfd);
 
 static struct lazy_pages_info *lpi_init(void)
 {
@@ -92,7 +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;
+	lpi->lpfd.revent = handle_user_fault;
 
 	return lpi;
 }
@@ -673,7 +668,7 @@ static int handle_remaining_pages(struct lazy_pages_info *lpi)
 	return 0;
 }
 
-static int handle_user_fault(struct lazy_pages_fd *lpfd)
+static int handle_user_fault(struct epoll_rfd *lpfd)
 {
 	struct lazy_pages_info *lpi;
 	struct uffd_msg msg;
@@ -737,39 +732,14 @@ static int lazy_pages_summary(struct lazy_pages_info *lpi)
 
 static int handle_requests(int epollfd, struct epoll_event *events)
 {
-	int nr_fds = epoll_nr_fds(task_entries->nr_tasks);
 	struct lazy_pages_info *lpi;
-	int ret = -1;
-	int i;
-
-	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
-		 * copying the remaining pages.
-		 */
-		ret = epoll_wait(epollfd, events, nr_fds, POLL_TIMEOUT);
-		pr_debug("epoll() ret: 0x%x\n", ret);
-		if (ret < 0) {
-			pr_perror("polling failed");
-			goto out;
-		} else if (ret == 0) {
-			pr_debug("read timeout\n");
-			pr_debug("switching from request to copy mode\n");
-			break;
-		}
+	int ret;
 
-		for (i = 0; i < ret; i++) {
-			int err;
+	ret = epoll_run_rfds(epollfd, events, epoll_nr_fds(task_entries->nr_tasks), POLL_TIMEOUT);
+	if (ret < 0)
+		goto out;
 
-			lpfd = (struct lazy_pages_fd *)events[i].data.ptr;
-			err = lpfd->event(lpfd);
-			if (err < 0)
-				goto out;
-		}
-	}
+	pr_debug("switching from request to copy mode\n");
 	pr_debug("Handle remaining pages\n");
 	list_for_each_entry(lpi, &lpis, l) {
 		ret = handle_remaining_pages(lpi);
@@ -788,41 +758,6 @@ out:
 
 }
 
-static int prepare_epoll(int nr_fds, struct epoll_event **events)
-{
-	int epollfd;
-
-	*events = xmalloc(sizeof(struct epoll_event) * nr_fds);
-	if (!*events)
-		return -1;
-
-	epollfd = epoll_create(nr_fds);
-	if (epollfd == -1) {
-		pr_perror("epoll_create failed");
-		goto free_events;
-	}
-
-	return epollfd;
-
-free_events:
-	free(*events);
-	return -1;
-}
-
-static int epoll_add_lpfd(int epollfd, struct lazy_pages_fd *lpfd)
-{
-	struct epoll_event ev;
-
-	ev.events = EPOLLIN;
-	ev.data.ptr = lpfd;
-	if (epoll_ctl(epollfd, EPOLL_CTL_ADD, lpfd->fd, &ev) == -1) {
-		pr_perror("epoll_ctl failed");
-		return -1;
-	}
-
-	return 0;
-}
-
 static int prepare_lazy_socket(void)
 {
 	int listen;
@@ -862,7 +797,7 @@ static int prepare_uffds(int listen, int epollfd)
 			goto close_uffd;
 		if (lpi == NULL)
 			continue;
-		if (epoll_add_lpfd(epollfd, &lpi->lpfd))
+		if (epoll_add_rfd(epollfd, &lpi->lpfd))
 			goto close_uffd;
 	}
 
@@ -876,12 +811,12 @@ close_uffd:
 	return -1;
 }
 
-static int page_server_event(struct lazy_pages_fd *lpfd)
+static int page_server_event(struct epoll_rfd *lpfd)
 {
 	return page_server_async_read();
 }
 
-static struct lazy_pages_fd page_server_sk_fd;
+static struct epoll_rfd page_server_sk_fd;
 
 static int prepare_page_server_socket(int epollfd)
 {
@@ -891,10 +826,10 @@ static int prepare_page_server_socket(int epollfd)
 	if (sk < 0)
 		return -1;
 
-	page_server_sk_fd.event = page_server_event;
+	page_server_sk_fd.revent = page_server_event;
 	page_server_sk_fd.fd = sk;
 
-	return epoll_add_lpfd(epollfd, &page_server_sk_fd);
+	return epoll_add_rfd(epollfd, &page_server_sk_fd);
 }
 
 int cr_lazy_pages(bool daemon)
@@ -936,7 +871,7 @@ int cr_lazy_pages(bool daemon)
 	}
 
 	nr_fds = epoll_nr_fds(task_entries->nr_tasks);
-	epollfd = prepare_epoll(nr_fds, &events);
+	epollfd = epoll_prepare(nr_fds, &events);
 	if (epollfd < 0)
 		return -1;
 
diff --git a/criu/util.c b/criu/util.c
index 2cf0355..622e948 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -1185,3 +1185,67 @@ int setup_tcp_client(char *addr)
 
 	return sk;
 }
+
+int epoll_add_rfd(int epfd, struct epoll_rfd *rfd)
+{
+	struct epoll_event ev;
+
+	ev.events = EPOLLIN;
+	ev.data.ptr = rfd;
+	if (epoll_ctl(epfd, EPOLL_CTL_ADD, rfd->fd, &ev) == -1) {
+		pr_perror("epoll_ctl failed");
+		return -1;
+	}
+
+	return 0;
+}
+
+int epoll_run_rfds(int epollfd, struct epoll_event *evs, int nr_fds, int timeout)
+{
+	int ret = 0, i;
+
+	while (1) {
+		/* FIXME -- timeout should decrease over time...  */
+		ret = epoll_wait(epollfd, evs, nr_fds, timeout);
+		pr_debug("epoll() ret: 0x%x\n", ret);
+		if (ret <= 0) {
+			if (ret < 0)
+				pr_perror("polling failed");
+			else
+				pr_debug("polling timeout\n");
+			break;
+		}
+
+		for (i = 0; i < ret; i++) {
+			struct epoll_rfd *rfd;
+
+			rfd = (struct epoll_rfd *)evs[i].data.ptr;
+			ret = rfd->revent(rfd);
+			if (ret < 0)
+				goto out;
+		}
+	}
+out:
+	return ret;
+}
+
+int epoll_prepare(int nr_fds, struct epoll_event **events)
+{
+	int epollfd;
+
+	*events = xmalloc(sizeof(struct epoll_event) * nr_fds);
+	if (!*events)
+		return -1;
+
+	epollfd = epoll_create(nr_fds);
+	if (epollfd == -1) {
+		pr_perror("epoll_create failed");
+		goto free_events;
+	}
+
+	return epollfd;
+
+free_events:
+	xfree(*events);
+	return -1;
+}
-- 
2.5.0



More information about the CRIU mailing list