[CRIU] [PATCH 07/11] lazy-pages: make handle_requests also poll for listening socket
Mike Rapoport
rppt at linux.vnet.ibm.com
Sun Apr 10 23:19:50 PDT 2016
Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
criu/uffd.c | 119 +++++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 77 insertions(+), 42 deletions(-)
diff --git a/criu/uffd.c b/criu/uffd.c
index 87c2602..fece56e 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -545,32 +545,56 @@ static int handle_user_fault(int fd, struct list_head *uffd_list, void *dest)
return 0;
}
+static int handle_socket_conn(int listen, struct sockaddr_un *saddr,
+ struct list_head *uffd_list)
+{
+ int uffd;
+ int uffd_flags;
+
+ uffd = ud_open(listen, saddr);
+ if (uffd < 0) {
+ pr_perror("uffd open error");
+ return -1;
+ }
+
+ pr_debug("uffd is 0x%d\n", uffd);
+ uffd_flags = fcntl(uffd, F_GETFD, NULL);
+ pr_debug("uffd_flags are 0x%x\n", uffd_flags);
+ if (fcntl(uffd, F_SETFD, uffd_flags | O_NONBLOCK))
+ return -1;
+
+ /*
+ * Find the memory pages belonging to the restored process so
+ * that it is trackable when all pages have been transferred.
+ */
+ if ((total_pages = find_vmas(uffd_list)) == -1)
+ return -1;
+
+ return uffd;
+}
+
#define POLL_TIMEOUT 5000
-static int handle_requests(int fd)
+static int handle_requests(int listen, struct sockaddr_un *saddr)
{
struct pollfd *pollfd;
- int nr_pollfd;
+ int nr_pollfd = 1;
+ int max_pollfd;
+ int timeout = -1;
int ret = -1;
unsigned long ps;
void *dest;
+ int i;
LIST_HEAD(uffd_list);
- /*
- * Find the memory pages belonging to the restored process
- * so that it is trackable when all pages have been transferred.
- */
- if ((total_pages = find_vmas(&uffd_list)) == -1)
- return -1;
-
/* All operations will be done on page size */
ps = page_size();
dest = malloc(ps);
/* allocate pollfd per task + pollfd for listen */
- nr_pollfd = task_entries->nr_tasks + 1;
- pollfd = malloc(sizeof(*pollfd) * nr_pollfd);
+ max_pollfd = task_entries->nr_tasks + 1;
+ pollfd = malloc(sizeof(*pollfd) * max_pollfd);
if (!pollfd || !dest) {
pr_err("memory allocation failed\n");
ret = -1;
@@ -578,12 +602,10 @@ static int handle_requests(int fd)
}
/*
- * use nr_pollfd to set number of pollfd's being polled
- * FIXME: eventually nr_pollfd should be nr_tasks + 1, and the
- * first fd to poll on should that of listen
+ * use nr_pollfd to set number of pollfd's being polled, the
+ * first pollfd is always for the listening socket
*/
- nr_pollfd = 1;
- pollfd[0].fd = fd;
+ pollfd[0].fd = listen;
pollfd[0].events = POLLIN;
while (1) {
@@ -592,7 +614,7 @@ static int handle_requests(int fd)
* no uffd pages are requested the code switches to
* copying the remaining pages.
*/
- ret = poll(pollfd, nr_pollfd, POLL_TIMEOUT);
+ ret = poll(pollfd, nr_pollfd, timeout);
pr_debug("poll() rc: 0x%x\n", ret);
if (ret < 0) {
pr_perror("polling failed");
@@ -603,16 +625,42 @@ static int handle_requests(int fd)
break;
}
- ret = handle_user_fault(fd, &uffd_list, dest);
- if (ret < 0)
- goto out;
+ if (pollfd[0].revents & POLLIN) {
+ int fd = handle_socket_conn(listen, saddr, &uffd_list);
+ if (fd < 0)
+ goto out;
+ pollfd[nr_pollfd].fd = fd;
+ pollfd[nr_pollfd].events = POLLIN;
+ nr_pollfd++;
+ BUG_ON(nr_pollfd > max_pollfd);
+
+ /*
+ * once the first uffd is register wait POLL_TIMEOUT
+ * before starting bulk page trasfer
+ */
+ timeout = POLL_TIMEOUT;
+
+ continue;
+ }
+
+ for (i = 1; i < nr_pollfd; i++) {
+ if (pollfd[i].revents & POLLIN) {
+ ret = handle_user_fault(pollfd[i].fd,
+ &uffd_list, dest);
+ if (ret < 0)
+ goto out;
+ }
+ }
}
- pr_debug("Handle remaining pages\n");
- ret = handle_remaining_pages(fd, &uffd_list, dest);
- if (ret < 0) {
- pr_err("Error during remaining page copy\n");
- ret = 1;
- goto out;
+
+ for (i = 1; i < nr_pollfd; i++) {
+ pr_debug("Handle remaining pages\n");
+ ret = handle_remaining_pages(pollfd[i].fd, &uffd_list, dest);
+ if (ret < 0) {
+ pr_err("Error during remaining page copy\n");
+ ret = 1;
+ goto out;
+ }
}
pr_debug("With UFFD transferred pages: (%ld/%ld)\n", uffd_copied_pages, total_pages);
@@ -626,9 +674,10 @@ static int handle_requests(int fd)
ret = 0;
out:
+ for (i = nr_pollfd - 1; i > 0; i--)
+ close(pollfd[i].fd);
free(pollfd);
free(dest);
- close(fd);
return ret;
}
@@ -657,8 +706,6 @@ static int lazy_pages_prepare_pstree(void)
int cr_lazy_pages()
{
int listen;
- int uffd;
- int uffd_flags;
int ret;
struct sockaddr_un saddr;
@@ -679,19 +726,7 @@ int cr_lazy_pages()
return -1;
}
- uffd = ud_open(listen, &saddr);
- if (uffd < 0) {
- pr_perror("uffd open error");
- return -1;
- }
-
- pr_debug("uffd is 0x%d\n", uffd);
- uffd_flags = fcntl(uffd, F_GETFD, NULL);
- pr_debug("uffd_flags are 0x%x\n", uffd_flags);
- if (fcntl(uffd, F_SETFD, uffd_flags | O_NONBLOCK))
- return -1;
-
- ret = handle_requests(uffd);
+ ret = handle_requests(listen, &saddr);
close(listen);
return ret;
--
1.9.1
More information about the CRIU
mailing list