[CRIU] [PATCH 11/28] rst: new routines for restoring shared files introduced

Kinsbursky Stanislav skinsbursky at openvz.org
Thu Mar 22 13:58:45 EDT 2012


From: Stanislav Kinsbursky <skinsbursky at openvz.org>

These are slighlty reqirtten currently existent routines. Old ones will be
removed later (simple replacement leads to unreadable patch).

Refresh of diff-rst-files-undump
---
 files.c |  200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 200 insertions(+), 0 deletions(-)
-------------- next part --------------
diff --git a/files.c b/files.c
index 6c14781..feff47b 100644
--- a/files.c
+++ b/files.c
@@ -59,6 +59,15 @@ static struct fdinfo_desc *find_fd(u64 id)
 	return NULL;
 }
 
+struct file_recipient {
+	struct list_head	list;
+	int			pid;
+	int			fd;
+	struct sockaddr_un	saddr;
+	int			sun_len;
+	u32			ready;
+};
+
 static int get_file_path(char *path, struct fdinfo_entry *fe, int fd)
 {
 	if (read(fd, path, fe->len) != fe->len) {
@@ -71,6 +80,34 @@ static int get_file_path(char *path, struct fdinfo_entry *fe, int fd)
 	return 0;
 }
 
+static int collect_fd_pid(int pid, struct fd_entry *fde)
+{
+	struct file_info *fi;
+	struct file_recipient *recipient;
+
+	pr_info("%d: Collect fd=%d type=%d id=%16lx\n",
+		pid, fde->fd, fde->type, fde->id);
+
+	fi = file_search(fde->type, fde->id);
+	if (fi == NULL) {
+		pr_err("Failed to find shared file: type %d, id %ld\n\n", fde->type, fde->id);
+		return -1;
+	}
+
+	recipient = xmalloc_shm(sizeof(*recipient));
+	if (!recipient)
+		return -ENOMEM;
+	recipient->pid	= pid;
+	recipient->fd	= fde->fd;
+	cr_wait_init(&recipient->ready);
+
+	if (fi->pid < pid)
+		fi->pid = pid;
+
+	list_add_tail(&recipient->list, &fi->recipients);
+	return 0;
+}
+
 static int collect_fd(int pid, struct fdinfo_entry *e)
 {
 	int i;
@@ -128,6 +165,17 @@ static int collect_fd(int pid, struct fdinfo_entry *e)
 	return 0;
 }
 
+static struct file_recipient *get_fd_recipient(struct file_info *fi,
+					       int pid, int fd)
+{
+	struct file_recipient *recipient = NULL;
+
+	list_for_each_entry(recipient, &fi->recipients, list)
+		if ((recipient->pid == pid) && (recipient->fd == fd))
+			return recipient;
+	return NULL;
+}
+
 static int prepare_reg_files(void)
 {
 	int reg_file_fd, ret = 0;
@@ -270,6 +318,25 @@ static int restore_exe_early(struct fdinfo_entry *fe, int fd)
 	return 0;
 }
 
+static int receive_shared_fd(int pid, struct file_info *fi, struct fd_entry *fde)
+{
+	int real_fd;
+
+	if (fi->pid == pid)
+		return 0;
+
+	pr_info("\t%d: Receive fd %d\n", pid, fde->fd);
+
+	real_fd = recv_fd(fde->fd);
+	if (real_fd < 0) {
+		pr_err("Can't get fd %d\n", real_fd);
+		return -1;
+	}
+	close(fde->fd);
+
+	return reopen_fd_as(fde->fd, real_fd);
+}
+
 struct fdinfo_list_entry *find_fdinfo_list_entry(int pid, int fd, struct fdinfo_desc *fi)
 {
 	struct fdinfo_list_entry *fle;
@@ -330,6 +397,139 @@ static int open_transport_fd(int pid, struct fdinfo_entry *fe,
 	return 0;
 }
 
+static int open_transport(int pid, int fd, struct file_info *fi)
+{
+	struct file_recipient *recipient;
+	struct sockaddr_un *saddr;
+	int ret;
+	int sock;
+
+	recipient = get_fd_recipient(fi, pid, fd);
+	if (!recipient) {
+		pr_err("Can't find recipient\n");
+		return -1;
+	}
+
+	pr_info("\t%d: Found recipient: %p\n", pid, recipient);
+
+	saddr = &recipient->saddr;
+	saddr->sun_family = AF_UNIX;
+	snprintf(saddr->sun_path, UNIX_PATH_MAX,
+		 "X/crtools-%d-fd-%d", pid, fd);
+
+	recipient->sun_len = SUN_LEN(saddr);
+	*saddr->sun_path = '\0';
+
+	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+	if (sock < 0) {
+		pr_perror("Can't create socket");
+		return -1;
+	}
+
+	ret = bind(sock, saddr, recipient->sun_len);
+	if (ret < 0) {
+		pr_perror("Can't bind unix socket %s", saddr->sun_path + 1);
+		return -1;
+	}
+
+	ret = reopen_fd_as(recipient->fd, sock);
+	if (ret < 0)
+		return -1;
+
+	cr_wait_set(&recipient->ready, pid);
+	pr_info("\t%d: Transport for fd %d ready (fi: %p, recipient: %p)\n",
+		pid, fd, fi, recipient);
+	return 0;
+}
+
+static int send_fd_to_recipients(struct file_info *fi)
+{
+	struct file_recipient *recipient, *tmp;
+	int sock;
+
+	if (list_empty(&fi->recipients))
+		return 0;
+
+	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+	if (sock < 0) {
+		pr_perror("Can't create socket");
+		return -1;
+	}
+
+	pr_info("\t%d: Send fd %d\n", fi->pid, fi->fd);
+
+	list_for_each_entry_safe(recipient, tmp, &fi->recipients, list) {
+		if (recipient->pid == fi->pid)
+			continue;
+		pr_info("\t%d: Wait pid's %d fd %d ready\n",
+			fi->pid, recipient->pid, recipient->fd);
+		cr_wait_while(&recipient->ready, 0);
+		pr_info("\t%d: Send to %s (fi: %p, recipient: %p)\n",
+			fi->pid, recipient->saddr.sun_path + 1, fi, recipient);
+		if (send_fd(sock, &recipient->saddr, recipient->sun_len, fi->fd) < 0) {
+			pr_perror("Can't send file descriptor");
+			return -1;
+		}
+	}
+	close(sock);
+	return 0;
+}
+
+static int open_reg_file(struct file_info *fi, struct fd_entry *fde)
+{
+	const struct file_entry *rfe = fi->rfe;
+
+	pr_info("\t%d: Open fd %d (%s)\n", fi->pid, fde->fd, (char *)rfe->name);
+
+	if (fi->fd != FD_ID_INVALID) {
+		if (dup2(fi->fd, fde->fd) != fde->fd)
+			return -1;
+		return 0;
+	}
+
+	fi->fd = open((char *)rfe->name, rfe->flags);
+	if (fi->fd < 0) {
+		pr_perror("Can't open file %s", rfe->name);
+		return -1;
+	}
+	lseek(fi->fd, rfe->pos, SEEK_SET);
+
+	if (reopen_fd_as(fde->fd, fi->fd) < 0)
+		return -1;
+
+	fi->fd = fde->fd;
+
+	return send_fd_to_recipients(fi);
+}
+
+static int open_fd_and_send(int pid, struct file_info *fi, struct fd_entry *fde)
+{
+	if (fi->pid != pid)
+		return 0;
+
+	switch (fde->type) {
+		case FDINFO_REG:
+			return open_reg_file(fi, fde);
+	}
+
+	pr_err("Failed to find shared file: type %d is not supported\n\n", fde->type);
+	return -1;
+}
+
+static int open_fd_transport(int pid, struct file_info *fi, struct fd_entry *fde)
+{
+	if (fi->pid == pid)
+		return 0;
+
+	if (fde->type != FDINFO_REG)
+		return 0;
+
+	pr_info("\t%d: Create transport for fd %d type %d id %ld\n", pid,
+			fde->fd, fde->type, fde->id);
+
+	return open_transport(pid, fde->fd, fi);
+}
+
 static int open_fd(int pid, struct fdinfo_entry *fe,
 				struct fdinfo_desc *fi, int fdinfo_fd)
 {


More information about the CRIU mailing list