[CRIU] [PATCH 3/4] sk-unix: Handle bindmounted dgram sockets on restore

Andrei Vagin avagin at gmail.com
Thu Aug 10 02:42:15 MSK 2017


On Tue, Aug 08, 2017 at 02:25:09PM +0300, Cyrill Gorcunov wrote:
> If a socket is bindmounted one we open it early (thus mount engine
> will be eable to proceed), put it into fdstore and then simply fetch
> it from there.
> 
> Note it's important that only basic scenario with dgram/closed sockets
> is supported by now: established, listening sockets requires a way
> more code change and we will do it only when really needed.
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
>  criu/include/sockets.h |  2 ++
>  criu/mount.c           |  7 +++++++
>  criu/sk-unix.c         | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 62 insertions(+)
> 
> diff --git a/criu/include/sockets.h b/criu/include/sockets.h
> index 64673c5e5dc8..3d4669859182 100644
> --- a/criu/include/sockets.h
> +++ b/criu/include/sockets.h
> @@ -8,6 +8,7 @@
>  
>  struct fdinfo_list_entry;
>  struct sk_opts_entry;
> +struct mount_info;
>  struct file_desc;
>  struct fd_parms;
>  struct cr_imgset;
> @@ -38,6 +39,7 @@ extern struct collect_image_info inet_sk_cinfo;
>  extern struct collect_image_info unix_sk_cinfo;
>  extern int fix_external_unix_sockets(void);
>  extern int collect_unix_bindmounts(void);
> +extern int unix_prepare_bindmount(struct mount_info *mi);
>  
>  extern struct collect_image_info netlink_sk_cinfo;
>  
> diff --git a/criu/mount.c b/criu/mount.c
> index 59fd17870db8..174cc4639209 100644
> --- a/criu/mount.c
> +++ b/criu/mount.c
> @@ -27,6 +27,7 @@
>  #include "files-reg.h"
>  #include "external.h"
>  #include "fdstore.h"
> +#include "sockets.h"
>  
>  #include "images/mnt.pb-c.h"
>  
> @@ -2042,6 +2043,12 @@ static int do_bind_mount(struct mount_info *mi)
>  		}
>  	}
>  
> +	if (unix_prepare_bindmount(mi)) {

Why do we call this function for all mounts?

> +		pr_err("Failed to prepare bindmount on unix at %s\n",
> +		       mi->mountpoint);
> +		goto err;
> +	}
> +
>  	if (mount(root, mi->mountpoint, NULL, MS_BIND | (mi->flags & MS_REC), NULL) < 0) {
>  		pr_perror("Can't mount at %s", mi->mountpoint);
>  		goto err;
> diff --git a/criu/sk-unix.c b/criu/sk-unix.c
> index bf013c5ca4de..adc6d58aa173 100644
> --- a/criu/sk-unix.c
> +++ b/criu/sk-unix.c
> @@ -867,6 +867,7 @@ struct unix_sk_info {
>  	struct file_desc d;
>  	struct list_head connected; /* List of sockets, connected to me */
>  	struct list_head node; /* To link in peer's connected list  */
> +	int fdstore_id;
>  
>  	/*
>  	 * For DGRAM sockets with queues, we should only restore the queue
> @@ -1241,6 +1242,12 @@ static int open_unixsk_standalone(struct unix_sk_info *ui, int *new_fd)
>  	pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
>  			ui->ue->id, ui->ue->ino, ui->ue->peer);
>  
> +	if (ui->fdstore_id >= 0) {
> +		pr_debug("\tObtaining from fdstore id %#x\n", ui->fdstore_id);
> +		*new_fd = fdstore_get(ui->fdstore_id);
> +		return 0;
> +	}
> +
>  	if (set_netns(ui->ue->ns_id))
>  		return -1;
>  
> @@ -1453,6 +1460,9 @@ static void unlink_stale(struct unix_sk_info *ui)
>  {
>  	int ret, cwd_fd = -1, root_fd = -1;
>  
> +	if (ui->fdstore_id >= 0)
> +		return;
> +
>  	if (ui->name[0] == '\0' || (ui->ue->uflags & USK_EXTERN))
>  		return;
>  
> @@ -1509,6 +1519,7 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i)
>  	INIT_LIST_HEAD(&ui->connected);
>  	INIT_LIST_HEAD(&ui->node);
>  	ui->flags = 0;
> +	ui->fdstore_id = -1;
>  	fixup_sock_net_ns_id(&ui->ue->ns_id, &ui->ue->has_ns_id);
>  
>  	uname = ui->name;
> @@ -1553,6 +1564,48 @@ struct collect_image_info unix_sk_cinfo = {
>  	.flags = COLLECT_SHARED,
>  };
>  
> +int unix_prepare_bindmount(struct mount_info *mi)
> +{
> +	char name_dir[PATH_MAX], ns_root[PATH_MAX];
> +	struct unix_sk_info *ui, *t = NULL;
> +	char *old_name_dir = NULL;
> +	int ret, sk;
> +
> +	list_for_each_entry(ui, &unix_sockets, list) {
> +		if (!ui->ue->has_mnt_id || ui->ue->mnt_id != mi->mnt_id)

I don't like an idea to run this loop for each mount
> +			continue;
> +		t = ui;
> +		break;
> +	}
> +
> +	if (!t)
> +		return 0;
> +
> +	print_ns_root(mi->nsid, 0, ns_root, sizeof(ns_root));
> +	if (ui->name_dir) {
> +		old_name_dir = ui->name_dir;
> +		snprintf(name_dir, sizeof(name_dir), "%s/%s", ns_root, ui->name_dir);
> +		ui->name_dir = name_dir;
> +	}
> +
> +	ret = open_unixsk_standalone(ui, &sk);
> +	if (ui->name_dir)
> +		ui->name_dir = old_name_dir;
> +	BUG_ON(ret > 0);
> +
> +	if (ret)
> +		return -1;
> +
> +	ui->fdstore_id = fdstore_add(sk);
> +	if (ui->fdstore_id < 0)
> +		return -1;
> +	close(sk);
> +
> +	pr_debug("Standalone socket moved into fdstore (id %#x ino %#x peer %#x)\n",
> +		 ui->ue->id, ui->ue->ino, ui->ue->peer);
> +	return 0;
> +}
> +
>  static void set_peer(struct unix_sk_info *ui, struct unix_sk_info *peer)
>  {
>  	ui->peer = peer;
> -- 
> 2.7.5
> 
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu


More information about the CRIU mailing list