[CRIU] [PATCH v2 5/7] lazy-pages: use epoll instead of select
Mike Rapoport
rppt at linux.vnet.ibm.com
Mon Apr 18 06:34:36 PDT 2016
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
criu/uffd.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 61 insertions(+), 19 deletions(-)
diff --git a/criu/uffd.c b/criu/uffd.c
index f411a3a..a9caf1a 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -14,6 +14,7 @@
#include <sys/ioctl.h>
#include <sys/un.h>
#include <sys/socket.h>
+#include <sys/epoll.h>
#include "asm/page.h"
#include "include/log.h"
@@ -577,18 +578,16 @@ static int lazy_pages_summary(struct lazy_pages_info *lpi)
return 0;
}
-static int handle_requests(struct lazy_pages_info *lpi)
+#define POLL_TIMEOUT 5000
+
+static int handle_requests(struct lazy_pages_info *lpi, int epollfd,
+ struct epoll_event *events)
{
- fd_set set;
+ int nr_fds = task_entries->nr_tasks;
int ret = -1;
unsigned long ps;
- struct timeval timeout;
void *dest;
- /* Initialize FD sets for read() with timeouts (using select()) */
- FD_ZERO(&set);
- FD_SET(lpi->uffd, &set);
-
/* All operations will be done on page size */
ps = page_size();
dest = malloc(ps);
@@ -598,16 +597,13 @@ static int handle_requests(struct lazy_pages_info *lpi)
* Setting the timeout to 5 seconds. If after this time
* no uffd pages are requested the code switches to
* copying the remaining pages.
- *
- * Timeout is re-defined every time select() is run as
- * select(2) says:
- * Consider timeout to be undefined after select() returns.
*/
- timeout.tv_sec = 5;
- timeout.tv_usec = 0;
- ret = select(lpi->uffd + 1, &set, NULL, NULL, &timeout);
- pr_debug("select() rc: 0x%x\n", ret);
- if (ret == 0) {
+ 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;
@@ -655,7 +651,44 @@ static int lazy_pages_prepare_pstree(void)
return 0;
}
-static int prepare_uffds(struct lazy_pages_info *lpi)
+static int prepare_epoll(int nr_fds, struct epoll_event **events)
+{
+ int epollfd;
+
+ *events = malloc(sizeof(struct epoll_event) * nr_fds);
+ if (!events) {
+ pr_err("memory allocation failed\n");
+ 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_fd(int epollfd, int fd)
+{
+ struct epoll_event ev;
+
+ ev.events = EPOLLIN;
+ ev.data.fd = fd;
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
+ pr_perror("epoll_ctl failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int prepare_uffds(struct lazy_pages_info *lpi, int epollfd)
{
int listen;
int uffd;
@@ -691,6 +724,9 @@ static int prepare_uffds(struct lazy_pages_info *lpi)
if ((lpi->total_pages = find_vmas(lpi)) == -1)
goto close_uffd;
+ if (epoll_add_fd(epollfd, uffd))
+ goto close_uffd;
+
close(listen);
return 0;
@@ -704,6 +740,8 @@ close_unix_sock:
int cr_lazy_pages()
{
struct lazy_pages_info lpi;
+ struct epoll_event *events;
+ int epollfd;
if (!opts.addr) {
pr_info("Please specify a file name for the unix domain socket\n");
@@ -716,10 +754,14 @@ int cr_lazy_pages()
if (lazy_pages_prepare_pstree())
return -1;
- if (prepare_uffds(&lpi))
+ epollfd = prepare_epoll(task_entries->nr_tasks, &events);
+ if (epollfd < 0)
+ return -1;
+
+ if (prepare_uffds(&lpi, epollfd))
return -1;
- return handle_requests(&lpi);
+ return handle_requests(&lpi, epollfd, events);
}
#else /* CONFIG_HAS_UFFD */
--
1.9.1
More information about the CRIU
mailing list