Re: [PATCH v2 1/2] open_by_handle: add support for testing connectable file handles

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, May 09, 2025 at 07:00:32PM +0200, Amir Goldstein wrote:
> Test for kernel and filesystem support for conenctable file handles.
> 
> With -N flag, encode connectable file handles and fail the test if the
> kernel or filesystem do not support conenctable file handles.
> 
> Verify that decoding connectable file handles always results in a non
> empty path of the fd.
> 
> Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
> ---

Reviewed-by: Zorro Lang <zlang@xxxxxxxxxx>

>  common/rc            | 16 ++++++++++---
>  src/open_by_handle.c | 53 ++++++++++++++++++++++++++++++++++++--------
>  2 files changed, 57 insertions(+), 12 deletions(-)
> 
> diff --git a/common/rc b/common/rc
> index 6592c835..6407b744 100644
> --- a/common/rc
> +++ b/common/rc
> @@ -3829,8 +3829,14 @@ _require_freeze()
>  }
>  
>  # Does NFS export work on this fs?
> -_require_exportfs()
> +_require_open_by_handle()
>  {
> +	local what="NFS export"
> +	local opts="$1"
> +	if [ "$1" == "-N" ]; then
> +		what="connectable file handles"
> +	fi
> +
>  	_require_test_program "open_by_handle"
>  
>  	# virtiofs doesn't support open_by_handle_at(2) yet, though the syscall
> @@ -3841,10 +3847,14 @@ _require_exportfs()
>  		_notrun "$FSTYP doesn't support open_by_handle_at(2)"
>  
>  	mkdir -p "$TEST_DIR"/exportfs_test
> -	$here/src/open_by_handle -c "$TEST_DIR"/exportfs_test 2>&1 \
> -		|| _notrun "$FSTYP does not support NFS export"
> +	$here/src/open_by_handle $opts -c "$TEST_DIR"/exportfs_test 2>&1 \
> +		|| _notrun "$FSTYP does not support $what"
>  }
>  
> +_require_exportfs()
> +{
> +	_require_open_by_handle
> +}
>  
>  # Does shutdown work on this fs?
>  _require_scratch_shutdown()
> diff --git a/src/open_by_handle.c b/src/open_by_handle.c
> index a99cce4b..7b664201 100644
> --- a/src/open_by_handle.c
> +++ b/src/open_by_handle.c
> @@ -96,6 +96,9 @@ Examples:
>  #ifndef AT_HANDLE_MNT_ID_UNIQUE
>  #	define AT_HANDLE_MNT_ID_UNIQUE 0x001
>  #endif
> +#ifndef AT_HANDLE_CONNECTABLE
> +#	define AT_HANDLE_CONNECTABLE   0x002
> +#endif
>  
>  #define MAXFILES 1024
>  
> @@ -121,6 +124,7 @@ void usage(void)
>  	fprintf(stderr, "open_by_handle -d <test_dir> [N] - unlink test files and hardlinks, drop caches and try to open by handle\n");
>  	fprintf(stderr, "open_by_handle -m <test_dir> [N] - rename test files, drop caches and try to open by handle\n");
>  	fprintf(stderr, "open_by_handle -M <test_dir> [N] - do not silently skip the mount ID verifications\n");
> +	fprintf(stderr, "open_by_handle -N <test_dir> [N] - encode connectable file handles\n");
>  	fprintf(stderr, "open_by_handle -p <test_dir>     - create/delete and try to open by handle also test_dir itself\n");
>  	fprintf(stderr, "open_by_handle -i <handles_file> <test_dir> [N] - read test files handles from file and try to open by handle\n");
>  	fprintf(stderr, "open_by_handle -o <handles_file> <test_dir> [N] - get file handles of test files and write handles to file\n");
> @@ -130,14 +134,16 @@ void usage(void)
>  	fprintf(stderr, "open_by_handle -C <feature>      - check if <feature> is supported by the kernel.\n");
>  	fprintf(stderr, "  <feature> can be any of the following values:\n");
>  	fprintf(stderr, "  - AT_HANDLE_MNT_ID_UNIQUE\n");
> +	fprintf(stderr, "  - AT_HANDLE_CONNECTABLE\n");
>  	exit(EXIT_FAILURE);
>  }
>  
> -static int do_name_to_handle_at(const char *fname, struct file_handle *fh,
> -				int bufsz, bool force_check_mountid)
> +static int do_name_to_handle_at(const char *fname, struct file_handle *fh, int bufsz,
> +				bool force_check_mountid, bool connectable)
>  {
>  	int ret;
>  	int mntid_short;
> +	int at_flags;
>  
>  	static bool skip_mntid, skip_mntid_unique;
>  
> @@ -181,18 +187,24 @@ static int do_name_to_handle_at(const char *fname, struct file_handle *fh,
>  		}
>  	}
>  
> +	at_flags = connectable ? AT_HANDLE_CONNECTABLE : 0;
>  	fh->handle_bytes = bufsz;
> -	ret = name_to_handle_at(AT_FDCWD, fname, fh, &mntid_short, 0);
> +	ret = name_to_handle_at(AT_FDCWD, fname, fh, &mntid_short, at_flags);
>  	if (bufsz < fh->handle_bytes) {
>  		/* Query the filesystem required bufsz and the file handle */
>  		if (ret != -1 || errno != EOVERFLOW) {
>  			fprintf(stderr, "%s: unexpected result from name_to_handle_at: %d (%m)\n", fname, ret);
>  			return EXIT_FAILURE;
>  		}
> -		ret = name_to_handle_at(AT_FDCWD, fname, fh, &mntid_short, 0);
> +		ret = name_to_handle_at(AT_FDCWD, fname, fh, &mntid_short, at_flags);
>  	}
>  	if (ret < 0) {
> -		fprintf(stderr, "%s: name_to_handle: %m\n", fname);
> +		/* No filesystem support for encoding connectable file handles (e.g. overlayfs)? */
> +		if (connectable)
> +			fprintf(stderr, "%s: name_to_handle_at(AT_HANDLE_CONNECTABLE) not supported by %s\n",
> +					fname, errno == EINVAL ? "kernel" : "filesystem");
> +		else
> +			fprintf(stderr, "%s: name_to_handle: %m\n", fname);
>  		return EXIT_FAILURE;
>  	}
>  
> @@ -245,8 +257,17 @@ static int check_feature(const char *feature)
>  			return EXIT_FAILURE;
>  		}
>  		return 0;
> +	} else if (!strcmp(feature, "AT_HANDLE_CONNECTABLE")) {
> +		int ret = name_to_handle_at(AT_FDCWD, ".", NULL, NULL, AT_HANDLE_CONNECTABLE);
> +		/* If AT_HANDLE_CONNECTABLE is supported, we get EFAULT. */
> +		if (ret < 0 && errno == EINVAL) {
> +			fprintf(stderr, "name_to_handle_at(AT_HANDLE_CONNECTABLE) not supported by running kernel\n");
> +			return EXIT_FAILURE;
> +		}
> +		return 0;
>  	}
>  
> +
>  	fprintf(stderr, "unknown feature name '%s'\n", feature);
>  	return EXIT_FAILURE;
>  }
> @@ -270,13 +291,13 @@ int main(int argc, char **argv)
>  	int	create = 0, delete = 0, nlink = 1, move = 0;
>  	int	rd = 0, wr = 0, wrafter = 0, parent = 0;
>  	int	keepopen = 0, drop_caches = 1, sleep_loop = 0;
> -	int	force_check_mountid = 0;
> +	bool	force_check_mountid = 0, connectable = 0;
>  	int	bufsz = MAX_HANDLE_SZ;
>  
>  	if (argc < 2)
>  		usage();
>  
> -	while ((c = getopt(argc, argv, "cC:ludmMrwapknhi:o:sz")) != -1) {
> +	while ((c = getopt(argc, argv, "cC:ludmMNrwapknhi:o:sz")) != -1) {
>  		switch (c) {
>  		case 'c':
>  			create = 1;
> @@ -313,6 +334,9 @@ int main(int argc, char **argv)
>  		case 'M':
>  			force_check_mountid = 1;
>  			break;
> +		case 'N':
> +			connectable = 1;
> +			break;
>  		case 'p':
>  			parent = 1;
>  			break;
> @@ -445,7 +469,8 @@ int main(int argc, char **argv)
>  				return EXIT_FAILURE;
>  			}
>  		} else {
> -			ret = do_name_to_handle_at(fname, &handle[i].fh, bufsz, force_check_mountid);
> +			ret = do_name_to_handle_at(fname, &handle[i].fh, bufsz,
> +						   force_check_mountid, connectable);
>  			if (ret)
>  				return EXIT_FAILURE;
>  		}
> @@ -475,7 +500,8 @@ int main(int argc, char **argv)
>  				return EXIT_FAILURE;
>  			}
>  		} else {
> -			ret = do_name_to_handle_at(test_dir, &dir_handle.fh, bufsz, force_check_mountid);
> +			ret = do_name_to_handle_at(test_dir, &dir_handle.fh, bufsz,
> +						   force_check_mountid, connectable);
>  			if (ret)
>  				return EXIT_FAILURE;
>  		}
> @@ -589,6 +615,15 @@ int main(int argc, char **argv)
>  		errno = 0;
>  		fd = open_by_handle_at(mount_fd, &handle[i].fh, wrafter ? O_RDWR : O_RDONLY);
>  		if ((nlink || keepopen) && fd >= 0) {
> +			char linkname[PATH_MAX];
> +			char procname[64];
> +			sprintf(procname, "/proc/self/fd/%i", fd);
> +			int n = readlink(procname, linkname, PATH_MAX);
> +
> +			/* check that fd is "connected" - that is has a non empty path */
> +			if (connectable && n <= 1) {
> +				printf("open_by_handle(%s) returned a disconnected fd!\n", fname);
> +			}
>  			if (rd) {
>  				char buf[4] = {0};
>  				int size = read(fd, buf, 4);
> -- 
> 2.34.1
> 





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux