sys/kern: Add struct file* arg to VOP_{GETATTR,SETATTR,READ,WRITE,FSYNC,READDIR}
authorTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Sun, 31 Mar 2019 16:30:07 +0000 (01:30 +0900)
committerTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Sun, 31 Mar 2019 17:04:18 +0000 (02:04 +0900)
This commit changes VOP interface to support FUSE API/ABI.
It just adds an additional struct file* argument to VOP's, so that
FUSE VOP's can access *fp pointer (currently accessible only from
caller of VOP's if any, with exception of VOP_OPEN(), VOP_CLOSE(),
etc) and make use of its ->private_data pointer.

FUSE API/ABI requires FUSE to maintain a per file (usually per file
descriptor) data called fh. The fh is an opaque data whose purpose
may differ among userspace filesystems, but typically used to store
file descriptor value or arbitrary userspace address used by the
userspace filesystem process.

Below diagram illustrates typical flow of maintaining fh. The
userspace filesystem uses fd obtained from opening backing store
(e.g fd for regular file, socket, etc) for fh, as a consequence of
end user's open(2) syscall, and expects FUSE to maintain that value
for future use as an identifier for userspace.

* Notes on Linux VFS I/F vs BSD VFS I/F:
In Linux, supporting the concept of fh is quite straight forward since
Linux kernel has functions vector built around (opened)file including
things like mmap(2) handler, in addition to a vector built around
inode.

But since DragonFly doesn't have a vector built around file (other
than a simple struct fileops, which doesn't meet requirements of fh),
this change was needed for selected VOP's as minimum requirements
for initial FUSE API/ABI support.

--
FUSE user                  FUSE                       FUSE userspace fs
|                          |                          |
|---------open(2)--------->|                          |
| * issue VOP_OPEN         |---------VOP_OPEN-------->|
|                          | * issue FUSE_OPEN        | * open something
|                          |                          | * reply fd as fh
|                          |<--------VOP_OPEN---------|
|<--------open(2)----------| * store fh in fp         |
| * open success           |                          |
|                          |                          |
|...                       |                          |
|...                       |                          |
|                          |                          |
|---------read(2)--------->|                          |
| * issue VOP_READ         |---------VOP_READ-------->|
|                          | * issue FUSE_READ        |
|                          |   with fh from fp        | * read something
|                          |                          |   using fh for fd
|                          |<--------VOP_READ---------|
|<--------read(2)----------| * return read bytes      |
| * uiomove() success      |                          |
|                          |                          |

sys/kern/kern_fp.c
sys/kern/uipc_syscalls.c
sys/kern/vfs_syscalls.c
sys/kern/vfs_vnops.c
sys/kern/vfs_vopops.c
sys/sys/vfsops.h

