[CRIU] [PATCH 4/4] files: dump file descriptors by protions

Pavel Emelyanov xemul at virtuozzo.com
Mon Apr 4 03:26:34 PDT 2016


On 04/01/2016 08:53 AM, Andrey Vagin wrote:
> From: Andrew Vagin <avagin at virtuozzo.com>
> 
> Currently criu can't handle a processes with more than 1024
> file descriptors.
> 
> In this patch, criu dumps file descriptors for a few iterations.
> 
> https://jira.sw.ru/browse/PSBM-44887
> https://github.com/xemul/criu/issues/145
> 
> Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
> ---
>  criu/files.c            | 69 +++++++++++++++++++++++++++----------------------
>  criu/include/parasite.h |  2 +-
>  2 files changed, 39 insertions(+), 32 deletions(-)
> 
> diff --git a/criu/files.c b/criu/files.c
> index eb5f3d9..4bcaf32 100644
> --- a/criu/files.c
> +++ b/criu/files.c
> @@ -459,20 +459,16 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
>  	return dump_unsupp_fd(&p, lfd, img, "unknown", NULL);
>  }
>  
> -static int collect_fds(pid_t pid, struct parasite_drain_fd *dfds, int *skip_fds, int skip_n)
> +static int collect_fds(pid_t pid, DIR *fd_dir,
> +			struct parasite_drain_fd *dfds, int *skip_fds, int skip_n)
>  {
>  	struct dirent *de;
> -	DIR *fd_dir;
>  	int n;
>  
>  	pr_info("\n");
>  	pr_info("Collecting fds (pid: %d)\n", pid);
>  	pr_info("----------------------------------------\n");
>  
> -	fd_dir = opendir_proc(pid, "fd");
> -	if (!fd_dir)
> -		return -1;
> -
>  	n = 0;
>  	while ((de = readdir(fd_dir))) {
>  		int fd, i;
> @@ -480,9 +476,6 @@ static int collect_fds(pid_t pid, struct parasite_drain_fd *dfds, int *skip_fds,
>  		if (dir_dots(de))
>  			continue;
>  
> -		if (n > PARASITE_MAX_FDS - 1)
> -			return -ENOMEM;
> -
>  		fd = atoi(de->d_name);
>  		for (i = 0; i < skip_n; i++)
>  			if (skip_fds[i] == fd)
> @@ -491,14 +484,14 @@ static int collect_fds(pid_t pid, struct parasite_drain_fd *dfds, int *skip_fds,
>  			continue;
>  
>  		dfds->fds[n++] = fd;
> +		if (n == PARASITE_MAX_FDS)
> +			break;
>  	}
>  
>  	dfds->nr_fds = n;
>  	pr_info("Found %d file descriptors\n", n);
>  	pr_info("----------------------------------------\n");
>  
> -	closedir(fd_dir);
> -
>  	return 0;
>  }
>  
> @@ -510,51 +503,65 @@ int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item)
>  	pid_t pid = ctl->pid.real;
>  	int *lfds = NULL;
>  	int i, ret = -1;
> +	DIR *fd_dir;
> +
> +	BUILD_BUG_ON(PARASITE_MAX_FDS > PAGE_SIZE / sizeof(int));
>  
>  	pr_info("\n");
>  	pr_info("Dumping opened files (pid: %d)\n", ctl->pid.real);
>  	pr_info("----------------------------------------\n");
>  
> -	dfds = xmalloc(sizeof(*dfds));
> -	if (!dfds)
> -		goto err;
> -
> +	fd_dir = opendir_proc(pid, "fd");
> +	if (!fd_dir)
> +		return -1;
>  	img = open_image(CR_FD_FDINFO, O_DUMP, item->ids->files_id);
>  	if (!img)
>  		goto err;
>  
> -	ret = collect_fds(pid, dfds, (int [2]) {ctl->ptsock, ctl->plogfd} , 2);
> -	if (ret) {
> -		pr_err("Collect fds (pid: %d) failed with %d\n", pid, ret);
> +	dfds = xmalloc(sizeof(*dfds));
> +	if (!dfds)
>  		goto err;

You've change the order of dfds = xmalloc and img = open_image to make
the reviewer work harder. Thank you.

> -	}
> -
> -	parasite_ensure_args_size(drain_fds_size(dfds));
>  
> -	lfds = xmalloc(dfds->nr_fds * sizeof(int));
> +	lfds = xmalloc(PARASITE_MAX_FDS * sizeof(int));
>  	if (!lfds)
>  		goto err;
>  
> -	opts = xmalloc(dfds->nr_fds * sizeof(struct fd_opts));
> +	opts = xmalloc(PARASITE_MAX_FDS * sizeof(struct fd_opts));
>  	if (!opts)
>  		goto err;
>  
> -	ret = parasite_drain_fds_seized(ctl, dfds, lfds, opts);
> -	if (ret)
> -		goto err;
> +	while (1) {
> +		ret = collect_fds(pid, fd_dir, dfds,
> +				  (int [2]) {ctl->ptsock, ctl->plogfd} , 2);
> +		if (ret) {
> +			pr_err("Collect fds (pid: %d) failed with %d\n", pid, ret);
> +			goto err;
> +		}
>  
> -	for (i = 0; i < dfds->nr_fds; i++) {
> -		ret = dump_one_file(ctl, dfds->fds[i], lfds[i], opts + i, img);
> -		close(lfds[i]);
> -		if (ret)
> +		if (dfds->nr_fds == 0)
>  			break;
> -	}
>  
> +		parasite_ensure_args_size(drain_fds_size(dfds));

Same here -- this ensure_args_size() makes no sense in this place.

> +
> +		ret = parasite_drain_fds_seized(ctl, dfds, lfds, opts);
> +		if (ret)
> +			goto err;
> +
> +		for (i = 0; i < dfds->nr_fds; i++) {
> +			ret = dump_one_file(ctl, dfds->fds[i], lfds[i], opts + i, img);
> +			close(lfds[i]);
> +			if (ret)
> +				break;
> +		}
> +	}
>  
>  	pr_info("----------------------------------------\n");
> +
>  err:
> +	closedir(fd_dir);
>  	if (img)
>  		close_image(img);
> +	xfree(dfds);
>  	xfree(opts);
>  	xfree(lfds);
>  	return ret;
> diff --git a/criu/include/parasite.h b/criu/include/parasite.h
> index 1319cb6..c3ae644 100644
> --- a/criu/include/parasite.h
> +++ b/criu/include/parasite.h
> @@ -224,7 +224,7 @@ static inline void copy_sas(ThreadSasEntry *dst, const stack_t *src)
>  	dst->ss_flags = src->ss_flags;
>  }
>  
> -#define PARASITE_MAX_FDS	(PAGE_SIZE / sizeof(int))
> +#define PARASITE_MAX_FDS CR_SCM_MAX_FD
>  
>  struct parasite_drain_fd {
>  	int	nr_fds;
> 



More information about the CRIU mailing list