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

Andrew Vagin avagin at parallels.com
Fri Mar 23 03:36:02 EDT 2012


On Thu, Mar 22, 2012 at 08:58:45PM +0300, Kinsbursky Stanislav wrote:
> From: Stanislav Kinsbursky <skinsbursky at openvz.org>
> 
> These are slighlty reqirtten currently existent routines.
Why do we need new routines? What has been changed?

> Old ones will be
> removed later (simple replacement leads to unreadable patch).
I think you should split patched by another way

> 
> Refresh of diff-rst-files-undump
> ---
>  files.c |  200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 200 insertions(+), 0 deletions(-)

> 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)
>  {

> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://openvz.org/mailman/listinfo/criu



More information about the CRIU mailing list