[CRIU] [PATCH cr 04/11] pipe: all pipes are saved in one file (v2)
Andrey Vagin
avagin at openvz.org
Thu Apr 5 12:02:08 EDT 2012
Information about pipe's file structs saved in one global file and
fdinfo_entry is saved for each descriptor
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
cr-dump.c | 205 +++++++++++++++++++++++++++--------------------------
cr-show.c | 4 +-
include/crtools.h | 4 +-
include/image.h | 5 +-
4 files changed, 110 insertions(+), 108 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index e7c94a2..f1e9f6c 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -158,6 +158,89 @@ static int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
return 0;
}
+#define PIPES_SIZE 1024
+static u32 *pipes; /* pipes for which data already dumped */
+static int nr_pipes = 0;
+
+static int dump_one_pipe(int lfd, u32 id, const struct fd_parms *p)
+{
+ struct pipe_entry pe;
+ int fd_pipes;
+ int steal_pipe[2];
+ int pipe_size;
+ int has_bytes = 0;
+ int ret = -1;
+ int i = 0;
+
+ pr_info("Dumping pipe %d with id %x pipe_id %x\n", lfd, id, p->id);
+
+ fd_pipes = fdset_fd(glob_fdset, CR_FD_PIPES);
+
+ if (p->flags & O_WRONLY)
+ goto dump;
+
+ pr_info("Dumping data from pipe %x fd %d\n", id, lfd);
+
+ for (i = 0; i < nr_pipes; i++)
+ if (pipes[i] == p->id)
+ goto dump; /* data was dumped already */
+
+ nr_pipes++;
+ if (nr_pipes > PIPES_SIZE) {
+ pr_err("OOM storing pipe\n");
+ return -1;
+ }
+
+ pipes[nr_pipes - 1] = p->id;
+
+ pipe_size = fcntl(lfd, F_GETPIPE_SZ);
+ if (pipe_size < 0) {
+ pr_err("Can't obtain piped data size\n");
+ goto err;
+ }
+
+ if (pipe(steal_pipe) < 0) {
+ pr_perror("Can't create pipe for stealing data");
+ goto err;
+ }
+
+ has_bytes = tee(lfd, steal_pipe[1], pipe_size, SPLICE_F_NONBLOCK);
+ if (has_bytes < 0) {
+ if (errno != EAGAIN) {
+ pr_perror("Can't pick pipe data");
+ goto err_close;
+ } else
+ has_bytes = 0;
+ }
+dump:
+ pe.id = id;
+ pe.pipe_id = p->id;
+ pe.bytes = has_bytes;
+ pe.flags = p->flags;
+
+ if (write_img(fd_pipes, &pe))
+ goto err_close;
+
+ if (has_bytes) {
+ ret = splice(steal_pipe[0], NULL, fd_pipes,
+ NULL, has_bytes, 0);
+ if (ret < 0) {
+ pr_perror("Can't push pipe data");
+ goto err_close;
+ }
+ }
+
+ ret = 0;
+
+err_close:
+ if (has_bytes) {
+ close(steal_pipe[0]);
+ close(steal_pipe[1]);
+ }
+err:
+ return ret;
+}
+
static int do_dump_one_fdinfo(const struct fd_parms *p, int lfd,
const struct cr_fdset *cr_fdset)
{
@@ -170,7 +253,14 @@ static int do_dump_one_fdinfo(const struct fd_parms *p, int lfd,
ret = fd_id_generate(p->pid, &e);
if (ret == 1) /* new ID generated */
- ret = dump_one_reg_file(lfd, e.id, p);
+ switch (p->type) {
+ case FDINFO_PIPE:
+ ret = dump_one_pipe(lfd, e.id, p);
+ break;
+ default:
+ ret = dump_one_reg_file(lfd, e.id, p);
+ break;
+ }
if (ret < 0)
goto err;
@@ -190,7 +280,10 @@ static int dump_one_fdinfo(struct fd_parms *p, int lfd,
const struct cr_fdset *cr_fdset)
{
p->id = MAKE_FD_GENID(p->stat.st_dev, p->stat.st_ino, p->pos);
- p->type = FDINFO_REG;
+ if (S_ISFIFO(p->stat.st_mode))
+ p->type = FDINFO_PIPE;
+ else
+ p->type = FDINFO_REG;
return do_dump_one_fdinfo(p, lfd, cr_fdset);
}
@@ -231,101 +324,6 @@ static int dump_task_special_files(pid_t pid, const struct cr_fdset *cr_fdset)
return ret;
}
-static int dump_pipe_and_data(int lfd, struct pipe_entry *e,
- const struct cr_fdset *cr_fdset)
-{
- int fd_pipes;
- int steal_pipe[2];
- int pipe_size;
- int has_bytes;
- int ret = -1;
-
- fd_pipes = fdset_fd(cr_fdset, CR_FD_PIPES);
-
- pr_info("Dumping data from pipe %x\n", e->pipeid);
- if (pipe(steal_pipe) < 0) {
- pr_perror("Can't create pipe for stealing data");
- goto err;
- }
-
- pipe_size = fcntl(lfd, F_GETPIPE_SZ);
- if (pipe_size < 0) {
- pr_err("Can't obtain piped data size\n");
- goto err;
- }
-
- has_bytes = tee(lfd, steal_pipe[1], pipe_size, SPLICE_F_NONBLOCK);
- if (has_bytes < 0) {
- if (errno != EAGAIN) {
- pr_perror("Can't pick pipe data");
- goto err_close;
- } else
- has_bytes = 0;
- }
-
- e->bytes = has_bytes;
- if (write_img(fd_pipes, e))
- goto err_close;
-
- if (has_bytes) {
- ret = splice(steal_pipe[0], NULL, fd_pipes,
- NULL, has_bytes, 0);
- if (ret < 0) {
- pr_perror("Can't push pipe data");
- goto err_close;
- }
- }
-
- ret = 0;
-
-err_close:
- close(steal_pipe[0]);
- close(steal_pipe[1]);
-
-err:
- return ret;
-}
-
-static int dump_one_pipe(const struct fd_parms *p, int lfd,
- const struct cr_fdset *cr_fdset)
-{
- struct pipe_entry e;
- int ret = -1;
- struct statfs stfs_buf;
- int id = p->stat.st_ino;
-
- if (fstatfs(lfd, &stfs_buf) < 0) {
- pr_perror("Can't fstatfs on %ld", p->fd_name);
- return -1;
- }
-
- if (stfs_buf.f_type != PIPEFS_MAGIC) {
- pr_err("Dumping of FIFO's is not supported: %ld\n", p->fd_name);
- return -1;
- }
-
- pr_info("Dumping pipe %ld/%x flags %x\n", p->fd_name, id, p->flags);
-
- e.fd = p->fd_name;
- e.pipeid = id;
- e.flags = p->flags;
-
- if (p->flags & O_WRONLY) {
- e.bytes = 0;
- ret = write_img(fdset_fd(cr_fdset, CR_FD_PIPES), &e);
- } else
- ret = dump_pipe_and_data(lfd, &e, cr_fdset);
-
-err:
- if (!ret)
- pr_info("Dumped pipe: fd: %8x pipeid: %8x flags: %8x bytes: %8x\n",
- e.fd, e.pipeid, e.flags, e.bytes);
- else
- pr_err("Dumping pipe %ld/%x flags %x\n", p->fd_name, id, p->flags);
-
- return ret;
-}
-
static int fill_fd_params(pid_t pid, int fd, int lfd, struct fd_parms *p)
{
if (fstat(lfd, &p->stat) < 0) {
@@ -385,12 +383,11 @@ static int dump_one_fd(pid_t pid, int fd, int lfd,
if (S_ISCHR(p.stat.st_mode))
return dump_one_chrdev(&p, lfd, cr_fdset);
- if (S_ISREG(p.stat.st_mode) || S_ISDIR(p.stat.st_mode))
+ if (S_ISREG(p.stat.st_mode) ||
+ S_ISDIR(p.stat.st_mode) ||
+ S_ISFIFO(p.stat.st_mode))
return dump_one_fdinfo(&p, lfd, cr_fdset);
- if (S_ISFIFO(p.stat.st_mode))
- return dump_one_pipe(&p, lfd, cr_fdset);
-
return dump_unsupp_fd(&p);
}
@@ -1521,6 +1518,9 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
shmems = xmalloc(SHMEMS_SIZE);
if (!shmems)
goto err;
+ pipes = xmalloc(PIPES_SIZE * sizeof(*pipes));
+ if (!pipes)
+ goto err;
list_for_each_entry(item, &pstree_list, list) {
if (dump_one_task(item))
@@ -1531,10 +1531,11 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
}
ret = cr_dump_shmem();
- xfree(shmems);
fd_id_show_tree();
err:
+ xfree(shmems);
+ xfree(pipes);
close_cr_fdset(&glob_fdset);
pstree_switch_state(&pstree_list, opts);
free_pstree(&pstree_list);
diff --git a/cr-show.c b/cr-show.c
index 6293be3..f7f8656 100644
--- a/cr-show.c
+++ b/cr-show.c
@@ -139,8 +139,8 @@ void show_pipes(int fd_pipes, struct cr_options *o)
ret = read_img_eof(fd_pipes, &e);
if (ret <= 0)
goto out;
- pr_msg("fd: %8x pipeid: %8x flags: %8x bytes: %8x\n",
- e.fd, e.pipeid, e.flags, e.bytes);
+ pr_msg("id: %8x pipeid: %8x flags: %8x bytes: %8x\n",
+ e.id, e.pipe_id, e.flags, e.bytes);
if (e.bytes)
lseek(fd_pipes, e.bytes, SEEK_CUR);
}
diff --git a/include/crtools.h b/include/crtools.h
index 5dc924a..8c494c2 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -24,7 +24,6 @@ enum {
CR_FD_PAGES,
CR_FD_CORE,
CR_FD_VMAS,
- CR_FD_PIPES,
CR_FD_SIGACT,
CR_FD_UNIXSK,
CR_FD_ITIMERS,
@@ -50,6 +49,7 @@ enum {
CR_FD_SK_QUEUES,
CR_FD_REG_FILES,
CR_FD_INETSK,
+ CR_FD_PIPES,
_CR_FD_GLOB_TO,
CR_FD_MAX
@@ -98,7 +98,7 @@ extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX];
#define FMT_FNAME_REG_FILES "reg-files.img"
#define FMT_FNAME_CORE "core-%d.img"
#define FMT_FNAME_VMAS "vmas-%d.img"
-#define FMT_FNAME_PIPES "pipes-%d.img"
+#define FMT_FNAME_PIPES "pipes.img"
#define FMT_FNAME_PSTREE "pstree.img"
#define FMT_FNAME_SIGACTS "sigacts-%d.img"
#define FMT_FNAME_UNIXSK "unixsk-%d.img"
diff --git a/include/image.h b/include/image.h
index a5a7066..ddd36f7 100644
--- a/include/image.h
+++ b/include/image.h
@@ -33,6 +33,7 @@
enum fd_types {
FDINFO_UND,
FDINFO_REG,
+ FDINFO_PIPE,
FDINFO_MAP,
FDINFO_INETSK,
FDINFO_CWD,
@@ -71,8 +72,8 @@ struct pstree_entry {
} __packed;
struct pipe_entry {
- u32 fd;
- u32 pipeid;
+ u32 id;
+ u32 pipe_id;
u32 flags;
u32 bytes;
u8 data[0];
--
1.7.1
More information about the CRIU
mailing list