[CRIU] [PATCH 2/3] files: dump file descriptors by portions (v2)

Andrey Vagin avagin at openvz.org
Mon Apr 4 09:58:07 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

v2: don't move the collect stage

Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 criu/cr-dump.c                  |  3 ---
 criu/files.c                    | 46 +++++++++++++++++++++++------------------
 criu/include/parasite-syscall.h |  2 +-
 criu/include/parasite.h         |  4 +++-
 criu/parasite-syscall.c         |  8 ++++---
 5 files changed, 35 insertions(+), 28 deletions(-)

diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 5163699..d29a194 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -204,9 +204,6 @@ static int collect_fds(pid_t pid, struct parasite_drain_fd **dfds)
 		if (dir_dots(de))
 			continue;
 
-		if (n > PARASITE_MAX_FDS - 1)
-			return -ENOMEM;
-
 		if (sizeof(struct parasite_drain_fd) + sizeof(int) * (n + 1) > size) {
 			struct parasite_drain_fd *t;
 
diff --git a/criu/files.c b/criu/files.c
index a30dd06..79207f6 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -462,46 +462,52 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op
 int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
 		struct parasite_drain_fd *dfds)
 {
-	int *lfds;
-	struct cr_img *img;
-	struct fd_opts *opts;
+	int *lfds = NULL;
+	struct cr_img *img = NULL;
+	struct fd_opts *opts = NULL;
 	int i, ret = -1;
+	int off, nr_fds = min((int) PARASITE_MAX_FDS, dfds->nr_fds);
 
 	pr_info("\n");
 	pr_info("Dumping opened files (pid: %d)\n", ctl->pid.real);
 	pr_info("----------------------------------------\n");
 
-	lfds = xmalloc(dfds->nr_fds * sizeof(int));
+	lfds = xmalloc(nr_fds * sizeof(int));
 	if (!lfds)
 		goto err;
 
-	opts = xmalloc(dfds->nr_fds * sizeof(struct fd_opts));
+	opts = xmalloc(nr_fds * sizeof(struct fd_opts));
 	if (!opts)
-		goto err1;
-
-	ret = parasite_drain_fds_seized(ctl, dfds, lfds, opts);
-	if (ret)
-		goto err2;
+		goto err;
 
 	img = open_image(CR_FD_FDINFO, O_DUMP, item->ids->files_id);
 	if (!img)
-		goto err2;
+		goto err;
+
+	for (off = 0; off < dfds->nr_fds; off += nr_fds) {
+		if (nr_fds + off > dfds->nr_fds)
+			nr_fds = dfds->nr_fds - off;
 
-	for (i = 0; i < dfds->nr_fds; i++) {
-		ret = dump_one_file(ctl, dfds->fds[i], lfds[i], opts + i, img);
-		close(lfds[i]);
+		ret = parasite_drain_fds_seized(ctl, dfds, nr_fds,
+							off, lfds, opts);
 		if (ret)
-			break;
+			goto err;
+
+		for (i = 0; i < nr_fds; i++) {
+			ret = dump_one_file(ctl, dfds->fds[i + off],
+						lfds[i], opts + i, img);
+			close(lfds[i]);
+			if (ret)
+				break;
+		}
 	}
 
-	close_image(img);
-
 	pr_info("----------------------------------------\n");
-err2:
+err:
+	if (img)
+		close_image(img);
 	xfree(opts);
-err1:
 	xfree(lfds);
-err:
 	return ret;
 }
 
diff --git a/criu/include/parasite-syscall.h b/criu/include/parasite-syscall.h
index 04d2602..15a13a6 100644
--- a/criu/include/parasite-syscall.h
+++ b/criu/include/parasite-syscall.h
@@ -91,7 +91,7 @@ extern int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
 extern int dump_thread_core(int pid, CoreEntry *core, const struct parasite_dump_thread *dt);
 
 extern int parasite_drain_fds_seized(struct parasite_ctl *ctl,
-					struct parasite_drain_fd *dfds,
+					struct parasite_drain_fd *dfds, int nr_fds, int off,
 					int *lfds, struct fd_opts *flags);
 extern int parasite_get_proc_fd_seized(struct parasite_ctl *ctl);
 
diff --git a/criu/include/parasite.h b/criu/include/parasite.h
index 417b324..7974a81 100644
--- a/criu/include/parasite.h
+++ b/criu/include/parasite.h
@@ -226,12 +226,14 @@ static inline void copy_sas(ThreadSasEntry *dst, const stack_t *src)
 
 struct parasite_drain_fd {
 	int	nr_fds;
+	int	off;
 	int	fds[0];
 };
 
 static inline int drain_fds_size(struct parasite_drain_fd *dfds)
 {
-	return sizeof(dfds->nr_fds) + dfds->nr_fds * sizeof(dfds->fds[0]);
+	int nr_fds = min((int)PARASITE_MAX_FDS, dfds->nr_fds);
+	return sizeof(dfds->nr_fds) + nr_fds * sizeof(dfds->fds[0]);
 }
 
 struct parasite_tty_args {
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index 8866965..fe0df6e 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -810,14 +810,16 @@ struct parasite_tty_args *parasite_dump_tty(struct parasite_ctl *ctl, int fd, in
 }
 
 int parasite_drain_fds_seized(struct parasite_ctl *ctl,
-		struct parasite_drain_fd *dfds, int *lfds, struct fd_opts *opts)
+		struct parasite_drain_fd *dfds, int nr_fds, int off,
+		int *lfds, struct fd_opts *opts)
 {
 	int ret = -1, size;
 	struct parasite_drain_fd *args;
 
 	size = drain_fds_size(dfds);
 	args = parasite_args_s(ctl, size);
-	memcpy(args, dfds, size);
+	args->nr_fds = nr_fds;
+	memcpy(&args->fds, dfds->fds + off, sizeof(int) * nr_fds);
 
 	ret = __parasite_execute_daemon(PARASITE_CMD_DRAIN_FDS, ctl);
 	if (ret) {
@@ -825,7 +827,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl,
 		goto err;
 	}
 
-	ret = recv_fds(ctl->tsock, lfds, dfds->nr_fds, opts);
+	ret = recv_fds(ctl->tsock, lfds, nr_fds, opts);
 	if (ret)
 		pr_err("Can't retrieve FDs from socket\n");
 
-- 
2.5.0



More information about the CRIU mailing list