[CRIU] [PATCH 2/2 v5] fsnotify: Always provide the path for inotify watchees

Andrew Vagin avagin at odin.com
Tue Oct 20 08:22:16 PDT 2015


On Mon, Oct 19, 2015 at 07:57:52PM +0300, Cyrill Gorcunov wrote:
> Take a look on attached please.

> From 0c6ea73b5baf5602fe8d3de756d22294bf5e8a54 Mon Sep 17 00:00:00 2001
> From: Cyrill Gorcunov <gorcunov at openvz.org>
> Date: Tue, 13 Oct 2015 19:58:22 +0300
> Subject: [PATCH] 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
>

Acked-by: Andrew Vagin <avagin at openvz.org>

> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
>  fsnotify.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 89 insertions(+), 11 deletions(-)
> 
> diff --git a/fsnotify.c b/fsnotify.c
> index a7acc9672927..9629977de8bc 100644
> --- a/fsnotify.c
> +++ b/fsnotify.c
> @@ -107,6 +107,90 @@ static int open_by_handle(void *arg, int fd, int pid)
>  	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;
>  		}
>  
> -- 
> 2.4.3
> 



More information about the CRIU mailing list