[CRIU] Re: [PATCH 2/4] sockets: Restore unconnected dgram sockets

Pavel Emelyanov xemul at parallels.com
Mon Apr 16 02:07:41 EDT 2012


> @@ -478,6 +481,7 @@ usage:
>  	pr_msg("  -s             leave tasks in stopped state after checkpoint instead of killing them\n");
>  	pr_msg("  -n             checkpoint/restore namespaces - values must be separated by comma\n");
>  	pr_msg("                 supported: uts, ipc\n");
> +	pr_msg("  -r             resolve unconnected socket peer connection by name\n");

I'd make the option meaning "allow external unix connections".

>  
>  	pr_msg("\nAdditional common parameters:\n");
>  	pr_msg("  -D dir         specifis directory where checkpoint files are/to be located\n");
> diff --git a/include/crtools.h b/include/crtools.h
> index d79878f..764cfe1 100644
> --- a/include/crtools.h
> +++ b/include/crtools.h
> @@ -67,6 +67,7 @@ struct cr_options {
>  	bool			leader_only;
>  	bool			show_pages_content;
>  	bool			restore_detach;
> +	bool			resolve_peer_by_name;
>  	unsigned int		namespaces_flags;
>  };
>  
> @@ -160,6 +161,7 @@ static inline int fdset_fd(const struct cr_fdset *fdset, int type)
>  }
>  
>  extern struct cr_fdset *glob_fdset;
> +extern struct cr_options opts;
>  
>  int cr_dump_tasks(pid_t pid, const struct cr_options *opts);
>  int cr_restore_tasks(pid_t pid, struct cr_options *opts);
> diff --git a/sockets.c b/sockets.c
> index 4428eae..09756e9 100644
> --- a/sockets.c
> +++ b/sockets.c
> @@ -38,6 +38,8 @@ static char buf[4096];
>  #define SOCKFS_MAGIC	0x534F434B
>  #endif
>  
> +#define SOCK_STATE_INFO	255
> +
>  struct socket_desc {
>  	unsigned int		family;
>  	unsigned int		ino;
> @@ -412,10 +414,32 @@ static int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
>  		 * Peer should have us as peer or have a name by which
>  		 * we can access one.
>  		 */
> -		if (!peer->name && (peer->peer_ino != ue.id)) {
> -			pr_err("Unix socket %x with unreachable peer %x (%x/%s)\n",
> -					ue.id, ue.peer, peer->peer_ino, peer->name);
> -			goto err;
> +		if (peer->peer_ino != ue.id) {
> +			if (!peer->name) {
> +				pr_err("Unix socket %x with unreachable peer %x (%x/%s)\n",
> +				       ue.id, ue.peer, peer->peer_ino, peer->name);
> +				goto err;
> +			}
> +
> +			struct unix_sk_entry pt = { };
> +
> +			/*
> +			 * Socket is not connected back but have a name,
> +			 * so at restore time we will find it here. Note
> +			 * the id is set to impossible value by purpose.
> +			 */
> +
> +			pt.id		= -1u;

This is wrong. You can have two or more sockets in the "image" to be connected
to this "external" one. E.g. two daemons connected to /dev/log

> +			pt.peer		= ue.id;
> +			pt.type		= SOCK_DGRAM;
> +			pt.state	= SOCK_STATE_INFO;
> +			pt.namelen	= peer->namelen;
> +
> +			if (write_img(fdset_fd(glob_fdset, CR_FD_UNIXSK), &pt))
> +				goto err;
> +			if (write_img_buf(fdset_fd(glob_fdset, CR_FD_UNIXSK),
> +					  peer->name, pt.namelen))
> +				goto err;
>  		}
>  	} else if (ue.state == TCP_ESTABLISHED) {
>  		const struct unix_sk_listen_icon *e;
> @@ -814,6 +838,7 @@ struct unix_sk_info {
>  #define USK_PAIR_SLAVE		0x2
>  
>  static LIST_HEAD(unix_sockets);
> +static LIST_HEAD(unix_sockets_peer_names);

I don't see much profit in having separate list for external sockets.
The existing infrastructure just allows for adding them in the common
trunk.

>  
>  static struct unix_sk_info *find_unix_sk(int id)
>  {
> @@ -825,6 +850,18 @@ static struct unix_sk_info *find_unix_sk(int id)
>  	return NULL;
>  }
>  
> +static struct unix_sk_info *find_peer_name_sk(int id)
> +{
> +	struct unix_sk_info *info;
> +
> +	list_for_each_entry(info, &unix_sockets_peer_names, list) {
> +		if (info->ue.id == id)
> +			return info;
> +	}
> +
> +	return NULL;
> +}
> +
>  struct sk_packet {
>  	struct list_head list;
>  	struct sk_packet_entry entry;
> @@ -1076,6 +1113,8 @@ static inline char *skstate2s(u32 state)
>  		return "closed";
>  	else if (state == TCP_LISTEN)
>  		return "listen";
> +	else if (state == SOCK_STATE_INFO)
> +		return "  info";

As described above -- external.

>  	else
>  		return unknown(state);
>  }
> @@ -1461,6 +1500,13 @@ int collect_unix_sockets(void)
>  
>  		ui->peer = NULL;
>  		ui->flags = 0;
> +
> +		if (ui->ue.state == SOCK_STATE_INFO) {
> +			pr_info(" `- Got peer name for %u\n", ui->ue.id);
> +			list_add(&ui->list, &unix_sockets_peer_names);
> +			continue;
> +		}
> +
>  		pr_info(" `- Got %u peer %u\n", ui->ue.id, ui->ue.peer);
>  		file_desc_add(&ui->d, FDINFO_UNIXSK, ui->ue.id,
>  				&unix_desc_ops);
> @@ -1485,9 +1531,13 @@ int resolve_unix_peers(void)
>  
>  		peer = find_unix_sk(ui->ue.peer);
>  		if (!peer) {
> -			pr_err("FATAL: Peer %x unresolved for %x\n",
> -					ui->ue.peer, ui->ue.id);
> -			return -1;
> +			if (opts.resolve_peer_by_name)
> +				peer = find_peer_name_sk(ui->ue.peer);
> +			if (!peer) {
> +				pr_err("FATAL: Peer %x unresolved for %x\n",
> +				       ui->ue.peer, ui->ue.id);
> +				return -1;
> +			}
>  		}
>  
>  		ui->peer = peer;



More information about the CRIU mailing list