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-all
mailing list