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

Mike Rapoport mike.rapoport at gmail.com
Mon Nov 21 04:48:38 PST 2016


On Mon, Nov 21, 2016 at 02:26:40PM +0300, Pavel Emelyanov wrote:
> 
> Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
> ---
>  criu/include/util.h | 14 ++++++++++
>  criu/uffd.c         | 74 +++++++++++------------------------------------------
>  criu/util.c         | 43 +++++++++++++++++++++++++++++++
>  3 files changed, 72 insertions(+), 59 deletions(-)
> 
> diff --git a/criu/include/util.h b/criu/include/util.h
> index 8eaee33..d6d3063 100644
> --- a/criu/include/util.h
> +++ b/criu/include/util.h
> @@ -281,4 +281,18 @@ 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);
> +

And what about, say

extern int epoll_alloc_events(int nr_fds, struct epoll_event **events);

?

>  #endif /* __CR_UTIL_H__ */
> diff --git a/criu/uffd.c b/criu/uffd.c
> index 2d09e66..c16f191 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);
> @@ -826,20 +796,6 @@ 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;
> @@ -879,7 +835,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;
>  	}
>  
> @@ -893,12 +849,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)
>  {
> @@ -908,10 +864,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)
> diff --git a/criu/util.c b/criu/util.c
> index 2cf0355..58a483a 100644
> --- a/criu/util.c
> +++ b/criu/util.c
> @@ -1185,3 +1185,46 @@ 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;
> +}
> -- 
> 2.5.0
> 


More information about the CRIU mailing list