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

Pavel Emelyanov xemul at parallels.com
Mon Oct 19 02:57:35 PDT 2015


> @@ -139,56 +139,91 @@ out:
>  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;
>  
> -	fd = open_handle(s_dev, i_ino, f_handle);
> -	if (fd >= 0) {
> -		struct mount_info *mi;
> +	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;
>  
> -		pr_debug("\tHandle 0x%x:0x%lx is openable\n", s_dev, i_ino);
> +		if (m->s_dev != s_dev)
> +			continue;
>  
> -		mi = lookup_mnt_sdev(s_dev);
> -		if (mi == NULL) {
> -			pr_err("Unable to lookup a mount by dev 0x%x\n", s_dev);
> +		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);

Turn from open_by_handle into userns_call deserves separate patch and explanation.

> +		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;
> +		}

So this WHOLE loop is for a single thing -- handle path resolve for tmpfs mounts. Right?

> +
> +		if (read_fd_link(fd, buf, sizeof(buf)) < 0) {
> +			close_safe(&fd);
>  			goto err;
>  		}
> +		close_safe(&fd);
>  
>  		/*
> -		 * Inode numbers are not restored for tmpfs content, but we can
> -		 * get file names, becasue tmpfs cache is not pruned.
> +		 * Convert into a relative path.
>  		 */
> -		if ((mi->fstype->code == FSTYPE__TMPFS) ||
> -				(mi->fstype->code == FSTYPE__DEVTMPFS)) {
> -			char p[PATH_MAX];
> +		__path = (buf[1] != '\0') ? buf + 1 : ".";
> +		pr_debug("\t\t\tlink as %s\n", __path);
>  
> -			if (read_fd_link(fd, p, sizeof(p)) < 0)
> -				goto err;
> +		mntfd = mntns_get_root_by_mnt_id(m->mnt_id);

Why not just "m->nsid" dereference?

> +		if (mntfd < 0)
> +			goto err;
>  
> -			path = xstrdup(p);
> +		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);
>  	}
>  
> +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");




More information about the CRIU mailing list