Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/checkpoint-restore/criu.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrill Gorcunov <gorcunov@openvz.org>2015-10-13 19:58:22 +0300
committerPavel Emelyanov <xemul@parallels.com>2015-10-22 16:13:26 +0300
commit78c72b62a06ddffd70a6e72a6b7f21b76821c3cd (patch)
tree7a9e4d5de85d4a7594f2cfc838817f42f44661c0
parentd2762ddf77dc1121ac876d6d857fbab968ee25b0 (diff)
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>
-rw-r--r--fsnotify.c100
1 files changed, 89 insertions, 11 deletions
diff --git a/fsnotify.c b/fsnotify.c
index adeaa7f2e..f7b0f0b27 100644
--- a/fsnotify.c
+++ b/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)
- goto err;
-
- path = xstrdup(p);
- if (path == NULL)
+ 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;
-
- f_handle->has_mnt_id = true;
- f_handle->mnt_id = mi->mnt_id;
-
+ }
goto out;
}