[CRIU] [RFC PATCH 2/5] autofs: dump stage introduced

Pavel Emelyanov xemul at parallels.com
Mon Nov 23 11:21:39 PST 2015


On 11/23/2015 08:22 PM, Stanislav Kinsburskiy wrote:
> Autofs doesn't need any special dump tricks.
> However, we don't want to dump it, if controlling pipe is not empty, because
> it means, that kernel has some state, which we don't want to carry with us.
> 
> We also need to update mount options, because "pgrp=" option content is pid
> namespace dependant. There are two ways how to do so:
> 1) Clone a process in desired pid namespace and collect mounts within it or
> 2) Replace AutoFS real prgp with container's one on dump.
> 
> This patch implements the second.
> 
> Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
> ---
>  mount.c |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 144 insertions(+)
> 
> diff --git a/mount.c b/mount.c
> index 562d6ca..c07d2d1 100644
> --- a/mount.c
> +++ b/mount.c
> @@ -1383,6 +1383,145 @@ static int always_fail(struct mount_info *pm)
>  	return -1;
>  }
>  
> +/*
> + * AutoFS options have to be fixed:
> + * - "timeout" have to be removed

Why?

> + * - "pgrp" have to be updated to virtual pid value
> + */
> +static int autofs_fixup_options(struct mount_info *new)
> +{
> +	char **options;
> +	int nr_opts, i, err = -1;
> +
> +	split(new->options, ',', &options, &nr_opts);
> +	if (!options)
> +		return -1;
> +
> +	xfree(new->options);
> +	new->options = xzalloc(1);
> +	if (!new->options)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < nr_opts; i++) {
> +		char *opt = options[i];
> +
> +		if (!strncmp(opt, "timeout=", strlen("timeout=")))
> +			continue;
> +		if (!strncmp(opt, "pgrp=", strlen("pgrp="))) {
> +			int real_pid, virt_pid = -1;
> +			struct pstree_item *item;
> +
> +			if (sscanf(opt, "pgrp=%d", &real_pid) != 1) {
> +				pr_err("Failed to get pgrp: %s\n", opt);
> +				goto out;
> +			}
> +
> +			for_each_pstree_item(item) {
> +				if (item->pid.real == real_pid) {
> +					virt_pid = item->pid.virt;
> +					break;
> +				}
> +			}

We have pid_in_pstree() helper doing almost the same. Plz, fix one to
return either item with matching pid, or vpid itself.

> +			pr_info("real pid: %d, virt pid: %d\n", real_pid, virt_pid);
> +
> +			if (virt_pid == -1) {
> +				pr_err("Failed to find process entry %d\n",
> +						real_pid);
> +				goto out;
> +			}
> +
> +			/* This should be enough: "pgrp=" + pid */
> +			opt = xrealloc(opt, 32);
> +			if (!opt)
> +				goto out;
> +
> +			if (snprintf(opt, 32, "pgrp=%d", virt_pid) == 32)

Comment above says it should be enough space in opt variable.

> +				return -1;
> +
> +			options[i] = opt;
> +		}
> +
> +		if (attach_option(new, opt))
> +			goto out;
> +	}
> +
> +	err = 0;
> +out:
> +	for (i = 0; i < nr_opts; i++)
> +		xfree(options[i]);
> +	xfree(options);
> +	return err;
> +}
> +
> +static int autofs_dump(struct mount_info *pm)
> +{
> +	unsigned pgrp, fd;
> +	int pipe_fd, pipe_size, steal_pipe[2];
> +	ssize_t bytes;
> +	int err;
> +
> +	/* TODO: we are called wthin proper pid namespace. We can't use blobal
> +	 * proc and have to mount proc somewhere */

What does this comment mean?

> +
> +	pr_info("autofs mount options: %s\n", pm->options);
> +	if (sscanf(pm->options, "fd=%d,pgrp=%d%*s", &fd, &pgrp) != 2) {
> +		pr_err("Unsupported autofs mount options: %s\n", pm->options);
> +		return -EINVAL;
> +	}
> +
> +	pr_info("automount: pgrp: %d, fd: %d\n", pgrp, fd);
> +
> +	pipe_fd = open_proc(pgrp, "fd/%d", fd);
> +	if (pipe_fd < 0) {
> +		pr_perror("Can't open automount pipe\n");
> +		return pipe_fd;
> +	}
> +
> +	pipe_size = fcntl(pipe_fd, F_GETPIPE_SZ);
> +	if (pipe_size < 0) {
> +		err = -errno;
> +		pr_perror("Can't obtain piped data size\n");
> +		goto close_pipe;
> +	}
> +
> +	if (pipe(steal_pipe) < 0) {
> +		err = -errno;
> +		pr_perror("Can't create pipe for stealing data");
> +		goto close_pipe;
> +	}
> +
> +	bytes = tee(pipe_fd, steal_pipe[1], pipe_size, SPLICE_F_NONBLOCK);
> +	if (bytes < 0) {
> +		if (errno != EAGAIN) {
> +			err = -errno;
> +			pr_perror("Can't pick pipe data");
> +			goto close_steal;
> +		}
> +
> +		bytes = 0;
> +	}
> +
> +	if (bytes) {
> +		err = -ENOTSUP;
> +		pr_perror("Can't dump autofs mount, when autmount pipe is not empty\n");
> +		goto close_steal;
> +	}

There's an fd_fas_data() helper out there. Does it work for this case?

> +
> +	err = autofs_fixup_options(pm);
> +	if (err)
> +		goto close_steal;
> +
> +	err = 0;
> +
> +close_steal:
> +	close(steal_pipe[0]);
> +	close(steal_pipe[1]);
> +close_pipe:
> +	close(pipe_fd);
> +	return err;
> +}
> +
>  static struct fstype fstypes[32] = {
>  	{
>  		.name = "unsupported",
> @@ -1451,6 +1590,11 @@ static struct fstype fstypes[32] = {
>  		.name = "overlay",
>  		.code = FSTYPE__OVERLAYFS,
>  		.parse = overlayfs_parse,
> +	}, {
> +		.name = "autofs",
> +		.code = FSTYPE__AUTOFS,
> +		.dump = autofs_dump,
> +		.restore = always_fail,
>  	},
>  };
>  
> 
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
> .
> 



More information about the CRIU mailing list