index 13916fb..94b57b8 100644 (file)
@@ -527,7 +527,7 @@ fp_mmap(void *addr_arg, size_t size, int prot, int flags, struct file *fp,
        ) {
            if ((fp->f_flag & FWRITE) != 0) {
                struct vattr va;
-               if ((error = VOP_GETATTR(vp, &va))) {
+               if ((error = VOP_GETATTR_FP(vp, &va, fp))) {
                    goto done;
                }
                if ((va.va_flags & (IMMUTABLE|APPEND)) == 0) {
index 5344c74..03ec1d8 100644 (file)
@@ -1791,9 +1791,9 @@ retry_lookup:
                        auio.uio_td = td;
 
                        vn_lock(vp, LK_SHARED | LK_RETRY);
-                       error = VOP_READ(vp, &auio, 
+                       error = VOP_READ_FP(vp, &auio,
                                         IO_VMIO | ((MAXBSIZE / bsize) << 16),
-                                        td->td_ucred);
+                                        td->td_ucred, fp);
                        vn_unlock(vp);
                        vm_object_hold_shared(obj);
 
index 6020d18..102abec 100644 (file)
@@ -2749,7 +2749,7 @@ kern_lseek(int fd, off_t offset, int whence, off_t *res)
                error = 0;
                break;
        case L_XTND:
-               error = VOP_GETATTR(vp, &vattr);
+               error = VOP_GETATTR_FP(vp, &vattr, fp);
                spin_lock(&fp->f_spin);
                new_offset = offset + vattr.va_size;
                break;
@@ -3722,7 +3722,7 @@ kern_futimens(int fd, struct timespec *ts)
                vp = fp->f_data;
                error = vget(vp, LK_EXCLUSIVE);
                if (error == 0) {
-                       error = VOP_GETATTR(vp, &vattr);
+                       error = VOP_GETATTR_FP(vp, &vattr, fp);
                        if (error == 0) {
                                error = naccess_va(&vattr, NLC_OWN | NLC_WRITE,
                                                   fp->f_cred);
@@ -3958,7 +3958,7 @@ kern_ftruncate(int fd, off_t length)
        }
 
        if (vfs_quota_enabled) {
-               error = VOP_GETATTR(vp, &vattr);
+               error = VOP_GETATTR_FP(vp, &vattr, fp);
                KASSERT(error == 0, ("kern_ftruncate(): VOP_GETATTR didn't return 0"));
                uid = vattr.va_uid;
                gid = vattr.va_gid;
@@ -3968,7 +3968,7 @@ kern_ftruncate(int fd, off_t length)
        if ((error = vn_writechk(vp, NULL)) == 0) {
                VATTR_NULL(&vattr);
                vattr.va_size = length;
-               error = VOP_SETATTR(vp, &vattr, fp->f_cred);
+               error = VOP_SETATTR_FP(vp, &vattr, fp->f_cred, fp);
                mp = vq_vptomp(vp);
                VFS_ACCOUNT(mp, uid, gid, length - old_size);
        }
@@ -4017,7 +4017,7 @@ sys_fsync(struct fsync_args *uap)
                        vm_object_page_clean(obj, 0, 0, 0);
                }
        }
-       error = VOP_FSYNC(vp, MNT_WAIT, VOP_FSYNC_SYSCALL);
+       error = VOP_FSYNC_FP(vp, MNT_WAIT, VOP_FSYNC_SYSCALL, fp);
        if (error == 0 && vp->v_mount)
                error = buf_fsync(vp);
        vn_unlock(vp);
@@ -4432,7 +4432,7 @@ kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res,
        auio.uio_td = td;
        auio.uio_resid = count;
        loff = auio.uio_offset = fp->f_offset;
-       error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
+       error = VOP_READDIR_FP(vp, &auio, fp->f_cred, &eofflag, NULL, NULL, fp);
        fp->f_offset = auio.uio_offset;
        if (error)
                goto done;
index 43d06a3..8b71e0a 100644 (file)
@@ -250,7 +250,7 @@ again:
                osize = vp->v_filesize;
                VATTR_NULL(vap);
                vap->va_size = 0;
-               error = VOP_SETATTR(vp, vap, cred);
+               error = VOP_SETATTR_FP(vp, vap, cred, fp);
                if (error)
                        goto bad;
                error = VOP_GETATTR(vp, vap);
@@ -678,7 +678,7 @@ vn_read(struct file *fp, struct uio *uio, struct ucred *cred, int flags)
        vn_lock(vp, LK_SHARED | LK_RETRY);
        ioflag |= sequential_heuristic(uio, fp);
 
-       error = VOP_READ(vp, uio, ioflag, cred);
+       error = VOP_READ_FP(vp, uio, ioflag, cred, fp);
        fp->f_nextoff = uio->uio_offset;
        vn_unlock(vp);
        if ((flags & O_FOFFSET) == 0 && (vp->v_flag & VNOTSEEKABLE) == 0)
@@ -731,7 +731,7 @@ vn_write(struct file *fp, struct uio *uio, struct ucred *cred, int flags)
                VFS_MODIFYING(vp->v_mount);
        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
        ioflag |= sequential_heuristic(uio, fp);
-       error = VOP_WRITE(vp, uio, ioflag, cred);
+       error = VOP_WRITE_FP(vp, uio, ioflag, cred, fp);
        fp->f_nextoff = uio->uio_offset;
        vn_unlock(vp);
        if ((flags & O_FOFFSET) == 0)
index e8bffd8..11b6c0c 100644 (file)
@@ -341,7 +341,8 @@ vop_access(struct vop_ops *ops, struct vnode *vp, int mode, int flags,
  * MPSAFE
  */
 int
-vop_getattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap)
+vop_getattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap,
+       struct file *fp)
 {
        struct vop_getattr_args ap;
        VFS_MPLOCK_DECLARE;
@@ -351,6 +352,7 @@ vop_getattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap)
        ap.a_head.a_ops = ops;
        ap.a_vp = vp;
        ap.a_vap = vap;
+       ap.a_fp = fp;
 
        VFS_MPLOCK_FLAG(vp->v_mount, MNTK_GA_MPSAFE);
        DO_OPS(ops, error, &ap, vop_getattr);
@@ -364,7 +366,7 @@ vop_getattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap)
  */
 int
 vop_setattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap,
-       struct ucred *cred)
+       struct ucred *cred, struct file *fp)
 {
        struct vop_setattr_args ap;
        VFS_MPLOCK_DECLARE;
@@ -375,6 +377,7 @@ vop_setattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap,
        ap.a_vp = vp;
        ap.a_vap = vap;
        ap.a_cred = cred;
+       ap.a_fp = fp;
 
        VFS_MPLOCK(vp->v_mount);
        DO_OPS(ops, error, &ap, vop_setattr);
@@ -387,7 +390,7 @@ vop_setattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap,
  */
 int
 vop_read(struct vop_ops *ops, struct vnode *vp, struct uio *uio, int ioflag,
-       struct ucred *cred)
+       struct ucred *cred, struct file *fp)
 {
        struct vop_read_args ap;
        VFS_MPLOCK_DECLARE;
@@ -399,6 +402,7 @@ vop_read(struct vop_ops *ops, struct vnode *vp, struct uio *uio, int ioflag,
        ap.a_uio = uio;
        ap.a_ioflag = ioflag;
        ap.a_cred = cred;
+       ap.a_fp = fp;
 
        VFS_MPLOCK_FLAG(vp->v_mount, MNTK_RD_MPSAFE);
        DO_OPS(ops, error, &ap, vop_read);
@@ -411,7 +415,7 @@ vop_read(struct vop_ops *ops, struct vnode *vp, struct uio *uio, int ioflag,
  */
 int
 vop_write(struct vop_ops *ops, struct vnode *vp, struct uio *uio, int ioflag,
-       struct ucred *cred)
+       struct ucred *cred, struct file *fp)
 {
        struct vop_write_args ap;
        VFS_MPLOCK_DECLARE;
@@ -427,6 +431,7 @@ vop_write(struct vop_ops *ops, struct vnode *vp, struct uio *uio, int ioflag,
        ap.a_uio = uio;
        ap.a_ioflag = ioflag;
        ap.a_cred = cred;
+       ap.a_fp = fp;
 
        /* is this a regular vnode ? */
        VFS_MPLOCK_FLAG(vp->v_mount, MNTK_WR_MPSAFE);
@@ -556,7 +561,8 @@ vop_mmap(struct vop_ops *ops, struct vnode *vp, int fflags, struct ucred *cred)
  * MPSAFE
  */
 int
-vop_fsync(struct vop_ops *ops, struct vnode *vp, int waitfor, int flags)
+vop_fsync(struct vop_ops *ops, struct vnode *vp, int waitfor, int flags,
+       struct file *fp)
 {
        struct vop_fsync_args ap;
        VFS_MPLOCK_DECLARE;
@@ -567,6 +573,7 @@ vop_fsync(struct vop_ops *ops, struct vnode *vp, int waitfor, int flags)
        ap.a_vp = vp;
        ap.a_waitfor = waitfor;
        ap.a_flags = flags;
+       ap.a_fp = fp;
 
        VFS_MPLOCK(vp->v_mount);
        DO_OPS(ops, error, &ap, vop_fsync);
@@ -725,7 +732,8 @@ vop_old_symlink(struct vop_ops *ops, struct vnode *dvp,
  */
 int
 vop_readdir(struct vop_ops *ops, struct vnode *vp, struct uio *uio,
-       struct ucred *cred, int *eofflag, int *ncookies, off_t **cookies)
+       struct ucred *cred, int *eofflag, int *ncookies, off_t **cookies,
+       struct file *fp)
 {
        struct vop_readdir_args ap;
        VFS_MPLOCK_DECLARE;
@@ -739,6 +747,7 @@ vop_readdir(struct vop_ops *ops, struct vnode *vp, struct uio *uio,
        ap.a_eofflag = eofflag;
        ap.a_ncookies = ncookies;
        ap.a_cookies = cookies;
+       ap.a_fp = fp;
 
        VFS_MPLOCK(vp->v_mount);
        DO_OPS(ops, error, &ap, vop_readdir);
index 2580740..8ebf374 100644 (file)
@@ -149,6 +149,7 @@ struct vop_getattr_args {
        struct vop_generic_args a_head;
        struct vnode *a_vp;
        struct vattr *a_vap;
+       struct file *a_fp; /* FUSE */
 };
 
 struct vop_setattr_args {
@@ -156,6 +157,7 @@ struct vop_setattr_args {
        struct vnode *a_vp;
        struct vattr *a_vap;
        struct ucred *a_cred;
+       struct file *a_fp; /* FUSE */
 };
 
 struct vop_read_args {
@@ -164,6 +166,7 @@ struct vop_read_args {
        struct uio *a_uio;
        int a_ioflag;
        struct ucred *a_cred;
+       struct file *a_fp; /* FUSE */
 };
 
 struct vop_write_args {
@@ -172,6 +175,7 @@ struct vop_write_args {
        struct uio *a_uio;
        int a_ioflag;
        struct ucred *a_cred;
+       struct file *a_fp; /* FUSE */
 };
 
 struct vop_ioctl_args {
@@ -209,6 +213,7 @@ struct vop_fsync_args {
        struct vnode *a_vp;
        int a_waitfor;
        int a_flags;
+       struct file *a_fp; /* FUSE */
 };
 
 struct vop_old_remove_args {
@@ -267,6 +272,7 @@ struct vop_readdir_args {
        int *a_eofflag;
        int *a_ncookies;
        off_t **a_cookies;
+       struct file *a_fp; /* FUSE */
 };
 
 struct vop_readlink_args {
@@ -744,13 +750,14 @@ int vop_close(struct vop_ops *ops, struct vnode *vp, int fflag,
                struct file *file);
 int vop_access(struct vop_ops *ops, struct vnode *vp, int mode, int flags,
                struct ucred *cred);
-int vop_getattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap);
+int vop_getattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap,
+               struct file *fp);
 int vop_setattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap,
-               struct ucred *cred);
+               struct ucred *cred, struct file *fp);
 int vop_read(struct vop_ops *ops, struct vnode *vp, struct uio *uio,
-               int ioflag, struct ucred *cred);
+               int ioflag, struct ucred *cred, struct file *fp);
 int vop_write(struct vop_ops *ops, struct vnode *vp, struct uio *uio,
-               int ioflag, struct ucred *cred);
+               int ioflag, struct ucred *cred, struct file *fp);
 int vop_ioctl(struct vop_ops *ops, struct vnode *vp, u_long command,
                caddr_t data, int fflag, struct ucred *cred,
                struct sysmsg *msg);
@@ -759,7 +766,8 @@ int vop_poll(struct vop_ops *ops, struct vnode *vp, int events,
 int vop_kqfilter(struct vop_ops *ops, struct vnode *vp, struct knote *kn);
 int vop_mmap(struct vop_ops *ops, struct vnode *vp, int fflags,
                struct ucred *cred);
-int vop_fsync(struct vop_ops *ops, struct vnode *vp, int waitfor, int flags);
+int vop_fsync(struct vop_ops *ops, struct vnode *vp, int waitfor, int flags,
+               struct file *fp);
 int vop_old_remove(struct vop_ops *ops, struct vnode *dvp,
                struct vnode *vp, struct componentname *cnp);
 int vop_old_link(struct vop_ops *ops, struct vnode *tdvp,
@@ -778,7 +786,7 @@ int vop_old_symlink(struct vop_ops *ops, struct vnode *dvp,
                struct vattr *vap, char *target);
 int vop_readdir(struct vop_ops *ops, struct vnode *vp, struct uio *uio,
                struct ucred *cred, int *eofflag, 
-               int *ncookies, off_t **cookies);
+               int *ncookies, off_t **cookies, struct file *fp);
 int vop_readlink(struct vop_ops *ops, struct vnode *vp, struct uio *uio,
                struct ucred *cred);
 int vop_inactive(struct vop_ops *ops, struct vnode *vp);
@@ -989,14 +997,22 @@ extern struct syslink_desc vop_nrename_desc;
        vop_access(*(vp)->v_ops, vp, mode, AT_EACCESS, cred)
 #define VOP_ACCESS_FLAGS(vp, mode, flags, cred)                \
        vop_access(*(vp)->v_ops, vp, mode, flags, cred)
+#define VOP_GETATTR_FP(vp, vap, fp)                    \
+       vop_getattr(*(vp)->v_ops, vp, vap, fp) /* FUSE */
 #define VOP_GETATTR(vp, vap)                           \
-       vop_getattr(*(vp)->v_ops, vp, vap)
+       VOP_GETATTR_FP(vp, vap, NULL)
+#define VOP_SETATTR_FP(vp, vap, cred, fp)              \
+       vop_setattr(*(vp)->v_ops, vp, vap, cred, fp) /* FUSE */
 #define VOP_SETATTR(vp, vap, cred)                     \
-       vop_setattr(*(vp)->v_ops, vp, vap, cred)
+       VOP_SETATTR_FP(vp, vap, cred, NULL)
+#define VOP_READ_FP(vp, uio, ioflag, cred, fp)         \
+       vop_read(*(vp)->v_ops, vp, uio, ioflag, cred, fp) /* FUSE */
 #define VOP_READ(vp, uio, ioflag, cred)                        \
-       vop_read(*(vp)->v_ops, vp, uio, ioflag, cred)
+       VOP_READ_FP(vp, uio, ioflag, cred, NULL)
+#define VOP_WRITE_FP(vp, uio, ioflag, cred, fp)                \
+       vop_write(*(vp)->v_ops, vp, uio, ioflag, cred, fp) /* FUSE */
 #define VOP_WRITE(vp, uio, ioflag, cred)               \
-       vop_write(*(vp)->v_ops, vp, uio, ioflag, cred)
+       VOP_WRITE_FP(vp, uio, ioflag, cred, NULL)
 #define VOP_IOCTL(vp, command, data, fflag, cred, msg) \
        vop_ioctl(*(vp)->v_ops, vp, command, data, fflag, cred, msg)
 #define VOP_POLL(vp, events, cred)                     \
@@ -1005,10 +1021,14 @@ extern struct syslink_desc vop_nrename_desc;
        vop_kqfilter(*(vp)->v_ops, vp, kn)
 #define VOP_MMAP(vp, fflags, cred)                     \
        vop_mmap(*(vp)->v_ops, vp, fflags, cred)
+#define VOP_FSYNC_FP(vp, waitfor, flags, fp)           \
+       vop_fsync(*(vp)->v_ops, vp, waitfor, flags, fp) /* FUSE*/
 #define VOP_FSYNC(vp, waitfor, flags)                  \
-       vop_fsync(*(vp)->v_ops, vp, waitfor, flags)
+       VOP_FSYNC_FP(vp, waitfor, flags, NULL)
+#define VOP_READDIR_FP(vp, uio, cred, eofflag, ncookies, cookies, fp)  \
+       vop_readdir(*(vp)->v_ops, vp, uio, cred, eofflag, ncookies, cookies, fp) /* FUSE */
 #define VOP_READDIR(vp, uio, cred, eofflag, ncookies, cookies)         \
-       vop_readdir(*(vp)->v_ops, vp, uio, cred, eofflag, ncookies, cookies)
+       VOP_READDIR_FP(vp, uio, cred, eofflag, ncookies, cookies, NULL)
 #define VOP_READLINK(vp, uio, cred)                    \
        vop_readlink(*(vp)->v_ops, vp, uio, cred)
 #define VOP_INACTIVE(vp)                               \