-.\" $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 <ccna.syl@gmail.com>
.\" Copyright (c) 2018 Helg Bredow <helg@openbsd.org>
.\" 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
.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 *);
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
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
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
-/* $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 <ccna.syl@gmail.com>
*
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)
{
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;
-/* $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 <ccna.syl@gmail.com>
*
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);
.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,
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);
+}
-/* $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 <ccna.syl@gmail.com>
*
#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;