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

Andrey Vagin avagin at openvz.org
Thu Mar 31 22:53:28 PDT 2016


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;
-	}
-
-	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));
+
+		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;
-- 
2.5.0



More information about the CRIU mailing list