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 *);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to