diff options
author | 2018-05-20 02:51:26 +0000 | |
---|---|---|
committer | 2018-05-20 02:51:26 +0000 | |
commit | e1487996d306181a6e7f96708e70c7a896a0016b (patch) | |
tree | 61f9860df3eafeec26f1369a373168b1f1f98501 /sys | |
parent | In ui.h rev. 1.10 2018/05/19 11:03:33, tb@ added a const qualifier (diff) | |
download | wireguard-openbsd-e1487996d306181a6e7f96708e70c7a896a0016b.tar.xz wireguard-openbsd-e1487996d306181a6e7f96708e70c7a896a0016b.zip |
Implement FBT_FLUSH. This is sent whenever a file descriptor is closed with
VOP_CLOSE(9). The associated FUSE file handle is however not closed at this
time and is instead closed on VOP_RELEASE(9) because that's the only time
it's guaranteed to be no longer used. Directory handles are now only closed
on VOP_RELEASE(9) for the same reason.
ok mpi@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/miscfs/fuse/fuse_vnops.c | 107 | ||||
-rw-r--r-- | sys/miscfs/fuse/fusefs.h | 3 |
2 files changed, 71 insertions, 39 deletions
diff --git a/sys/miscfs/fuse/fuse_vnops.c b/sys/miscfs/fuse/fuse_vnops.c index 91fda224c6d..d130e9dbcdf 100644 --- a/sys/miscfs/fuse/fuse_vnops.c +++ b/sys/miscfs/fuse/fuse_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_vnops.c,v 1.41 2018/05/17 11:25:11 helg Exp $ */ +/* $OpenBSD: fuse_vnops.c,v 1.42 2018/05/20 02:51:26 helg Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com> * @@ -204,6 +204,16 @@ filt_fusefsvnode(struct knote *kn, long int hint) return (kn->kn_fflags != 0); } +/* + * FUSE file systems can maintain a file handle for each VFS file descriptor + * that is opened. The OpenBSD VFS does not make file descriptors visible to + * us so we fake it by mapping open flags to file handles. + * There is no way for FUSE to know which file descriptor is being used + * by an application for a file operation. We only maintain 3 descriptors, + * one each for O_RDONLY, O_WRONLY and O_RDWR. When reading and writing, the + * first open descriptor is used and this may well not be the one that was set + * by FUSE open and may have even been opened by another application. + */ int fusefs_open(void *v) { @@ -228,7 +238,7 @@ fusefs_open(void *v) else { if ((ap->a_mode & FREAD) && (ap->a_mode & FWRITE)) fufh_type = FUFH_RDWR; - else if (ap->a_mode & (FWRITE)) + else if (ap->a_mode & (FWRITE)) fufh_type = FUFH_WRONLY; } @@ -252,8 +262,9 @@ fusefs_close(void *v) struct vop_close_args *ap; struct fusefs_node *ip; struct fusefs_mnt *fmp; + struct fusebuf *fbuf; enum fufh_type fufh_type = FUFH_RDONLY; - int isdir, i; + int error = 0; ap = v; ip = VTOI(ap->a_vp); @@ -262,34 +273,42 @@ fusefs_close(void *v) if (!fmp->sess_init) return (0); - if (ap->a_vp->v_type == VDIR) { - isdir = 1; + /* + * The file or directory may have been opened more than once so there + * is no reliable way to determine when to ask the FUSE daemon to + * release its file descriptor. For files, ask the daemon to flush any + * buffers to disk now. All open file descriptors will be released on + * VOP_INACTIVE(9). + */ - if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) - return (fusefs_file_close(fmp, ip, fufh_type, O_RDONLY, - isdir, ap->a_p)); - } else { - if (ap->a_fflag & IO_NDELAY) - return (0); + if (ap->a_vp->v_type == VDIR) + return (0); - if ((ap->a_fflag & FREAD) && (ap->a_fflag & FWRITE)) - fufh_type = FUFH_RDWR; - else if (ap->a_fflag & (FWRITE)) - fufh_type = FUFH_WRONLY; - } + if ((ap->a_fflag & FREAD) && (ap->a_fflag & FWRITE)) + fufh_type = FUFH_RDWR; + else if (ap->a_fflag & (FWRITE)) + fufh_type = FUFH_WRONLY; - /* - * if fh not valid lookup for another valid fh in vnode. - * Do we need panic if there's not a valid fh ? - */ - if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) { - for (i = 0; i < FUFH_MAXTYPE; i++) - if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) - break; + if (ip->fufh[fufh_type].fh_type == FUFH_INVALID) + return (EBADF); + + /* No need to flush read-only file descriptors. */ + if (!(ap->a_fflag & FWRITE)) return (0); - } - return (0); + /* Implementing flush is optional. */ + if (fmp->undef_op & UNDEF_FLUSH) + return (0); + + fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_FLUSH, ap->a_p); + fbuf->fb_io_fd = ip->fufh[fufh_type].fh_id; + error = fb_queue(fmp->dev, fbuf); + if (error == ENOSYS) + fmp->undef_op |= UNDEF_FLUSH; + + fb_delete(fbuf); + + return (error); } int @@ -754,30 +773,42 @@ fusefs_inactive(void *v) struct vop_inactive_args *ap = v; struct vnode *vp = ap->a_vp; struct proc *p = ap->a_p; - struct ucred *cred = p->p_ucred; struct fusefs_node *ip = VTOI(vp); struct fusefs_filehandle *fufh = NULL; struct fusefs_mnt *fmp; - struct vattr vattr; - int error = 0; - int type; + int type, flags; fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; + /* Close all open file handles. */ for (type = 0; type < FUFH_MAXTYPE; type++) { fufh = &(ip->fufh[type]); - if (fufh->fh_type != FUFH_INVALID) - fusefs_file_close(fmp, ip, fufh->fh_type, type, - (vp->v_type == VDIR), ap->a_p); - } + if (fufh->fh_type != FUFH_INVALID) { + + /* + * FUSE file systems expect the same flags to be sent + * on release that were sent on open. We don't have a + * record of them so make a best guess. + */ + switch (type) { + case FUFH_RDONLY: + flags = O_RDONLY; + break; + case FUFH_WRONLY: + flags = O_WRONLY; + break; + default: + flags = O_RDWR; + } - error = VOP_GETATTR(vp, &vattr, cred, p); + fusefs_file_close(fmp, ip, fufh->fh_type, flags, + (vp->v_type == VDIR), p); + } + } VOP_UNLOCK(vp); - if (error) - vrecycle(vp, p); - + /* Don't return error to prevent kernel panic in vclean(9). */ return (0); } diff --git a/sys/miscfs/fuse/fusefs.h b/sys/miscfs/fuse/fusefs.h index 2b96e3c168a..bf2c1f34c3a 100644 --- a/sys/miscfs/fuse/fusefs.h +++ b/sys/miscfs/fuse/fusefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: fusefs.h,v 1.8 2016/08/21 09:23:33 natano Exp $ */ +/* $OpenBSD: fusefs.h,v 1.9 2018/05/20 02:51:26 helg Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com> * @@ -66,6 +66,7 @@ struct fusefs_mnt { #define UNDEF_RENAME 1<<8 #define UNDEF_SYMLINK 1<<9 #define UNDEF_MKNOD 1<<10 +#define UNDEF_FLUSH 1<<11 extern struct vops fusefs_vops; extern struct pool fusefs_fbuf_pool; |