[CRIU] [PATCH] mnt: add support for external shared mounts
Tycho Andersen
tycho.andersen at canonical.com
Fri Apr 3 07:18:00 PDT 2015
On Fri, Apr 03, 2015 at 02:44:23PM +0300, Pavel Emelyanov wrote:
> On 04/02/2015 11:22 PM, Tycho Andersen wrote:
> > Add support for external shared mounts via the --enable-external-masters flag.
> > This flag assumes that the mount is visible to criu via /proc/self/mountinfo
> > and that it will be present at the same location on restore. No attempt to dump
> > or restore the content is made; the external master is bind mounted into the
> > mount ns and whatever is there is what the container sees.
> >
> > Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
>
> Thanks :) Please, find my comments and questions inline.
>
> > ---
> > crtools.c | 6 +++
> > include/cr_options.h | 1 +
> > include/proc_parse.h | 1 +
> > mount.c | 115 +++++++++++++++++++++++++++++++++++++++++++++------
> > protobuf/mnt.proto | 2 +
> > 5 files changed, 112 insertions(+), 13 deletions(-)
> >
>
> > @@ -637,6 +641,8 @@ usage:
> > " --force-irmap force resolving names for inotify/fsnotify watches\n"
> > " -M|--ext-mount-map KEY:VALUE\n"
> > " add external mount mapping\n"
> > +" --enable-external-masters\n"
> > +" Allow mounts with external masters\n"
>
> Nitpick -- help text starts with small letter :)
>
> > " --manage-cgroups dump or restore cgroups the process is in\n"
> > " --cgroup-root [controller:]/newroot\n"
> > " change the root cgroup the controller will be\n"
>
> > diff --git a/mount.c b/mount.c
> > index 021c6e3..cbdad87 100644
> > --- a/mount.c
> > +++ b/mount.c
> > @@ -566,6 +566,9 @@ static struct mount_info *find_fsroot_mount_for(struct mount_info *bm)
> > return NULL;
> > }
> >
> > +struct mount_info *external_mounts = NULL;
>
> AFAIU the external_mounts is regular mounts list but collected for criu's
> mount namespace. We already have ns_id object for criu and it has the
> mnt.mntinfo_list/_tree fields. One thing is that in collect_mnt_namespaces()
> we don't collect criu's one when we dump container.
>
> Can fix the existing collection code to have the criu's ns_id collected
> in case the --enable-external-masters is specified?
>
> > +static int try_resolve_external_sharing(struct mount_info *m);
> > +
> > static int validate_mounts(struct mount_info *info, bool for_dump)
> > {
> > struct mount_info *m, *t;
> > @@ -578,6 +581,11 @@ static int validate_mounts(struct mount_info *info, bool for_dump)
> > if (m->shared_id && validate_shared(m))
> > return -1;
> >
> > + if (m->master_id && opts.enable_external_masters) {
> > + if (try_resolve_external_sharing(m) == 0)
>
> Shouldn't this be in collect_shared()? Validation is just checking that
> the tree is in dumpable state, while any interconnections are be set in
> other places.
>
> > + continue;
> > + }
> > +
> > /*
> > * Mountpoint can point to / of an FS. In that case this FS
> > * should be of some known type so that we can just mount one.
>
> > @@ -676,10 +685,28 @@ static int collect_shared(struct mount_info *info)
> > }
> >
> > if (need_master && m->parent) {
> > - pr_err("Mount %d (master_id: %d shared_id: %d) "
> > - "has unreachable sharing\n", m->mnt_id,
> > - m->master_id, m->shared_id);
> > - return -1;
> > + if (opts.enable_external_masters) {
> > + struct mount_info *pm;
> > + bool found = false;
> > +
> > + for (pm = external_mounts; pm->next != NULL; pm = pm->next) {
> > + if (pm->shared_id == m->master_id) {
> > + found = true;
> > + break;
> > + }
>
> I mean this place -- once we foung shared_id == master_id we do the body
> of try_resolve_external_mount().
>
> > + }
> > +
> > + if (!found) {
> > + pr_err("couldn't find sharing for %d "
> > + "(master_id: %d shared_id: %d)",
> > + m->mnt_id, m->master_id, m->shared_id);
> > + }
> > + } else {
> > + pr_err("Mount %d (master_id: %d shared_id: %d) "
> > + "has unreachable sharing. Try --enable-external-masters.\n", m->mnt_id,
> > + m->master_id, m->shared_id);
> > + return -1;
> > + }
> > }
> >
> > /* Search bind-mounts */
>
> > @@ -1302,7 +1335,7 @@ again:
> > if (!progress) {
> > struct mount_info *m;
> >
> > - pr_err("A few mount points can't be mounted");
> > + pr_err("A few mount points can't be mounted\n");
>
> I'd appreciate fixes and cleanups to be sent separately :)
>
> > list_for_each_entry(m, &postpone2, postpone) {
> > pr_err("%d:%d %s %s %s\n", m->mnt_id,
> > m->parent_mnt_id, m->root,
> > @@ -1475,17 +1508,19 @@ static int do_new_mount(struct mount_info *mi)
> > return -1;
> >
> > if (mount(src, mi->mountpoint, tp->name,
> > - mi->flags & (~MS_SHARED), mi->options) < 0) {
> > + mi->flags & ~(MS_SLAVE | MS_SHARED), mi->options) < 0) {
>
> What if mountpoint is not slave? Doesn't this hunk break the existing restore?
If the mount point is not a slave I think this hunk should have no
effect (here we're just masking off the bits to restore MS_SLAVE
later). Without masking of MS_SLAVE, mount(2) was giving me an error
(EINVAL, I think).
The rest of the changes are good, I will make them and re-send once we
resolve this.
Tycho
> > pr_perror("Can't mount at %s", mi->mountpoint);
> > return -1;
> > }
> >
> > - if (restore_shared_options(mi, 0, mi->shared_id, 0))
> > + if (restore_shared_options(mi, 0, mi->shared_id, mi->flags & MS_SLAVE || mi->external_master))
> > return -1;
> >
> > mi->mounted = true;
> >
> > - if (tp->restore && tp->restore(mi))
> > + // If there is an external master, the content of the mount comes from
> > + // there; otherwise, we restore it as usual.
>
> We try to follow kernel coding style which encourages usage of /**/-style
> comments. Please :)
>
> > + if (!mi->external_master && tp->restore && tp->restore(mi))
> > return -1;
> >
> > return 0;
>
> -- Pavel
More information about the CRIU
mailing list