[CRIU] [PATCH 2/2 v4] fsnotify: Always provide the path for inotify watchees
Cyrill Gorcunov
gorcunov at gmail.com
Mon Oct 19 03:29:51 PDT 2015
On Mon, Oct 19, 2015 at 01:23:21PM +0300, Pavel Emelyanov wrote:
> >
> > Yeah, exactly!
>
> OK. Can we then split common path from tmpfs-path then? Like -- do regular
> open_handle(), then (if opened) get the fstype and IFF it's tmpfs go on a
> loop to find the accessible path?
>
> Another issue I've found while re-reading the patch:
>
> > + openable_fd = openat(mntfd, __path, O_PATH);
> > + if (openable_fd >= 0) {
> > + close(openable_fd);
> > +
> > + pr_debug("\t\t\topenable as %s\n", __path);
> > + path = xstrdup(buf);
> > if (path == NULL)
> > goto err;
> >
> > f_handle->has_mnt_id = true;
> > - f_handle->mnt_id = mi->mnt_id;
> > -
> > + f_handle->mnt_id = m->mnt_id;
> > goto out;
> > - }
> > -
> > - if (!opts.force_irmap)
> > - /*
> > - * If we're not forced to do irmap, then
> > - * say we have no path for watch. Otherwise
> > - * do irmap scan even if the handle is
> > - * working.
> > - *
> > - * FIXME -- no need to open-by-handle if
> > - * we are in force-irmap and not on tempfs
> > - */
> > - goto out_nopath;
> > + } else
> > + pr_debug("\t\t\tnot openable as %s (%m)\n", __path);
> > }
>
> After you've managed to open something by some name you should check that
> the file opened is the same as referenced by fd from open_by_handle().
Well, I'll try to split it but I fear this would be more messy. Simply take
a look not on the diff but the complete function instead
int check_open_handle(unsigned int s_dev, unsigned long i_ino,
FhEntry *f_handle)
{
struct mount_info *m;
fh_t handle;
int fd = -1;
char *path;
decode_handle(&handle, f_handle);
/*
* We gonna try to open the handle and then
* depending on command line options and type
* of the filesystem (tmpfs/devtmpfs do not
* preserve their inodes between mounts) we
* might need to find out an openable path
* get used on restore as a watch destination.
*/
for (m = mntinfo; m; m = m->next) {
char buf[PATH_MAX], *__path;
int mntfd, openable_fd;
if (m->s_dev != s_dev)
continue;
mntfd = __open_mountpoint(m, -1);
pr_debug("\t\tTrying via mntid %d root %s ns_mountpoint @%s (%d)\n",
m->mnt_id, m->root, m->ns_mountpoint, mntfd);
if (mntfd < 0)
goto cant_open;
fd = userns_call(open_by_handle, UNS_FDOUT, &handle,
sizeof(handle), mntfd);
close(mntfd);
if (fd < 0)
goto cant_open;
/*
* On tmpfs/devtmps we have to always fetch
* openable path, in turn on all others
* it depends on command line option: if
* we're requested to use irmap lets fetch
* the path, otherwise simply save the bare
* handler and that's it.
*/
if ((m->fstype->code != FSTYPE__TMPFS) &&
(m->fstype->code != FSTYPE__DEVTMPFS)) {
if (!opts.force_irmap)
goto out_nopath;
else
goto force_irmap;
}
if (read_fd_link(fd, buf, sizeof(buf)) < 0) {
close_safe(&fd);
goto err;
}
close_safe(&fd);
/*
* Convert into a relative path.
*/
__path = (buf[1] != '\0') ? buf + 1 : ".";
pr_debug("\t\t\tlink as %s\n", __path);
mntfd = mntns_get_root_by_mnt_id(m->mnt_id);
if (mntfd < 0)
goto err;
openable_fd = openat(mntfd, __path, O_PATH);
if (openable_fd >= 0) {
close(openable_fd);
pr_debug("\t\t\topenable as %s\n", __path);
path = xstrdup(buf);
if (path == NULL)
goto err;
f_handle->has_mnt_id = true;
f_handle->mnt_id = m->mnt_id;
goto out;
} else
pr_debug("\t\t\tnot openable as %s (%m)\n", __path);
}
cant_open:
pr_warn("\tHandle 0x%x:0x%lx cannot be opened\n", s_dev, i_ino);
force_irmap:
path = irmap_lookup(s_dev, i_ino);
if (!path) {
pr_err("\tCan't dump that handle\n");
return -1;
}
out:
pr_debug("\tDumping %s as path for handle\n", path);
f_handle->path = path;
out_nopath:
close_safe(&fd);
return 0;
err:
close_safe(&fd);
return -1;
}
As to path check -- we don't care which path we obtain,
the inode referenced by the path is the same.
More information about the CRIU
mailing list