[CRIU] [PATCH] unix: allow --external unix[ino]:stub[string]

Pavel Emelyanov xemul at virtuozzo.com
Tue Feb 28 07:26:11 PST 2017


On 02/28/2017 04:47 PM, Ruslan Kuprieiev wrote:
> Needles to say it's useful for debug, but it is also
> very useful when you syncronise checkpoint/restore
> whith a dumpee using unix socketpair and want it to
> painlessly receive notification on restore.
> 
> I.e. on dump, if --external unix[ino]:foo is specified,

Can you remind why it's a dump-time option, rather than the
restore-time one?

> criu will treat specified unix socket almost the same
> way it handles criu service socket. It will dump it as
> closed and will put "foo" string into images, to put
> that "foo" string into that socket on restore. This is
> almost identical to what criu does with service socket,
> but instead of putting a Criu_Resp message into it on
> restore, it puts an arbitrary string.
> 
> Signed-off-by: Ruslan Kuprieiev <rkuprieiev at cloudlinux.com>
> ---
>  criu/crtools.c          |  2 +-
>  criu/external.c         | 26 ++++++++++++++++++++++++++
>  criu/include/external.h |  1 +
>  criu/sk-unix.c          | 25 +++++++++++++++++++++++--
>  images/sk-unix.proto    |  1 +
>  5 files changed, 52 insertions(+), 3 deletions(-)
> 
> diff --git a/criu/crtools.c b/criu/crtools.c
> index ec02fe3..4bb3c69 100644
> --- a/criu/crtools.c
> +++ b/criu/crtools.c
> @@ -884,7 +884,7 @@ usage:
>  "                            tty[rdev:dev]\n"
>  "                            file[mnt_id:inode]\n"
>  "                            dev[major/minor]:NAME\n"
> -"                            unix[ino]\n"
> +"                            unix[ino]{:stub[string]}\n"
>  "                            mnt[MOUNTPOINT]:COOKIE\n"
>  "                            mnt[]{:AUTO_OPTIONS}\n"
>  "                        Formats of RES on restore:\n"
> diff --git a/criu/external.c b/criu/external.c
> index 96e6768..721102d 100644
> --- a/criu/external.c
> +++ b/criu/external.c
> @@ -73,6 +73,32 @@ char *external_lookup_by_key(char *key)
>  	return ERR_PTR(-ENOENT);
>  }
>  
> +char *external_lookup_stub_by_key(char *key)
> +{
> +	char *val, *stub, *end;
> +	char prefix[] = "stub[";
> +	char suffix = ']';
> +
> +	val = external_lookup_by_key(key);
> +	if (IS_ERR_OR_NULL(val))
> +		return val;
> +
> +	if (strncmp(val, prefix, strlen(prefix)))
> +		return ERR_PTR(-ENOENT);
> +
> +	val += strlen(prefix);
> +	stub = strdup(val);
> +
> +	end = strrchr(stub, suffix);
> +	if (!end) {
> +		free(stub);
> +		return ERR_PTR(-EINVAL);
> +	}
> +	*end = '\0';
> +
> +	return stub;
> +}
> +
>  int external_for_each_type(char *type, int (*cb)(struct external *, void *), void *arg)
>  {
>  	struct external *ext;
> diff --git a/criu/include/external.h b/criu/include/external.h
> index d284b79..08e04e4 100644
> --- a/criu/include/external.h
> +++ b/criu/include/external.h
> @@ -9,6 +9,7 @@ struct external {
>  extern int add_external(char *key);
>  extern bool external_lookup_id(char *id);
>  extern char *external_lookup_by_key(char *id);
> +extern char *external_lookup_stub_by_key(char *id);
>  extern void *external_lookup_data(char *id);
>  extern int external_for_each_type(char *type, int (*cb)(struct external *, void *), void *arg);
>  
> diff --git a/criu/sk-unix.c b/criu/sk-unix.c
> index a44d998..419c061 100644
> --- a/criu/sk-unix.c
> +++ b/criu/sk-unix.c
> @@ -263,6 +263,8 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
>  	SkOptsEntry *skopts;
>  	FilePermsEntry *perms;
>  	FownEntry *fown;
> +	char buf[PATH_MAX];
> +	char *stub = NULL;
>  
>  	ue = xmalloc(sizeof(UnixSkEntry) +
>  			sizeof(SkOptsEntry) +
> @@ -324,6 +326,18 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
>  		ue->uflags |= USK_SERVICE;
>  	}
>  
> +	/* Same as with service_sk, but for custom sockets */
> +	snprintf(buf, sizeof(buf), "unix[%u]", ue->ino);
> +	stub = external_lookup_stub_by_key(buf);
> +	if (unlikely(!IS_ERR_OR_NULL(stub))) {
> +		pr_info("Unix socket %#x is closed and plugged with stub '%s' "
> +			"for restore\n", ue->ino, stub);
> +		ue->state = TCP_CLOSE;
> +		ue->peer = 0;
> +		ue->uflags |= USK_SERVICE;
> +		ue->stub = (void *)stub;
> +	}
> +
>  	if (sk->namelen && *sk->name) {
>  		ue->file_perms = perms;
>  
> @@ -1165,8 +1179,15 @@ static int open_unixsk_standalone(struct unix_sk_info *ui, int *new_fd)
>  			return -1;
>  		}
>  
> -		if (send_criu_dump_resp(sks[1], true, true) == -1)
> -			return -1;
> +		if (ui->ue->stub) {
> +			pr_warn("Writing stub %s to unix socket %#x\n",
> +				(char *)ui->ue->stub, ui->ue->ino);
> +			if (write(sks[1], ui->ue->stub, strlen(ui->ue->stub)) != strlen(ui->ue->stub))
> +				return -1;
> +		} else {
> +			if (send_criu_dump_resp(sks[1], true, true) == -1)
> +				return -1;
> +		}
>  
>  		close(sks[1]);
>  		sk = sks[0];
> diff --git a/images/sk-unix.proto b/images/sk-unix.proto
> index d695070..a1ce8be 100644
> --- a/images/sk-unix.proto
> +++ b/images/sk-unix.proto
> @@ -50,4 +50,5 @@ message unix_sk_entry {
>  	optional bool			deleted		= 15;
>  
>  	optional uint32			ns_id		= 16;
> +	optional string			stub		= 17;
>  }
> 



More information about the CRIU mailing list