[CRIU] [RFC PATCH 2/5] autofs: dump stage introduced
Stanislav Kinsburskiу
skinsbursky at odin.com
Mon Nov 23 12:33:26 PST 2015
23 нояб. 2015 г. 20:21 пользователь Pavel Emelyanov <xemul at parallels.com> написал:
>
> 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?
>
This restriction comes from kernel. Timeout as an option is not accepted.
It has to be set via ioctl.
> > + * - "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.
>
Sure.
> > + 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.
>
Yes. It's just a check to make sure, that we are crossing the limit.
> > + 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?
>
It's an artefact. Sorry, I'll remove it.
> > +
> > + 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?
>
I'll check it.
> > +
> > + 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