mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-17 16:47:50 +00:00
fsnotify: Always provide the path for inotify watchees
In debian-8 container we faced the problem -- systemd creates nested mount namespaces and inotify watchee are resolved into a path which is inaccessbile on restore, the same happens when pathes where watchees are living are bind-overmounted. Thus when we try to restore such watchees we can't open the paths. Lets do a trick here (thanks a huge to Andrew Vagin for idea and overall help) -- walk over all mount points which device match the handle's device and open handle first and test if the path provided is openable as well for tmpfs and devtmps which do not save inodes between remounts. After all the inotify objects are bound to inode so it's irrelevean via which path it's assigned. https://jira.sw.ru/browse/PSBM-39957 Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Acked-by: Andrew Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
d2762ddf77
commit
78c72b62a0
1 changed files with 89 additions and 11 deletions
100
fsnotify.c
100
fsnotify.c
|
|
@ -107,6 +107,90 @@ static int open_by_handle(void *arg, int fd)
|
|||
return sys_open_by_handle_at(fd, arg, O_PATH);
|
||||
}
|
||||
|
||||
static char *alloc_openable(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;
|
||||
struct stat st;
|
||||
|
||||
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)
|
||||
continue;
|
||||
|
||||
fd = userns_call(open_by_handle, UNS_FDOUT, &handle,
|
||||
sizeof(handle), mntfd);
|
||||
close(mntfd);
|
||||
if (fd < 0)
|
||||
continue;
|
||||
|
||||
if (read_fd_link(fd, buf, sizeof(buf)) < 0) {
|
||||
close(fd);
|
||||
goto err;
|
||||
}
|
||||
close(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_fd(m->nsid);
|
||||
if (mntfd < 0)
|
||||
goto err;
|
||||
|
||||
openable_fd = openat(mntfd, __path, O_PATH);
|
||||
if (openable_fd >= 0) {
|
||||
if (fstat(openable_fd, &st)) {
|
||||
pr_perror("Can't stat on %s\n", __path);
|
||||
close(openable_fd);
|
||||
return ERR_PTR(-errno);
|
||||
}
|
||||
close(openable_fd);
|
||||
|
||||
pr_debug("\t\t\topenable (inode %s) as %s\n",
|
||||
st.st_ino == i_ino ?
|
||||
"match" : "don't match", __path);
|
||||
|
||||
if (st.st_ino == i_ino) {
|
||||
path = xstrdup(buf);
|
||||
if (path == NULL)
|
||||
goto err;
|
||||
|
||||
f_handle->has_mnt_id = true;
|
||||
f_handle->mnt_id = m->mnt_id;
|
||||
return path;
|
||||
}
|
||||
} else
|
||||
pr_debug("\t\t\tnot openable as %s (%m)\n", __path);
|
||||
}
|
||||
|
||||
return ERR_PTR(-ENOENT);
|
||||
err:
|
||||
return ERR_PTR(-1);
|
||||
}
|
||||
|
||||
static int open_handle(unsigned int s_dev, unsigned long i_ino,
|
||||
FhEntry *f_handle)
|
||||
{
|
||||
|
|
@ -160,18 +244,12 @@ int check_open_handle(unsigned int s_dev, unsigned long i_ino,
|
|||
*/
|
||||
if ((mi->fstype->code == FSTYPE__TMPFS) ||
|
||||
(mi->fstype->code == FSTYPE__DEVTMPFS)) {
|
||||
char p[PATH_MAX];
|
||||
|
||||
if (read_fd_link(fd, p, sizeof(p)) < 0)
|
||||
path = alloc_openable(s_dev, i_ino, f_handle);
|
||||
if (IS_ERR_OR_NULL(path)) {
|
||||
pr_err("Can't find suitable path for handle (%d)\n",
|
||||
(int)PTR_ERR(path));
|
||||
goto err;
|
||||
|
||||
path = xstrdup(p);
|
||||
if (path == NULL)
|
||||
goto err;
|
||||
|
||||
f_handle->has_mnt_id = true;
|
||||
f_handle->mnt_id = mi->mnt_id;
|
||||
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue