Commit 96a355ab authored by Andrew Vagin's avatar Andrew Vagin Committed by Pavel Emelyanov

files: dump file descriptors by portions (v2)

Currently criu can't handle a processes with more than 1024
file descriptors.

In this patch, criu dumps file descriptors for a few iterations.

Fixes https://github.com/xemul/criu/issues/145

v2: don't move the collect stage
Signed-off-by: 's avatarAndrew Vagin <avagin@virtuozzo.com>
Reviewed-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent a249869d
...@@ -204,9 +204,6 @@ static int collect_fds(pid_t pid, struct parasite_drain_fd **dfds) ...@@ -204,9 +204,6 @@ static int collect_fds(pid_t pid, struct parasite_drain_fd **dfds)
if (dir_dots(de)) if (dir_dots(de))
continue; continue;
if (n > PARASITE_MAX_FDS - 1)
return -ENOMEM;
if (sizeof(struct parasite_drain_fd) + sizeof(int) * (n + 1) > size) { if (sizeof(struct parasite_drain_fd) + sizeof(int) * (n + 1) > size) {
struct parasite_drain_fd *t; struct parasite_drain_fd *t;
......
...@@ -459,46 +459,52 @@ static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_op ...@@ -459,46 +459,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, int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
struct parasite_drain_fd *dfds) struct parasite_drain_fd *dfds)
{ {
int *lfds; int *lfds = NULL;
struct cr_img *img; struct cr_img *img = NULL;
struct fd_opts *opts; struct fd_opts *opts = NULL;
int i, ret = -1; int i, ret = -1;
int off, nr_fds = min((int) PARASITE_MAX_FDS, dfds->nr_fds);
pr_info("\n"); pr_info("\n");
pr_info("Dumping opened files (pid: %d)\n", ctl->pid.real); pr_info("Dumping opened files (pid: %d)\n", ctl->pid.real);
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
lfds = xmalloc(dfds->nr_fds * sizeof(int)); lfds = xmalloc(nr_fds * sizeof(int));
if (!lfds) if (!lfds)
goto err; goto err;
opts = xmalloc(dfds->nr_fds * sizeof(struct fd_opts)); opts = xmalloc(nr_fds * sizeof(struct fd_opts));
if (!opts) if (!opts)
goto err1; goto err;
ret = parasite_drain_fds_seized(ctl, dfds, lfds, opts);
if (ret)
goto err2;
img = open_image(CR_FD_FDINFO, O_DUMP, item->ids->files_id); img = open_image(CR_FD_FDINFO, O_DUMP, item->ids->files_id);
if (!img) 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 = parasite_drain_fds_seized(ctl, dfds, nr_fds,
ret = dump_one_file(ctl, dfds->fds[i], lfds[i], opts + i, img); off, lfds, opts);
close(lfds[i]);
if (ret) 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"); pr_info("----------------------------------------\n");
err2: err:
if (img)
close_image(img);
xfree(opts); xfree(opts);
err1:
xfree(lfds); xfree(lfds);
err:
return ret; return ret;
} }
......
...@@ -91,7 +91,7 @@ extern int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id, ...@@ -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 dump_thread_core(int pid, CoreEntry *core, const struct parasite_dump_thread *dt);
extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, 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); int *lfds, struct fd_opts *flags);
extern int parasite_get_proc_fd_seized(struct parasite_ctl *ctl); extern int parasite_get_proc_fd_seized(struct parasite_ctl *ctl);
......
...@@ -231,7 +231,8 @@ struct parasite_drain_fd { ...@@ -231,7 +231,8 @@ struct parasite_drain_fd {
static inline int drain_fds_size(struct parasite_drain_fd *dfds) 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 * sizeof(dfds->fds[0]);
} }
struct parasite_tty_args { struct parasite_tty_args {
......
...@@ -811,14 +811,16 @@ struct parasite_tty_args *parasite_dump_tty(struct parasite_ctl *ctl, int fd, in ...@@ -811,14 +811,16 @@ struct parasite_tty_args *parasite_dump_tty(struct parasite_ctl *ctl, int fd, in
} }
int parasite_drain_fds_seized(struct parasite_ctl *ctl, 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; int ret = -1, size;
struct parasite_drain_fd *args; struct parasite_drain_fd *args;
size = drain_fds_size(dfds); size = drain_fds_size(dfds);
args = parasite_args_s(ctl, size); 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); ret = __parasite_execute_daemon(PARASITE_CMD_DRAIN_FDS, ctl);
if (ret) { if (ret) {
...@@ -826,7 +828,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl, ...@@ -826,7 +828,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl,
goto err; goto err;
} }
ret = recv_fds(ctl->tsock, lfds, dfds->nr_fds, opts); ret = recv_fds(ctl->tsock, lfds, nr_fds, opts);
if (ret) if (ret)
pr_err("Can't retrieve FDs from socket\n"); pr_err("Can't retrieve FDs from socket\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment