[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