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

Mike Rapoport rppt at linux.vnet.ibm.com
Tue Apr 12 04:23:19 PDT 2016


On Tue, Apr 12, 2016 at 02:03:21PM +0300, Pavel Emelyanov wrote:
> 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.

Frankly, I was too lazy to read epoll manuals because for tens of
descriptors poll should be fast enough :)
We anyway will have to do some optimization rounds for uffd.c... 
 
> > 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