[CRIU] [PATCH 05/11] lazy-pages: use poll instead of select

Pavel Emelyanov xemul at virtuozzo.com
Tue Apr 12 04:03:21 PDT 2016


On 04/11/2016 09:19 AM, Mike Rapoport wrote:

Why not epoll? AFAIK this is right now the best (from the scalability
POV) way to poll file descriptors.

> Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
> ---
>  criu/uffd.c | 47 ++++++++++++++++++++++++++++++++---------------
>  1 file changed, 32 insertions(+), 15 deletions(-)
> 
> diff --git a/criu/uffd.c b/criu/uffd.c
> index 254a5b3..14de015 100644
> --- a/criu/uffd.c
> +++ b/criu/uffd.c
> @@ -500,15 +500,17 @@ out:
>  	return ret;
>  }
>  
> +#define POLL_TIMEOUT 5000
> +
>  static int handle_requests(int fd)
>  {
> -	fd_set set;
> +	struct pollfd *pollfd;
> +	int nr_pollfd;
>  	int ret = -1;
>  	struct uffd_msg msg;
>  	__u64 flags;
>  	__u64 address;
>  	unsigned long ps;
> -	struct timeval timeout;
>  	struct uffd_pages_struct *uffd_pages;
>  	void *dest;
>  
> @@ -521,34 +523,46 @@ static int handle_requests(int fd)
>  	if ((total_pages = find_vmas(&uffd_list)) == -1)
>  		return -1;
>  
> -	/* Initialize FD sets for read() with timeouts (using select()) */
> -	FD_ZERO(&set);
> -	FD_SET(fd, &set);
> -
>  	/* 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);
> +	if (!pollfd || !dest) {
> +		pr_err("memory allocation failed\n");
> +		ret = -1;
> +		goto out;
> +	}
> +
> +	/*
> +	 * 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
> +	 */
> +	nr_pollfd = 1;
> +	pollfd[0].fd = fd;
> +	pollfd[0].events = POLLIN;
> +
>  	while (1) {
>  		bool page_sent = false;
>  		/*
>  		 * 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(fd + 1, &set, NULL, NULL, &timeout);
> -		pr_debug("select() rc: 0x%x\n", ret);
> -		if (ret == 0) {
> +		ret = poll(pollfd, nr_pollfd, POLL_TIMEOUT);
> +		pr_debug("poll() rc: 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;
>  		}
> +
>  		ret = read(fd, &msg, sizeof(msg));
>  		pr_debug("read() ret: 0x%x\n", ret);
>  		if (!ret)
> @@ -613,6 +627,7 @@ static int handle_requests(int fd)
>  	ret = 0;
>  
>  out:
> +	free(pollfd);
>  	free(dest);
>  	close(fd);
>  	return ret;
> @@ -674,6 +689,8 @@ int cr_lazy_pages()
>  	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);
>  	close(listen);
> 



More information about the CRIU mailing list