[CRIU] [PATCH 07/12] dump: Use parasite file descriptors draining
Cyrill Gorcunov
gorcunov at openvz.org
Sun Mar 25 17:33:53 EDT 2012
Since we're able to simply drain file descriptors
we're interested in, just do that with parasite
help.
This changes the calling sequence a bit
1) Collect file descriptors before parasite
get intected the dumpee and remember them in
local copy.
2) Ask parasite to drain collected descriptrs
into our space.
3) Operate with file descriptors directly via fcntl
calls and such.
Overall idea is to prepare ground for fowners
dumping which will be addressed in further patches.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
cr-dump.c | 143 +++++++++++++++++++++++++++++++++----------------------------
1 files changed, 77 insertions(+), 66 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index 9fd4f2c..0374255 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -31,6 +31,7 @@
#include "namespaces.h"
#include "image.h"
#include "proc_parse.h"
+#include "parasite.h"
#include "parasite-syscall.h"
#ifndef CONFIG_X86_64
@@ -87,7 +88,36 @@ err:
return ret;
}
-static int reg_files_fd = -1;
+static int collect_fds(pid_t pid, int *fd, int *nr_fd)
+{
+ struct dirent *d;
+ DIR *dir;
+ int n;
+
+ pr_info("\n");
+ pr_info("Collecting fds (pid: %d)\n", pid);
+ pr_info("----------------------------------------\n");
+
+ dir = opendir_proc(pid, "fd");
+ if (!dir)
+ return -1;
+
+ n = 0;
+ while ((d = readdir(dir))) {
+ if (d->d_name[0] == '.')
+ continue;
+
+ if (n > *nr_fd - 1)
+ return -ENOMEM;
+ fd[n++] = atoi(d->d_name);
+ }
+
+ *nr_fd = n;
+ pr_info("Found %d file descriptors\n", n);
+
+ pr_info("----------------------------------------\n");
+ return 0;
+}
struct fd_parms {
unsigned long fd_name;
@@ -99,6 +129,8 @@ struct fd_parms {
pid_t pid;
};
+static int reg_files_fd = -1;
+
static int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
{
char fd_str[128];
@@ -289,68 +321,47 @@ err:
return ret;
}
-static int read_fd_params(pid_t pid, const char *fd, struct fd_parms *p)
+static void fill_fd_params(pid_t pid, int fd, int lfd, struct fd_parms *p)
{
- FILE *file;
- int ret;
+ p->fd_name = fd;
+ p->pos = lseek(lfd, 0, SEEK_CUR);
+ p->flags = fcntl(lfd, F_GETFL);
+ p->pid = pid;
+ p->id = FD_ID_INVALID;
- file = fopen_proc(pid, "fdinfo/%s", fd);
- if (!file)
- return -1;
-
- p->fd_name = atoi(fd);
- ret = fscanf(file, "pos:\t%li\nflags:\t%o\n", &p->pos, &p->flags);
- fclose(file);
-
- if (ret != 2) {
- pr_err("Bad format of fdinfo file (%d items, want 2)\n", ret);
- return -1;
- }
-
- pr_info("%d fdinfo %s: pos: %16lx flags: %16o\n",
+ pr_info("%d fdinfo %d: pos: %16lx flags: %16o\n",
pid, fd, p->pos, p->flags);
-
- p->pid = pid;
- p->id = FD_ID_INVALID;
-
- return 0;
}
-static int dump_one_fd(pid_t pid, int pid_fd_dir, const char *d_name,
+static int dump_one_fd(pid_t pid, int fd, int lfd,
const struct cr_fdset *cr_fdset,
struct sk_queue *sk_queue)
{
struct stat fd_stat;
- int err = -1;
struct fd_parms p;
- int lfd;
-
- if (read_fd_params(pid, d_name, &p))
- return -1;
-
- lfd = openat(pid_fd_dir, d_name, O_RDONLY);
- if (lfd < 0) {
- err = try_dump_socket(pid, p.fd_name, cr_fdset, sk_queue);
- if (err != 1)
- return err;
-
- pr_perror("Failed to open %d/%ld", pid_fd_dir, p.fd_name);
- return -1;
- }
+ int err = -1;
if (fstat(lfd, &fd_stat) < 0) {
- pr_perror("Can't get stat on %ld", p.fd_name);
+ pr_perror("Can't get stat on %d", fd);
goto out_close;
}
+ if (S_ISSOCK(fd_stat.st_mode)) {
+ err = try_dump_socket(pid, fd, cr_fdset, sk_queue);
+ if (err)
+ pr_perror("Failed to open %d", fd);
+ return err;
+ }
+
+ fill_fd_params(pid, fd, lfd, &p);
+
if (S_ISCHR(fd_stat.st_mode) &&
(major(fd_stat.st_rdev) == TTY_MAJOR ||
major(fd_stat.st_rdev) == UNIX98_PTY_SLAVE_MAJOR)) {
/* skip only standard destriptors */
if (p.fd_name < 3) {
err = 0;
- pr_info("... Skipping tty ... %d/%ld\n",
- pid_fd_dir, p.fd_name);
+ pr_info("... Skipping tty ... %d\n", fd);
goto out_close;
}
goto err;
@@ -370,52 +381,43 @@ static int dump_one_fd(pid_t pid, int pid_fd_dir, const char *d_name,
return dump_one_pipe(&p, fd_stat.st_ino, lfd, cr_fdset);
err:
- pr_err("Can't dump file %ld of that type [%x]\n", p.fd_name, fd_stat.st_mode);
+ pr_err("Can't dump file %d of that type [%x]\n", fd, fd_stat.st_mode);
out_close:
close_safe(&lfd);
return err;
}
-static int dump_task_files(pid_t pid, const struct cr_fdset *cr_fdset,
- struct sk_queue *sk_queue)
+static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdset *cr_fdset,
+ int *fds, int nr_fds, struct sk_queue *sk_queue)
{
- struct dirent *de;
- unsigned long pos;
- unsigned int flags;
- DIR *fd_dir;
+ int lfds[PARASITE_MAX_FDS];
+ int i;
pr_info("\n");
- pr_info("Dumping opened files (pid: %d)\n", pid);
+ pr_info("Dumping opened files (pid: %d)\n", ctl->pid);
pr_info("----------------------------------------\n");
+ if (parasite_drain_fds_seized(ctl, fds, lfds, nr_fds))
+ return -1;
+
/*
* Dump special files at the beginning. We might need
* to re-read them in restorer, so better to make it
* fast.
*/
- if (dump_task_special_files(pid, cr_fdset)) {
+ if (dump_task_special_files(ctl->pid, cr_fdset)) {
pr_err("Can't dump special files\n");
return -1;
}
- fd_dir = opendir_proc(pid, "fd");
- if (!fd_dir)
- return -1;
-
- while ((de = readdir(fd_dir))) {
- if (!strcmp(de->d_name, "."))
- continue;
- if (!strcmp(de->d_name, ".."))
- continue;
- if (dump_one_fd(pid, dirfd(fd_dir), de->d_name, cr_fdset,
- sk_queue))
+ for (i = 0; i < nr_fds; i++) {
+ if (dump_one_fd(ctl->pid, fds[i], lfds[i],
+ cr_fdset, sk_queue))
return -1;
}
pr_info("----------------------------------------\n");
-
- closedir(fd_dir);
return 0;
}
@@ -1290,6 +1292,9 @@ static int dump_one_task(const struct pstree_item *item, struct cr_fdset *cr_fds
struct parasite_dump_misc misc;
struct sk_queue sk_queue = { };
+ int nr_fds = PARASITE_MAX_FDS;
+ int fds[nr_fds];
+
pr_info("========================================\n");
pr_info("Dumping task (pid: %d)\n", pid);
pr_info("========================================\n");
@@ -1317,9 +1322,9 @@ static int dump_one_task(const struct pstree_item *item, struct cr_fdset *cr_fds
goto err;
}
- ret = dump_task_files(pid, cr_fdset, &sk_queue);
+ ret = collect_fds(pid, fds, &nr_fds);
if (ret) {
- pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
+ pr_err("Collect fds (pid: %d) failed with %d\n", pid, ret);
goto err;
}
@@ -1329,6 +1334,12 @@ static int dump_one_task(const struct pstree_item *item, struct cr_fdset *cr_fds
goto err;
}
+ ret = dump_task_files_seized(parasite_ctl, cr_fdset, fds, nr_fds, &sk_queue);
+ if (ret) {
+ pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
+ goto err;
+ }
+
ret = parasite_dump_pages_seized(parasite_ctl, &vma_area_list, cr_fdset);
if (ret) {
pr_err("Can't dump pages (pid: %d) with parasite\n", pid);
--
1.7.7.6
More information about the CRIU
mailing list