[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