[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