From: helg Date: Mon, 16 Jul 2018 13:10:53 +0000 (+0000) Subject: Implement FBT_FSYNC, which is called on fsync(2) and fdatasync(2). X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=0d64465817bc318c59b559b5ca4ecc8c74468463;p=openbsd Implement FBT_FSYNC, which is called on fsync(2) and fdatasync(2). Currently ignores the a_waitfor argument and always invokes the file system's fsync implementation synchronously. ok mpi@ --- diff --git a/lib/libfuse/fuse_new.3 b/lib/libfuse/fuse_new.3 index d640805490b..3c5887c2b01 100644 --- a/lib/libfuse/fuse_new.3 +++ b/lib/libfuse/fuse_new.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: fuse_new.3,v 1.2 2018/07/08 06:17:10 jmc Exp $ +.\" $OpenBSD: fuse_new.3,v 1.3 2018/07/16 13:10:53 helg Exp $ .\" .\" Copyright (c) 2013 Sylvestre Gallon .\" Copyright (c) 2018 Helg Bredow @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: July 8 2018 $ +.Dd $Mdocdate: July 16 2018 $ .Dt FUSE_NEW 3 .Os .Sh NAME @@ -38,6 +38,13 @@ a negated errno value (-errno) on failure. .Pp All operations are optional but a functional file system will want to implement at least statfs, readdir, open, read and getattr. +FUSE will return ENOSYS if any operation other than flush, fsync or +fsyncdir is not implemented. +.Pp +The first parameter to each of these operations (except for init and +terminate) is a NULL terminated string representing the full path to +the file or directory, relative to the root of this file system, that +is being operated on. .Bd -literal struct fuse_operations { int (*getattr)(const char *, struct stat *); @@ -123,6 +130,24 @@ creates and opens the file. There is no equivalent in the .Ox VFS. +.It flush +Called when the file is closed by the +.Xr close 2 +system call. +This is the only way for a file system to return an error on close. +.It fsync +Optional function that implements +.Xr fsync 2 +and +.Xr fdatasync 2 . +The datasync parameter specifies whether the operation is as a result +of a call to +.Xr fdatasync 2 +and is currently always 0 (false). +ffi.fh_id will contain the file handle returned by the file system when +the file was opened. +.It fsyncdir +Not implemented. .It getattr Corresponds to the .Xr stat 2 @@ -131,19 +156,9 @@ Flags and extended attributes are ignored. This operation is mandatory. .It getxattr Not implemented. -.It flush -Called when the file is closed by the -.Xr close 2 -system call. -This is the only way for a file system to return an error on close. .It getdir Deprecated. File system should implement readdir instead. -.It flush -Called when the file is closed by the -.Xr close 2 -system call. -This is the only way for a file system to return an error on close. .It mknod Called on .Xr open 2 @@ -195,7 +210,9 @@ This is always set on Similar to use_ino but the file system's inode number is only reported for readdir. This is always set on -.Ox . +.Ox +because it's required by +.Xr getcwd 3 . .It uid=%u The UID that will be reported as the owner for all files by getattr. .It umask=%o diff --git a/lib/libfuse/fuse_ops.c b/lib/libfuse/fuse_ops.c index 2a3b0b0f5d3..5e9ea7bd631 100644 --- a/lib/libfuse/fuse_ops.c +++ b/lib/libfuse/fuse_ops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_ops.c,v 1.34 2018/06/08 23:43:40 helg Exp $ */ +/* $OpenBSD: fuse_ops.c,v 1.35 2018/07/16 13:10:53 helg Exp $ */ /* * Copyright (c) 2013 Sylvestre Gallon * @@ -434,6 +434,42 @@ ifuse_ops_release(struct fuse *f, struct fusebuf *fbuf) return (0); } +static int +ifuse_ops_fsync(struct fuse *f, struct fusebuf *fbuf) +{ + struct fuse_file_info ffi; + struct fuse_vnode *vn; + char *realname; + int datasync; + + CHECK_OPT(fsync); + + memset(&ffi, 0, sizeof(ffi)); + ffi.fh = fbuf->fb_io_fd; + + /* + * fdatasync(2) is just a wrapper around fsync(2) so datasync + * is always false. + */ + datasync = 0; + + vn = tree_get(&f->vnode_tree, fbuf->fb_ino); + if (vn == NULL) { + fbuf->fb_err = -errno; + return (0); + } + + realname = build_realname(f, vn->ino); + if (realname == NULL) { + fbuf->fb_err = -errno; + return (0); + } + fbuf->fb_err = f->op.fsync(realname, datasync, &ffi); + free(realname); + + return (0); +} + static int ifuse_ops_flush(struct fuse *f, struct fusebuf *fbuf) { @@ -1095,6 +1131,9 @@ ifuse_exec_opcode(struct fuse *f, struct fusebuf *fbuf) case FBT_RELEASE: ret = ifuse_ops_release(f, fbuf); break; + case FBT_FSYNC: + ret = ifuse_ops_fsync(f, fbuf); + break; case FBT_FLUSH: ret = ifuse_ops_flush(f, fbuf); break; diff --git a/sys/miscfs/fuse/fuse_vnops.c b/sys/miscfs/fuse/fuse_vnops.c index 051c6335f26..b20f532ce25 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.49 2018/06/21 14:17:23 visa Exp $ */ +/* $OpenBSD: fuse_vnops.c,v 1.50 2018/07/16 13:10:53 helg Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon * @@ -66,6 +66,7 @@ int fusefs_lock(void *); int fusefs_unlock(void *); int fusefs_islocked(void *); int fusefs_advlock(void *); +int fusefs_fsync(void *); /* Prototypes for fusefs kqfilter */ int filt_fusefsread(struct knote *, long); @@ -87,7 +88,7 @@ struct vops fusefs_vops = { .vop_ioctl = fusefs_ioctl, .vop_poll = fusefs_poll, .vop_kqfilter = fusefs_kqfilter, - .vop_fsync = nullop, + .vop_fsync = fusefs_fsync, .vop_remove = fusefs_remove, .vop_link = fusefs_link, .vop_rename = fusefs_rename, @@ -1526,3 +1527,59 @@ fusefs_advlock(void *v) return (lf_advlock(&ip->ufs_ino.i_lockf, ip->filesize, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags)); } + +int +fusefs_fsync(void *v) +{ + struct vop_fsync_args *ap = v; + struct vnode *vp = ap->a_vp; + struct proc *p = ap->a_p; + struct fusefs_node *ip; + struct fusefs_mnt *fmp; + struct fusefs_filehandle *fufh; + struct fusebuf *fbuf; + int type, error = 0; + + /* + * Can't write to directory file handles so no need to fsync. + * FUSE has fsyncdir but it doesn't make sense on OpenBSD. + */ + if (vp->v_type == VDIR) + return (0); + + ip = VTOI(vp); + fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; + + if (!fmp->sess_init) + return (ENXIO); + + /* Implementing fsync is optional so don't error. */ + if (fmp->undef_op & UNDEF_FSYNC) + return (0); + + /* Sync all writeable file descriptors. */ + for (type = 0; type < FUFH_MAXTYPE; type++) { + fufh = &(ip->fufh[type]); + if (fufh->fh_type == FUFH_WRONLY || + fufh->fh_type == FUFH_RDWR) { + + fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_FSYNC, p); + fbuf->fb_io_fd = fufh->fh_id; + + /* Always behave as if ap->a_waitfor = MNT_WAIT. */ + error = fb_queue(fmp->dev, fbuf); + fb_delete(fbuf); + if (error) + break; + } + } + + if (error == ENOSYS) { + fmp->undef_op |= UNDEF_FSYNC; + + /* Implementing fsync is optional so don't error. */ + return (0); + } + + return (error); +} diff --git a/sys/miscfs/fuse/fusefs.h b/sys/miscfs/fuse/fusefs.h index c0b3fb89126..237ef0578f2 100644 --- a/sys/miscfs/fuse/fusefs.h +++ b/sys/miscfs/fuse/fusefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: fusefs.h,v 1.12 2018/06/25 12:03:53 helg Exp $ */ +/* $OpenBSD: fusefs.h,v 1.13 2018/07/16 13:10:53 helg Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon * @@ -68,6 +68,7 @@ struct fusefs_mnt { #define UNDEF_SYMLINK 1<<9 #define UNDEF_MKNOD 1<<10 #define UNDEF_FLUSH 1<<11 +#define UNDEF_FSYNC 1<<12 extern struct vops fusefs_vops; extern struct pool fusefs_fbuf_pool;