[CRIU] [PATCH cr 11/11] pipe: restore pipe data

Andrey Vagin avagin at openvz.org
Thu Apr 5 12:02:15 EDT 2012


Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 pipes.c |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/pipes.c b/pipes.c
index ecac8a3..d46166a 100644
--- a/pipes.c
+++ b/pipes.c
@@ -21,6 +21,8 @@ struct pipe_info {
 	struct list_head list;		/* list head for fdinfo_list_entry-s */
 	struct list_head fd_head;
 	int create;
+	int bytes;
+	off_t off;
 };
 
 static LIST_HEAD(pipes);
@@ -64,8 +66,6 @@ int collect_pipes(void)
 		if (ret <= 0)
 			break;
 
-		lseek(fd, pi->pe.bytes, SEEK_CUR);
-
 		pr_info("Collected pipe entry ID %x PIPE ID %x\n",
 					pi->pe.id, pi->pe.pipe_id);
 		INIT_LIST_HEAD(&pi->fd_head);
@@ -116,6 +116,43 @@ static void show_saved_pipe_fds(struct pipe_info *pi)
 		pr_info("   `- FD %d pid %d\n", fle->fd, fle->pid);
 }
 
+static int handle_pipes_data()
+{
+	int fd, ret;
+
+	fd = open_image_ro(CR_FD_PIPES_DATA);
+	if (fd < 0)
+		return -1;
+
+	while (1) {
+		struct pipe_info *pi;
+		struct pipe_data_entry pde;
+
+		ret = read_img_eof(fd, &pde);
+		if (ret < 0)
+			goto err;
+
+		if (ret == 0)
+			break;
+
+		list_for_each_entry(pi, &pipes, list) {
+			if (pi->pe.pipe_id != pde.pipe_id)
+				continue;
+			if (!pi->create)
+				continue;
+
+			pi->off = lseek(fd, 0, SEEK_CUR) + pde.off;
+			pi->bytes = pde.bytes;
+
+			lseek(fd, pde.bytes + pde.off, SEEK_CUR);
+			break;
+		}
+	}
+err:
+	close(fd);
+	return ret;
+}
+
 /* Choose who will restore a pipe. */
 void mark_pipe_master()
 {
@@ -162,6 +199,8 @@ void mark_pipe_master()
 	}
 
 	list_splice(&head, &pipes);
+
+	handle_pipes_data();
 }
 
 int pipe_should_open_transport(struct fdinfo_entry *fe,
@@ -211,6 +250,41 @@ static int set_fd_flags(int fd, int flags)
 	return fcntl(fd, F_SETFL, flags);
 }
 
+static int restore_pipe_data(int pfd, struct pipe_info *pi)
+{
+	int fd, size = 0, ret;
+
+	fd = open_image_ro(CR_FD_PIPES_DATA);
+	if (fd < 0)
+		return -1;
+
+	lseek(fd, pi->off, SEEK_SET);
+
+	pr_info("\t\tSplicing data size=%d off=%ld\n", pi->bytes, pi->off);
+
+	while (size != pi->bytes) {
+		ret = splice(fd, NULL, pfd, NULL, pi->bytes - size, 0);
+		if (ret < 0) {
+			pr_perror("%x: Error splicing data", pi->pe.id);
+			goto err;
+		}
+
+		if (ret == 0) {
+			pr_err("%x: Wanted to restore %d bytes, but got %d\n",
+				pi->pe.id, pi->bytes, size);
+			ret = -1;
+			goto err;
+		}
+
+		size += ret;
+	}
+
+	ret = 0;
+err:
+	close(fd);
+	return ret;
+}
+
 int open_pipe(struct list_head *l)
 {
 	unsigned long time = 1000;
@@ -232,6 +306,8 @@ int open_pipe(struct list_head *l)
 		return -1;
 	}
 
+	ret = restore_pipe_data(pfd[1], pi);
+
 	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 	if (sock < 0) {
 		pr_perror("Can't create socket");
-- 
1.7.1



More information about the CRIU mailing list