svn commit: r367773 - in head/sys: amd64/linux amd64/linux32 arm64/linux compat/linux i386/linux kern sys

Conrad Meyer cem at FreeBSD.org
Tue Nov 17 19:51:49 UTC 2020


Author: cem
Date: Tue Nov 17 19:51:47 2020
New Revision: 367773
URL: https://svnweb.freebsd.org/changeset/base/367773

Log:
  linux(4): Implement name_to_handle_at(), open_by_handle_at()
  
  They are similar to our getfhat(2) and fhopen(2) syscalls.
  
  Differential Revision:	https://reviews.freebsd.org/D27111

Modified:
  head/sys/amd64/linux/syscalls.master
  head/sys/amd64/linux32/syscalls.master
  head/sys/arm64/linux/syscalls.master
  head/sys/compat/linux/linux_dummy.c
  head/sys/compat/linux/linux_file.c
  head/sys/compat/linux/linux_file.h
  head/sys/i386/linux/syscalls.master
  head/sys/kern/vfs_syscalls.c
  head/sys/sys/syscallsubr.h

Modified: head/sys/amd64/linux/syscalls.master
==============================================================================
--- head/sys/amd64/linux/syscalls.master	Tue Nov 17 18:28:20 2020	(r367772)
+++ head/sys/amd64/linux/syscalls.master	Tue Nov 17 19:51:47 2020	(r367773)
@@ -1792,10 +1792,20 @@
 	}
 ; Linux 2.6.39 (glibc 2.14):
 303	AUE_NULL	STD {
-		int linux_name_to_handle_at(void);
+		int linux_name_to_handle_at(
+		    l_int dirfd,
+		    const char *name,
+		    struct l_file_handle *handle,
+		    l_int *mnt_id,
+		    l_int flags
+		);
 	}
 304	AUE_NULL	STD {
-		int linux_open_by_handle_at(void);
+		int linux_open_by_handle_at(
+		    l_int mountdirfd,
+		    struct l_file_handle *handle,
+		    l_int flags
+		);
 	}
 305	AUE_NULL	STD {
 		int linux_clock_adjtime(void);

Modified: head/sys/amd64/linux32/syscalls.master
==============================================================================
--- head/sys/amd64/linux32/syscalls.master	Tue Nov 17 18:28:20 2020	(r367772)
+++ head/sys/amd64/linux32/syscalls.master	Tue Nov 17 19:51:47 2020	(r367773)
@@ -1916,10 +1916,20 @@
 	}
 ; Linux 2.6.39:
 341	AUE_NULL	STD {
-		int linux_name_to_handle_at(void);
+		int linux_name_to_handle_at(
+		    l_int dirfd,
+		    const char *name,
+		    struct l_file_handle *handle,
+		    l_int *mnt_id,
+		    l_int flags
+		);
 	}
 342	AUE_NULL	STD {
-		int linux_open_by_handle_at(void);
+		int linux_open_by_handle_at(
+		    l_int mountdirfd,
+		    struct l_file_handle *handle,
+		    l_int flags
+		);
 	}
 343	AUE_NULL	STD {
 		int linux_clock_adjtime(void);

Modified: head/sys/arm64/linux/syscalls.master
==============================================================================
--- head/sys/arm64/linux/syscalls.master	Tue Nov 17 18:28:20 2020	(r367772)
+++ head/sys/arm64/linux/syscalls.master	Tue Nov 17 19:51:47 2020	(r367773)
@@ -1473,10 +1473,20 @@
 		int linux_fanotify_mark(void);
 	}
 264	AUE_NULL	STD	{
-		int linux_name_to_handle_at(void);
+		int linux_name_to_handle_at(
+		    l_int dirfd,
+		    const char *name,
+		    struct l_file_handle *handle,
+		    l_int *mnt_id,
+		    l_int flags
+		);
 	}
 265	AUE_NULL	STD	{
-		int linux_open_by_handle_at(void);
+		int linux_open_by_handle_at(
+		    l_int mountdirfd,
+		    struct l_file_handle *handle,
+		    l_int flags
+		);
 	}
 266	AUE_NULL	STD	{
 		int linux_clock_adjtime(void);

Modified: head/sys/compat/linux/linux_dummy.c
==============================================================================
--- head/sys/compat/linux/linux_dummy.c	Tue Nov 17 18:28:20 2020	(r367772)
+++ head/sys/compat/linux/linux_dummy.c	Tue Nov 17 19:51:47 2020	(r367773)
@@ -101,8 +101,6 @@ DUMMY(perf_event_open);
 DUMMY(fanotify_init);
 DUMMY(fanotify_mark);
 /* Linux 2.6.39: */
-DUMMY(name_to_handle_at);
-DUMMY(open_by_handle_at);
 DUMMY(clock_adjtime);
 /* Linux 3.0: */
 DUMMY(setns);

Modified: head/sys/compat/linux/linux_file.c
==============================================================================
--- head/sys/compat/linux/linux_file.c	Tue Nov 17 18:28:20 2020	(r367772)
+++ head/sys/compat/linux/linux_file.c	Tue Nov 17 19:51:47 2020	(r367773)
@@ -121,13 +121,9 @@ linux_creat(struct thread *td, struct linux_creat_args
 #endif
 
 static int
-linux_common_open(struct thread *td, int dirfd, const char *path, int l_flags,
-    int mode, enum uio_seg seg)
+linux_common_openflags(int l_flags)
 {
-	struct proc *p = td->td_proc;
-	struct file *fp;
-	int fd;
-	int bsd_flags, error;
+	int bsd_flags;
 
 	bsd_flags = 0;
 	switch (l_flags & LINUX_O_ACCMODE) {
@@ -167,7 +163,19 @@ linux_common_open(struct thread *td, int dirfd, const 
 	if (l_flags & LINUX_O_DIRECTORY)
 		bsd_flags |= O_DIRECTORY;
 	/* XXX LINUX_O_NOATIME: unable to be easily implemented. */
+	return (bsd_flags);
+}
 
+static int
+linux_common_open(struct thread *td, int dirfd, const char *path, int l_flags,
+    int mode, enum uio_seg seg)
+{
+	struct proc *p = td->td_proc;
+	struct file *fp;
+	int fd;
+	int bsd_flags, error;
+
+	bsd_flags = linux_common_openflags(l_flags);
 	error = kern_openat(td, dirfd, path, seg, bsd_flags, mode);
 	if (error != 0) {
 		if (error == EMLINK)
@@ -253,6 +261,102 @@ linux_open(struct thread *td, struct linux_open_args *
 	return (error);
 }
 #endif
+
+int
+linux_name_to_handle_at(struct thread *td,
+    struct linux_name_to_handle_at_args *args)
+{
+	static const l_int valid_flags = (LINUX_AT_SYMLINK_FOLLOW |
+	    LINUX_AT_EMPTY_PATH);
+	static const l_uint fh_size = sizeof(fhandle_t);
+
+	fhandle_t fh;
+	l_uint fh_bytes;
+	l_int mount_id;
+	int error, fd, bsd_flags;
+
+	if (args->flags & ~valid_flags)
+		return (EINVAL);
+	if (args->flags & LINUX_AT_EMPTY_PATH)
+		/* XXX: not supported yet */
+		return (EOPNOTSUPP);
+
+	fd = args->dirfd;
+	if (fd == LINUX_AT_FDCWD)
+		fd = AT_FDCWD;
+
+	bsd_flags = 0;
+	if (!(args->flags & LINUX_AT_SYMLINK_FOLLOW))
+		bsd_flags |= AT_SYMLINK_NOFOLLOW;
+
+	if (!LUSECONVPATH(td)) {
+		error = kern_getfhat(td, bsd_flags, fd, args->name,
+		    UIO_USERSPACE, &fh, UIO_SYSSPACE);
+	} else {
+		char *path;
+
+		LCONVPATH_AT(td, args->name, &path, 0, fd);
+		error = kern_getfhat(td, bsd_flags, fd, path, UIO_SYSSPACE,
+		    &fh, UIO_SYSSPACE);
+		LFREEPATH(path);
+	}
+	if (error != 0)
+		return (error);
+
+	/* Emit mount_id -- required before EOVERFLOW case. */
+	mount_id = (fh.fh_fsid.val[0] ^ fh.fh_fsid.val[1]);
+	error = copyout(&mount_id, args->mnt_id, sizeof(mount_id));
+	if (error != 0)
+		return (error);
+
+	/* Check if there is room for handle. */
+	error = copyin(&args->handle->handle_bytes, &fh_bytes,
+	    sizeof(fh_bytes));
+	if (error != 0)
+		return (error);
+
+	if (fh_bytes < fh_size) {
+		error = copyout(&fh_size, &args->handle->handle_bytes,
+		    sizeof(fh_size));
+		if (error == 0)
+			error = EOVERFLOW;
+		return (error);
+	}
+
+	/* Emit handle. */
+	mount_id = 0;
+	/*
+	 * We don't use handle_type for anything yet, but initialize a known
+	 * value.
+	 */
+	error = copyout(&mount_id, &args->handle->handle_type,
+	    sizeof(mount_id));
+	if (error != 0)
+		return (error);
+
+	error = copyout(&fh, &args->handle->f_handle,
+	    sizeof(fh));
+	return (error);
+}
+
+int
+linux_open_by_handle_at(struct thread *td,
+    struct linux_open_by_handle_at_args *args)
+{
+	l_uint fh_bytes;
+	int bsd_flags, error;
+
+	error = copyin(&args->handle->handle_bytes, &fh_bytes,
+	    sizeof(fh_bytes));
+	if (error != 0)
+		return (error);
+
+	if (fh_bytes < sizeof(fhandle_t))
+		return (EINVAL);
+
+	bsd_flags = linux_common_openflags(args->flags);
+	return (kern_fhopen(td, (void *)&args->handle->f_handle, bsd_flags));
+}
 
 int
 linux_lseek(struct thread *td, struct linux_lseek_args *args)

Modified: head/sys/compat/linux/linux_file.h
==============================================================================
--- head/sys/compat/linux/linux_file.h	Tue Nov 17 18:28:20 2020	(r367772)
+++ head/sys/compat/linux/linux_file.h	Tue Nov 17 19:51:47 2020	(r367773)
@@ -36,6 +36,7 @@
 #define	LINUX_AT_EACCESS		0x200
 #define	LINUX_AT_REMOVEDIR		0x200
 #define	LINUX_AT_SYMLINK_FOLLOW		0x400
+#define	LINUX_AT_EMPTY_PATH		0x1000
 
 /*
  * posix_fadvise advice
@@ -173,5 +174,11 @@
 #define LINUX_HUGETLB_FLAG_ENCODE_1GB	(30 << LINUX_HUGETLB_FLAG_ENCODE_SHIFT)
 #define LINUX_HUGETLB_FLAG_ENCODE_2GB	(31 << LINUX_HUGETLB_FLAG_ENCODE_SHIFT)
 #define LINUX_HUGETLB_FLAG_ENCODE_16GB	(34U << LINUX_HUGETLB_FLAG_ENCODE_SHIFT)
+
+struct l_file_handle {
+	l_uint handle_bytes;
+	l_int handle_type;
+	unsigned char f_handle[0];
+};
 
 #endif	/* !_LINUX_FILE_H_ */

Modified: head/sys/i386/linux/syscalls.master
==============================================================================
--- head/sys/i386/linux/syscalls.master	Tue Nov 17 18:28:20 2020	(r367772)
+++ head/sys/i386/linux/syscalls.master	Tue Nov 17 19:51:47 2020	(r367773)
@@ -1934,10 +1934,20 @@
 	}
 ; Linux 2.6.39:
 341	AUE_NULL	STD {
-		int linux_name_to_handle_at(void);
+		int linux_name_to_handle_at(
+		    l_int dirfd,
+		    const char *name,
+		    struct l_file_handle *handle,
+		    l_int *mnt_id,
+		    l_int flags
+		);
 	}
 342	AUE_NULL	STD {
-		int linux_open_by_handle_at(void);
+		int linux_open_by_handle_at(
+		    l_int mountdirfd,
+		    struct l_file_handle *handle,
+		    l_int flags
+		);
 	}
 343	AUE_NULL	STD {
 		int linux_clock_adjtime(void);

Modified: head/sys/kern/vfs_syscalls.c
==============================================================================
--- head/sys/kern/vfs_syscalls.c	Tue Nov 17 18:28:20 2020	(r367772)
+++ head/sys/kern/vfs_syscalls.c	Tue Nov 17 19:51:47 2020	(r367773)
@@ -105,8 +105,6 @@ static int vn_access(struct vnode *vp, int user_flags,
     struct thread *td);
 static int kern_fhlinkat(struct thread *td, int fd, const char *path,
     enum uio_seg pathseg, fhandle_t *fhp);
-static int kern_getfhat(struct thread *td, int flags, int fd,
-    const char *path, enum uio_seg pathseg, fhandle_t *fhp);
 static int kern_readlink_vp(struct vnode *vp, char *buf, enum uio_seg bufseg,
     size_t count, struct thread *td);
 static int kern_linkat_vp(struct thread *td, struct vnode *vp, int fd,
@@ -4315,7 +4313,7 @@ sys_lgetfh(struct thread *td, struct lgetfh_args *uap)
 {
 
 	return (kern_getfhat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->fname,
-	    UIO_USERSPACE, uap->fhp));
+	    UIO_USERSPACE, uap->fhp, UIO_USERSPACE));
 }
 
 #ifndef _SYS_SYSPROTO_H_
@@ -4329,7 +4327,7 @@ sys_getfh(struct thread *td, struct getfh_args *uap)
 {
 
 	return (kern_getfhat(td, 0, AT_FDCWD, uap->fname, UIO_USERSPACE,
-	    uap->fhp));
+	    uap->fhp, UIO_USERSPACE));
 }
 
 /*
@@ -4355,12 +4353,12 @@ sys_getfhat(struct thread *td, struct getfhat_args *ua
 	    AT_RESOLVE_BENEATH)) != 0)
 		return (EINVAL);
 	return (kern_getfhat(td, uap->flags, uap->fd, uap->path, UIO_USERSPACE,
-	    uap->fhp));
+	    uap->fhp, UIO_USERSPACE));
 }
 
-static int
+int
 kern_getfhat(struct thread *td, int flags, int fd, const char *path,
-    enum uio_seg pathseg, fhandle_t *fhp)
+    enum uio_seg pathseg, fhandle_t *fhp, enum uio_seg fhseg)
 {
 	struct nameidata nd;
 	fhandle_t fh;
@@ -4382,8 +4380,12 @@ kern_getfhat(struct thread *td, int flags, int fd, con
 	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
 	error = VOP_VPTOFH(vp, &fh.fh_fid);
 	vput(vp);
-	if (error == 0)
-		error = copyout(&fh, fhp, sizeof (fh));
+	if (error == 0) {
+		if (fhseg == UIO_USERSPACE)
+			error = copyout(&fh, fhp, sizeof (fh));
+		else
+			memcpy(fhp, &fh, sizeof(fh));
+	}
 	return (error);
 }
 
@@ -4493,6 +4495,12 @@ struct fhopen_args {
 int
 sys_fhopen(struct thread *td, struct fhopen_args *uap)
 {
+	return (kern_fhopen(td, uap->u_fhp, uap->flags));
+}
+
+int
+kern_fhopen(struct thread *td, const struct fhandle *u_fhp, int flags)
+{
 	struct mount *mp;
 	struct vnode *vp;
 	struct fhandle fhp;
@@ -4504,11 +4512,11 @@ sys_fhopen(struct thread *td, struct fhopen_args *uap)
 	if (error != 0)
 		return (error);
 	indx = -1;
-	fmode = FFLAGS(uap->flags);
+	fmode = FFLAGS(flags);
 	/* why not allow a non-read/write open for our lockd? */
 	if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
 		return (EINVAL);
-	error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
+	error = copyin(u_fhp, &fhp, sizeof(fhp));
 	if (error != 0)
 		return(error);
 	/* find the mount point */

Modified: head/sys/sys/syscallsubr.h
==============================================================================
--- head/sys/sys/syscallsubr.h	Tue Nov 17 18:28:20 2020	(r367772)
+++ head/sys/sys/syscallsubr.h	Tue Nov 17 19:51:47 2020	(r367773)
@@ -140,6 +140,7 @@ int	kern_fchownat(struct thread *td, int fd, const cha
 	    enum uio_seg pathseg, int uid, int gid, int flag);
 int	kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg);
 int	kern_fcntl_freebsd(struct thread *td, int fd, int cmd, long arg);
+int	kern_fhopen(struct thread *td, const struct fhandle *u_fhp, int flags);
 int	kern_fhstat(struct thread *td, fhandle_t fh, struct stat *buf);
 int	kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf);
 int	kern_fpathconf(struct thread *td, int fd, int name, long *valuep);
@@ -153,6 +154,8 @@ int	kern_futimens(struct thread *td, int fd, struct ti
 	    enum uio_seg tptrseg);
 int	kern_getdirentries(struct thread *td, int fd, char *buf, size_t count,
 	    off_t *basep, ssize_t *residp, enum uio_seg bufseg);
+int	kern_getfhat(struct thread *td, int flags, int fd, const char *path,
+	    enum uio_seg pathseg, fhandle_t *fhp, enum uio_seg fhseg);
 int	kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
 	    size_t *countp, enum uio_seg bufseg, int mode);
 int	kern_getitimer(struct thread *, u_int, struct itimerval *);


More information about the svn-src-head mailing list