Date: Wed, 7 Aug 2019 10:49:12 -0500 From: Pedro Giffuni <pfg@FreeBSD.org> To: Alan Somers <asomers@FreeBSD.org>, src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r350665 - in head: . etc/mtree sbin/mount_fusefs share/man/man5 sys/fs/fuse sys/sys tests/sys/fs tests/sys/fs/fusefs Message-ID: <6c7f7b6f-c0e3-e99c-bd00-8c5a8f729c23@FreeBSD.org> In-Reply-To: <201908070038.x770cQZE007711@repo.freebsd.org> References: <201908070038.x770cQZE007711@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Awesome work. Thanks! On 06/08/2019 19:38, Alan Somers wrote: > Author: asomers > Date: Wed Aug 7 00:38:26 2019 > New Revision: 350665 > URL: https://svnweb.freebsd.org/changeset/base/350665 > > Log: > fusefs: merge from projects/fuse2 > > This commit imports the new fusefs driver. It raises the protocol level > from 7.8 to 7.23, fixes many bugs, adds a test suite for the driver, and > adds many new features. New features include: > > * Optional kernel-side permissions checks (-o default_permissions) > * Implement VOP_MKNOD, VOP_BMAP, and VOP_ADVLOCK > * Allow interrupting FUSE operations > * Support named pipes and unix-domain sockets in fusefs file systems > * Forward UTIME_NOW during utimensat(2) to the daemon > * kqueue support for /dev/fuse > * Allow updating mounts with "mount -u" > * Allow exporting fusefs file systems over NFS > * Server-initiated invalidation of the name cache or data cache > * Respect RLIMIT_FSIZE > * Try to support servers as old as protocol 7.4 > > Performance enhancements include: > > * Implement FUSE's FOPEN_KEEP_CACHE and FUSE_ASYNC_READ flags > * Cache file attributes > * Cache lookup entries, both positive and negative > * Server-selectable cache modes: writethrough, writeback, or uncached > * Write clustering > * Readahead > * Use counter(9) for statistical reporting > > PR: 199934 216391 233783 234581 235773 235774 235775 > PR: 236226 236231 236236 236291 236329 236381 236405 > PR: 236327 236466 236472 236473 236474 236530 236557 > PR: 236560 236844 237052 237181 237588 238565 > Reviewed by: bcr (man pages) > Reviewed by: cem, ngie, rpokala, glebius, kib, bde, emaste (post-commit > review on project branch) > MFC after: 3 weeks > Relnotes: yes > Sponsored by: The FreeBSD Foundation > Pull Request: https://reviews.freebsd.org/D21110 > > Added: > head/tests/sys/fs/fusefs/ > - copied from r350621, projects/fuse2/tests/sys/fs/fusefs/ > Deleted: > head/sys/fs/fuse/fuse_param.h > Modified: > head/MAINTAINERS (contents, props changed) > head/UPDATING > head/etc/mtree/BSD.tests.dist > head/sbin/mount_fusefs/mount_fusefs.8 > head/sbin/mount_fusefs/mount_fusefs.c > head/share/man/man5/fusefs.5 > head/sys/fs/fuse/fuse.h > head/sys/fs/fuse/fuse_device.c > head/sys/fs/fuse/fuse_file.c > head/sys/fs/fuse/fuse_file.h > head/sys/fs/fuse/fuse_internal.c > head/sys/fs/fuse/fuse_internal.h > head/sys/fs/fuse/fuse_io.c > head/sys/fs/fuse/fuse_io.h > head/sys/fs/fuse/fuse_ipc.c > head/sys/fs/fuse/fuse_ipc.h > head/sys/fs/fuse/fuse_kernel.h > head/sys/fs/fuse/fuse_main.c > head/sys/fs/fuse/fuse_node.c > head/sys/fs/fuse/fuse_node.h > head/sys/fs/fuse/fuse_vfsops.c > head/sys/fs/fuse/fuse_vnops.c > head/sys/sys/param.h > head/tests/sys/fs/Makefile > Directory Properties: > head/ (props changed) > > Modified: head/MAINTAINERS > ============================================================================== > --- head/MAINTAINERS Tue Aug 6 23:22:25 2019 (r350664) > +++ head/MAINTAINERS Wed Aug 7 00:38:26 2019 (r350665) > @@ -53,6 +53,7 @@ contrib/pjdfstest asomers,ngie,pjd,#test Pre-commit re > etc/mail gshapiro Pre-commit review requested. Keep in sync with -STABLE. > etc/sendmail gshapiro Pre-commit review requested. Keep in sync with -STABLE. > fetch des Pre-commit review requested, email only. > +fusefs(5) asomers Pre-commit review requested. > geli pjd Pre-commit review requested (both sys/geom/eli/ and sbin/geom/class/eli/). > isci(4) jimharris Pre-commit review requested. > iwm(4) adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org > > Modified: head/UPDATING > ============================================================================== > --- head/UPDATING Tue Aug 6 23:22:25 2019 (r350664) > +++ head/UPDATING Wed Aug 7 00:38:26 2019 (r350665) > @@ -26,6 +26,18 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW: > disable the most expensive debugging functionality run > "ln -s 'abort:false,junk:false' /etc/malloc.conf".) > > +20190727: > + The vfs.fusefs.sync_unmount and vfs.fusefs.init_backgrounded sysctls > + and the "-o sync_unmount" and "-o init_backgrounded" mount options have > + been removed from mount_fusefs(8). You can safely remove them from > + your scripts, because they had no effect. > + > + The vfs.fusefs.fix_broken_io, vfs.fusefs.sync_resize, > + vfs.fusefs.refresh_size, vfs.fusefs.mmap_enable, > + vfs.fusefs.reclaim_revoked, and vfs.fusefs.data_cache_invalidate > + sysctls have been removed. If you felt the need to set any of them to > + a non-default value, please tell asomers@FreeBSD.org why. > + > 20190713: > Default permissions on the /var/account/acct file (and copies of it > rotated by periodic daily scripts) are changed from 0644 to 0640 > > Modified: head/etc/mtree/BSD.tests.dist > ============================================================================== > --- head/etc/mtree/BSD.tests.dist Tue Aug 6 23:22:25 2019 (r350664) > +++ head/etc/mtree/BSD.tests.dist Wed Aug 7 00:38:26 2019 (r350665) > @@ -731,6 +731,8 @@ > file > .. > fs > + fusefs > + .. > tmpfs > .. > .. > > Modified: head/sbin/mount_fusefs/mount_fusefs.8 > ============================================================================== > --- head/sbin/mount_fusefs/mount_fusefs.8 Tue Aug 6 23:22:25 2019 (r350664) > +++ head/sbin/mount_fusefs/mount_fusefs.8 Wed Aug 7 00:38:26 2019 (r350665) > @@ -3,6 +3,11 @@ > .\" Copyright (c) 2005, 2006 Csaba Henk > .\" All rights reserved. > .\" > +.\" Copyright (c) 2019 The FreeBSD Foundation > +.\" > +.\" Portions of this documentation were written by BFF Storage Systems under > +.\" sponsorship from the FreeBSD Foundation. > +.\" > .\" Redistribution and use in source and binary forms, with or without > .\" modification, are permitted provided that the following conditions > .\" are met: > @@ -29,7 +34,7 @@ > .\" > .\" $FreeBSD$ > .\" > -.Dd November 17, 2018 > +.Dd July 31, 2019 > .Dt MOUNT_FUSEFS 8 > .Os > .Sh NAME > @@ -108,27 +113,27 @@ Intended for use in scripts and the > .Xr sudoers 5 > file. > .It Fl S , Ic --safe > -Run in safe mode (i.e. reject invoking a filesystem daemon) > +Run in safe mode (i.e., reject invoking a filesystem daemon). > .It Fl v > -Be verbose > -.It Fl D, Ic --daemon Ar daemon > +Be verbose. > +.It Fl D , Ic --daemon Ar daemon > Call the specified > -.Ar daemon > -.It Fl O, Ic --daemon_opts Ar opts > +.Ar daemon . > +.It Fl O , Ic --daemon_opts Ar opts > Add > .Ar opts > -to the daemon's command line > -.It Fl s, Ic --special Ar special > +to the daemon's command line. > +.It Fl s , Ic --special Ar special > Use > .Ar special > -as special > -.It Fl m, Ic --mountpath Ar node > +as special. > +.It Fl m , Ic --mountpath Ar node > Mount on > -.Ar node > -.It Fl h, Ic --help > -Show help > -.It Fl V, Ic --version > -Show version information > +.Ar node . > +.It Fl h , Ic --help > +Show help. > +.It Fl V , Ic --version > +Show version information. > .It Fl o > Mount options are specified via > .Fl o . > @@ -136,23 +141,38 @@ The following options are available (and also their ne > by prefixing them with > .Dq no ) : > .Bl -tag -width indent > -.It Cm default_permissions > -Enable traditional (file mode based) permission checking in kernel > .It Cm allow_other > Do not apply > .Sx STRICT ACCESS POLICY . > -Only root can use this option > +Only root can use this option. > +.It Cm async > +I/O to the file system may be done asynchronously. > +Writes may be delayed and/or reordered. > +.It Cm default_permissions > +Enable traditional (file mode based) permission checking in kernel. > +.It Cm intr > +Allow signals to interrupt operations that are blocked waiting for a reply from the server. > +When this option is in use, system calls may fail with > +.Er EINTR > +whenever a signal is received. > .It Cm max_read Ns = Ns Ar n > Limit size of read requests to > -.Ar n > +.Ar n . > +.It Cm neglect_shares > +Do not refuse unmounting if there are secondary mounts. > .It Cm private > Refuse shared mounting of the daemon. > This is the default behaviour, to allow sharing, expicitly use > -.Fl o Cm noprivate > -.It Cm neglect_shares > -Do not refuse unmounting if there are secondary mounts > +.Fl o Cm noprivate . > .It Cm push_symlinks_in > -Prefix absolute symlinks with the mountpoint > +Prefix absolute symlinks with the mountpoint. > +.It Cm subtype Ns = Ns Ar fsname > +Suffix > +.Ar fsname > +to the file system name as reported by > +.Xr statfs 2 . > +This option can be used to identify the file system implemented by > +.Ar fuse_daemon . > .El > .El > .Pp > @@ -167,11 +187,11 @@ However, there are some which do require in-kernel sup > Currently the options supported by the kernel are: > .Bl -tag -width indent > .It Cm direct_io > -Bypass the buffer cache system > +Bypass the buffer cache system. > .It Cm kernel_cache > By default cached buffers of a given file are flushed at each > .Xr open 2 . > -This option disables this behaviour > +This option disables this behaviour. > .El > .Sh DAEMON MOUNTS > Usually users do not need to use > @@ -194,7 +214,7 @@ only if the filesystem daemon has the same credentials > real gid) as the user. > .Pp > This is applied for Fuse mounts by default and only root can mount without > -the strict access policy (i.e. the > +the strict access policy (i.e., the > .Cm allow_other > mount option). > .Pp > @@ -206,7 +226,7 @@ Users might opt to willingly relax strict access polic > are concerned) by doing their own secondary mount (See > .Sx SHARED MOUNTS ) . > .Sh SHARED MOUNTS > -A Fuse daemon can be shared (i.e. mounted multiple times). > +A Fuse daemon can be shared (i.e., mounted multiple times). > When doing the first (primary) mount, the spawner and the mounter of the daemon > must have the same uid, or the mounter should be the superuser. > .Pp > @@ -225,7 +245,7 @@ is used or not. > .Pp > The device name of a secondary mount is the device name of the corresponding > primary mount, followed by a '#' character and the index of the secondary > -mount; e.g. > +mount; e.g., > .Pa /dev/fuse0#3 . > .Sh SECURITY > System administrators might want to use a custom mount policy (ie., one going > @@ -239,7 +259,7 @@ However, given that > is capable of invoking an arbitrary program, one must be careful when doing this. > .Nm > is designed in a way such that it makes that easy. > -For this purpose, there are options which disable certain risky features (i.e. > +For this purpose, there are options which disable certain risky features ( > .Fl S > and > .Fl A ) , > @@ -342,7 +362,7 @@ does not call any external utility and also provides a > was written as the part of the > .Fx > implementation of the Fuse userspace filesystem framework (see > -.Xr https://github.com/libfuse/libfuse ) > +.Lk https://github.com/libfuse/libfuse ) > and first appeared in the > .Pa sysutils/fusefs-kmod > port, supporting > > Modified: head/sbin/mount_fusefs/mount_fusefs.c > ============================================================================== > --- head/sbin/mount_fusefs/mount_fusefs.c Tue Aug 6 23:22:25 2019 (r350664) > +++ head/sbin/mount_fusefs/mount_fusefs.c Wed Aug 7 00:38:26 2019 (r350665) > @@ -5,6 +5,11 @@ > * Copyright (c) 2005 Csaba Henk > * All rights reserved. > * > + * Copyright (c) 2019 The FreeBSD Foundation > + * > + * Portions of this software were developed by BFF Storage Systems under > + * sponsorship from the FreeBSD Foundation. > + * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > @@ -60,7 +65,6 @@ void __usage_short(void); > void usage(void); > void helpmsg(void); > void showversion(void); > -int init_backgrounded(void); > > static struct mntopt mopts[] = { > #define ALTF_PRIVATE 0x01 > @@ -73,8 +77,6 @@ static struct mntopt mopts[] = { > { "max_read=", 0, ALTF_MAXREAD, 1 }, > #define ALTF_SUBTYPE 0x40 > { "subtype=", 0, ALTF_SUBTYPE, 1 }, > - #define ALTF_SYNC_UNMOUNT 0x80 > - { "sync_unmount", 0, ALTF_SYNC_UNMOUNT, 1 }, > /* > * MOPT_AUTOMOUNTED, included by MOPT_STDOPTS, does not fit into > * the 'flags' argument to nmount(2). We have to abuse altflags > @@ -82,6 +84,8 @@ static struct mntopt mopts[] = { > */ > #define ALTF_AUTOMOUNTED 0x100 > { "automounted", 0, ALTF_AUTOMOUNTED, 1 }, > + #define ALTF_INTR 0x200 > + { "intr", 0, ALTF_INTR, 1 }, > /* Linux specific options, we silently ignore them */ > { "fsname=", 0, 0x00, 1 }, > { "fd=", 0, 0x00, 1 }, > @@ -91,6 +95,8 @@ static struct mntopt mopts[] = { > { "large_read", 0, 0x00, 1 }, > /* "nonempty", just the first two chars are stripped off during parsing */ > { "nempty", 0, 0x00, 1 }, > + { "async", 0, MNT_ASYNC, 0}, > + { "noasync", 1, MNT_ASYNC, 0}, > MOPT_STDOPTS, > MOPT_END > }; > @@ -107,7 +113,7 @@ static struct mntval mvals[] = { > { 0, NULL, 0 } > }; > > -#define DEFAULT_MOUNT_FLAGS ALTF_PRIVATE | ALTF_SYNC_UNMOUNT > +#define DEFAULT_MOUNT_FLAGS ALTF_PRIVATE > > int > main(int argc, char *argv[]) > @@ -409,12 +415,6 @@ main(int argc, char *argv[]) > } > } > > - if (fd >= 0 && ! init_backgrounded() && close(fd) < 0) { > - if (pid) > - kill(pid, SIGKILL); > - err(1, "failed to close fuse device"); > - } > - > /* Prepare the options vector for nmount(). build_iovec() is declared > * in mntopts.h. */ > sprintf(fdstr, "%d", fd); > @@ -471,6 +471,7 @@ helpmsg(void) > " -o allow_other allow access to other users\n" > /* " -o nonempty allow mounts over non-empty file/dir\n" */ > " -o default_permissions enable permission checking by kernel\n" > + " -o intr interruptible mount\n" > /* > " -o fsname=NAME set filesystem name\n" > " -o large_read issue large read requests (2.4 only)\n" > @@ -481,7 +482,6 @@ helpmsg(void) > " -o neglect_shares don't report EBUSY when unmount attempted\n" > " in presence of secondary mounts\n" > " -o push_symlinks_in prefix absolute symlinks with mountpoint\n" > - " -o sync_unmount do unmount synchronously\n" > ); > exit(EX_USAGE); > } > @@ -491,18 +491,4 @@ showversion(void) > { > puts("mount_fusefs [fuse4bsd] version: " FUSE4BSD_VERSION); > exit(EX_USAGE); > -} > - > -int > -init_backgrounded(void) > -{ > - int ibg; > - size_t len; > - > - len = sizeof(ibg); > - > - if (sysctlbyname("vfs.fusefs.init_backgrounded", &ibg, &len, NULL, 0)) > - return (0); > - > - return (ibg); > } > > Modified: head/share/man/man5/fusefs.5 > ============================================================================== > --- head/share/man/man5/fusefs.5 Tue Aug 6 23:22:25 2019 (r350664) > +++ head/share/man/man5/fusefs.5 Wed Aug 7 00:38:26 2019 (r350665) > @@ -3,8 +3,8 @@ > .\" > .\" Copyright (c) 2019 The FreeBSD Foundation > .\" > -.\" This software was developed by BFF Storage Systems, LLC under sponsorship > -.\" from the FreeBSD Foundation. > +.\" This documentation was written by BFF Storage Systems, LLC under > +.\" sponsorship from the FreeBSD Foundation. > .\" > .\" Redistribution and use in source and binary forms, with or without > .\" modification, are permitted provided that the following conditions > @@ -28,7 +28,7 @@ > .\" SUCH DAMAGE. > .\" > .\" $FreeBSD$ > -.Dd April 13, 2019 > +.Dd July 31, 2019 > .Dt FUSEFS 5 > .Os > .Sh NAME > @@ -60,11 +60,9 @@ Finally, the > API is portable. > Many daemons can run on multiple operating systems with minimal modifications. > .Sh SYSCTL VARIABLES > -The following variables are available as both > +The following > .Xr sysctl 8 > -variables and > -.Xr loader 8 > -tunables: > +variables are available: > .Bl -tag -width indent > .It Va vfs.fusefs.kernelabi_major > Major version of the FUSE kernel ABI supported by this driver. > @@ -73,7 +71,7 @@ Minor version of the FUSE kernel ABI supported by this > .It Va vfs.fusefs.data_cache_mode > Controls how > .Nm > -will cache file data. > +will cache file data for pre-7.23 file systems. > A value of 0 will disable caching entirely. > Every data access will be forwarded to the daemon. > A value of 1 will select write-through caching. > @@ -84,33 +82,26 @@ Reads and writes will both be cached, and writes will > to the daemon by the page daemon. > Write-back caching is usually unsafe, especially for FUSE file systems that > require network access. > -.It Va vfs.fusefs.lookup_cache_enable > -Controls whether > -.Nm > -will cache lookup responses from the file system. > -FUSE file systems indicate whether lookup responses should be cacheable, but > -it may be useful to globally disable caching them if a file system is > -misbehaving. > +.Pp > +FUSE file systems using protocol 7.23 or later specify their cache behavior > +on a per-mountpoint basis, ignoring this sysctl. > +.It Va vfs.fusefs.stats.filehandle_count > +Current number of open FUSE file handles. > +.It Va vfs.fusefs.stats.lookup_cache_hits > +Total number of lookup cache hits. > +.It Va vfs.fusefs.stats.lookup_cache_misses > +Total number of lookup cache misses. > +.It Va vfs.fusefs.stats.node_count > +Current number of allocated FUSE vnodes. > +.It Va vfs.fusefs.stats.ticket_count > +Current number of allocated FUSE tickets, which is roughly equal to the number > +of FUSE operations currently being processed by daemons. > .\" Undocumented sysctls > .\" ==================== > -.\" Counters: I intend to rename to vfs.fusefs.stats.* for clarity > -.\" vfs.fusefs.lookup_cache_{hits, misses} > -.\" vfs.fusefs.filehandle_count > -.\" vfs.fusefs.ticker_count > -.\" vfs.fusefs.node_count > -.\" > -.\" vfs.fusefs.version - useless since the driver moved in-tree > -.\" vfs.fusefs.reclaim_revoked: I don't understand it well-enough > -.\" vfs.fusefs.sync_unmount: dead code > .\" vfs.fusefs.enforce_dev_perms: I don't understand it well enough. > -.\" vfs.fusefs.init_backgrounded: dead code > .\" vfs.fusefs.iov_credit: I don't understand it well enough > .\" vfs.fusefs.iov_permanent_bufsize: I don't understand it well enough > -.\" vfs.fusefs.fix_broken_io: I don't understand it well enough > -.\" vfs.fusefs.sync_resize: useless and should be removed > -.\" vfs.fusefs.refresh_size: probably useless? > -.\" vfs.fusefs.mmap_enable: why is this optional? > -.\" vfs.fusefs.data_cache_invalidate: what is this needed for? > +.El > .Sh SEE ALSO > .Xr mount_fusefs 8 > .Sh HISTORY > @@ -119,7 +110,7 @@ The > driver was written as the part of the > .Fx > implementation of the FUSE userspace file system framework (see > -.Xr https://github.com/libfuse/libfuse ) > +.Lk https://github.com/libfuse/libfuse ) > and first appeared in the > .Pa sysutils/fusefs-kmod > port, supporting > > Modified: head/sys/fs/fuse/fuse.h > ============================================================================== > --- head/sys/fs/fuse/fuse.h Tue Aug 6 23:22:25 2019 (r350664) > +++ head/sys/fs/fuse/fuse.h Wed Aug 7 00:38:26 2019 (r350665) > @@ -32,6 +32,11 @@ > * > * Copyright (C) 2005 Csaba Henk. > * All rights reserved. > + * > + * Copyright (c) 2019 The FreeBSD Foundation > + * > + * Portions of this software were developed by BFF Storage Systems, LLC under > + * sponsorship from the FreeBSD Foundation. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > @@ -63,87 +68,10 @@ > #define FUSE_MIN_DAEMON_TIMEOUT 0 /* s */ > #define FUSE_MAX_DAEMON_TIMEOUT 600 /* s */ > > -#ifndef FUSE_FREEBSD_VERSION > -#define FUSE_FREEBSD_VERSION "0.4.4" > -#endif > - > -/* Mapping versions to features */ > - > -#define FUSE_KERNELABI_GEQ(maj, min) \ > -(FUSE_KERNEL_VERSION > (maj) || (FUSE_KERNEL_VERSION == (maj) && FUSE_KERNEL_MINOR_VERSION >= (min))) > - > -/* > - * Appearance of new FUSE operations is not always in par with version > - * numbering... At least, 7.3 is a sufficient condition for having > - * FUSE_{ACCESS,CREATE}. > - */ > -#if FUSE_KERNELABI_GEQ(7, 3) > -#ifndef FUSE_HAS_ACCESS > -#define FUSE_HAS_ACCESS 1 > -#endif > -#ifndef FUSE_HAS_CREATE > -#define FUSE_HAS_CREATE 1 > -#endif > -#else /* FUSE_KERNELABI_GEQ(7, 3) */ > -#ifndef FUSE_HAS_ACCESS > -#define FUSE_HAS_ACCESS 0 > -#endif > -#ifndef FUSE_HAS_CREATE > -#define FUSE_HAS_CREATE 0 > -#endif > -#endif > - > -#if FUSE_KERNELABI_GEQ(7, 7) > -#ifndef FUSE_HAS_GETLK > -#define FUSE_HAS_GETLK 1 > -#endif > -#ifndef FUSE_HAS_SETLK > -#define FUSE_HAS_SETLK 1 > -#endif > -#ifndef FUSE_HAS_SETLKW > -#define FUSE_HAS_SETLKW 1 > -#endif > -#ifndef FUSE_HAS_INTERRUPT > -#define FUSE_HAS_INTERRUPT 1 > -#endif > -#else /* FUSE_KERNELABI_GEQ(7, 7) */ > -#ifndef FUSE_HAS_GETLK > -#define FUSE_HAS_GETLK 0 > -#endif > -#ifndef FUSE_HAS_SETLK > -#define FUSE_HAS_SETLK 0 > -#endif > -#ifndef FUSE_HAS_SETLKW > -#define FUSE_HAS_SETLKW 0 > -#endif > -#ifndef FUSE_HAS_INTERRUPT > -#define FUSE_HAS_INTERRUPT 0 > -#endif > -#endif > - > -#if FUSE_KERNELABI_GEQ(7, 8) > -#ifndef FUSE_HAS_FLUSH_RELEASE > -#define FUSE_HAS_FLUSH_RELEASE 1 > -/* > - * "DESTROY" came in the middle of the 7.8 era, > - * so this is not completely exact... > - */ > -#ifndef FUSE_HAS_DESTROY > -#define FUSE_HAS_DESTROY 1 > -#endif > -#endif > -#else /* FUSE_KERNELABI_GEQ(7, 8) */ > -#ifndef FUSE_HAS_FLUSH_RELEASE > -#define FUSE_HAS_FLUSH_RELEASE 0 > -#ifndef FUSE_HAS_DESTROY > -#define FUSE_HAS_DESTROY 0 > -#endif > -#endif > -#endif > - > /* misc */ > > SYSCTL_DECL(_vfs_fusefs); > +SYSCTL_DECL(_vfs_fusefs_stats); > > /* Fuse locking */ > > > Modified: head/sys/fs/fuse/fuse_device.c > ============================================================================== > --- head/sys/fs/fuse/fuse_device.c Tue Aug 6 23:22:25 2019 (r350664) > +++ head/sys/fs/fuse/fuse_device.c Wed Aug 7 00:38:26 2019 (r350665) > @@ -33,6 +33,11 @@ > * Copyright (C) 2005 Csaba Henk. > * All rights reserved. > * > + * Copyright (c) 2019 The FreeBSD Foundation > + * > + * Portions of this software were developed by BFF Storage Systems, LLC under > + * sponsorship from the FreeBSD Foundation. > + * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > @@ -81,27 +86,28 @@ __FBSDID("$FreeBSD$"); > #include <sys/selinfo.h> > > #include "fuse.h" > +#include "fuse_internal.h" > #include "fuse_ipc.h" > > -SDT_PROVIDER_DECLARE(fuse); > +SDT_PROVIDER_DECLARE(fusefs); > /* > * Fuse trace probe: > * arg0: verbosity. Higher numbers give more verbose messages > * arg1: Textual message > */ > -SDT_PROBE_DEFINE2(fuse, , device, trace, "int", "char*"); > +SDT_PROBE_DEFINE2(fusefs, , device, trace, "int", "char*"); > > static struct cdev *fuse_dev; > > +static d_kqfilter_t fuse_device_filter; > static d_open_t fuse_device_open; > -static d_close_t fuse_device_close; > static d_poll_t fuse_device_poll; > static d_read_t fuse_device_read; > static d_write_t fuse_device_write; > > static struct cdevsw fuse_device_cdevsw = { > + .d_kqfilter = fuse_device_filter, > .d_open = fuse_device_open, > - .d_close = fuse_device_close, > .d_name = "fuse", > .d_poll = fuse_device_poll, > .d_read = fuse_device_read, > @@ -109,6 +115,15 @@ static struct cdevsw fuse_device_cdevsw = { > .d_version = D_VERSION, > }; > > +static int fuse_device_filt_read(struct knote *kn, long hint); > +static void fuse_device_filt_detach(struct knote *kn); > + > +struct filterops fuse_device_rfiltops = { > + .f_isfd = 1, > + .f_detach = fuse_device_filt_detach, > + .f_event = fuse_device_filt_read, > +}; > + > /**************************** > * > * >>> Fuse device op defs > @@ -119,11 +134,100 @@ static void > fdata_dtor(void *arg) > { > struct fuse_data *fdata; > + struct fuse_ticket *tick; > > fdata = arg; > + if (fdata == NULL) > + return; > + > + fdata_set_dead(fdata); > + > + FUSE_LOCK(); > + fuse_lck_mtx_lock(fdata->aw_mtx); > + /* wakup poll()ers */ > + selwakeuppri(&fdata->ks_rsel, PZERO + 1); > + /* Don't let syscall handlers wait in vain */ > + while ((tick = fuse_aw_pop(fdata))) { > + fuse_lck_mtx_lock(tick->tk_aw_mtx); > + fticket_set_answered(tick); > + tick->tk_aw_errno = ENOTCONN; > + wakeup(tick); > + fuse_lck_mtx_unlock(tick->tk_aw_mtx); > + FUSE_ASSERT_AW_DONE(tick); > + fuse_ticket_drop(tick); > + } > + fuse_lck_mtx_unlock(fdata->aw_mtx); > + > + /* Cleanup unsent operations */ > + fuse_lck_mtx_lock(fdata->ms_mtx); > + while ((tick = fuse_ms_pop(fdata))) { > + fuse_ticket_drop(tick); > + } > + fuse_lck_mtx_unlock(fdata->ms_mtx); > + FUSE_UNLOCK(); > + > fdata_trydestroy(fdata); > } > > +static int > +fuse_device_filter(struct cdev *dev, struct knote *kn) > +{ > + struct fuse_data *data; > + int error; > + > + error = devfs_get_cdevpriv((void **)&data); > + > + /* EVFILT_WRITE is not supported; the device is always ready to write */ > + if (error == 0 && kn->kn_filter == EVFILT_READ) { > + kn->kn_fop = &fuse_device_rfiltops; > + kn->kn_hook = data; > + knlist_add(&data->ks_rsel.si_note, kn, 0); > + error = 0; > + } else if (error == 0) { > + error = EINVAL; > + kn->kn_data = error; > + } > + > + return (error); > +} > + > +static void > +fuse_device_filt_detach(struct knote *kn) > +{ > + struct fuse_data *data; > + > + data = (struct fuse_data*)kn->kn_hook; > + MPASS(data != NULL); > + knlist_remove(&data->ks_rsel.si_note, kn, 0); > + kn->kn_hook = NULL; > +} > + > +static int > +fuse_device_filt_read(struct knote *kn, long hint) > +{ > + struct fuse_data *data; > + int ready; > + > + data = (struct fuse_data*)kn->kn_hook; > + MPASS(data != NULL); > + > + mtx_assert(&data->ms_mtx, MA_OWNED); > + if (fdata_get_dead(data)) { > + kn->kn_flags |= EV_EOF; > + kn->kn_fflags = ENODEV; > + kn->kn_data = 1; > + ready = 1; > + } else if (STAILQ_FIRST(&data->ms_head)) { > + MPASS(data->ms_count >= 1); > + kn->kn_data = data->ms_count; > + ready = 1; > + } else { > + ready = 0; > + } > + > + return (ready); > +} > + > /* > * Resources are set up on a per-open basis > */ > @@ -133,52 +237,17 @@ fuse_device_open(struct cdev *dev, int oflags, int dev > struct fuse_data *fdata; > int error; > > - SDT_PROBE2(fuse, , device, trace, 1, "device open"); > + SDT_PROBE2(fusefs, , device, trace, 1, "device open"); > > fdata = fdata_alloc(dev, td->td_ucred); > error = devfs_set_cdevpriv(fdata, fdata_dtor); > if (error != 0) > fdata_trydestroy(fdata); > else > - SDT_PROBE2(fuse, , device, trace, 1, "device open success"); > + SDT_PROBE2(fusefs, , device, trace, 1, "device open success"); > return (error); > } > > -static int > -fuse_device_close(struct cdev *dev, int fflag, int devtype, struct thread *td) > -{ > - struct fuse_data *data; > - struct fuse_ticket *tick; > - int error; > - > - error = devfs_get_cdevpriv((void **)&data); > - if (error != 0) > - return (error); > - if (!data) > - panic("no fuse data upon fuse device close"); > - fdata_set_dead(data); > - > - FUSE_LOCK(); > - fuse_lck_mtx_lock(data->aw_mtx); > - /* wakup poll()ers */ > - selwakeuppri(&data->ks_rsel, PZERO + 1); > - /* Don't let syscall handlers wait in vain */ > - while ((tick = fuse_aw_pop(data))) { > - fuse_lck_mtx_lock(tick->tk_aw_mtx); > - fticket_set_answered(tick); > - tick->tk_aw_errno = ENOTCONN; > - wakeup(tick); > - fuse_lck_mtx_unlock(tick->tk_aw_mtx); > - FUSE_ASSERT_AW_DONE(tick); > - fuse_ticket_drop(tick); > - } > - fuse_lck_mtx_unlock(data->aw_mtx); > - FUSE_UNLOCK(); > - > - SDT_PROBE2(fuse, , device, trace, 1, "device close"); > - return (0); > -} > - > int > fuse_device_poll(struct cdev *dev, int events, struct thread *td) > { > @@ -219,7 +288,7 @@ fuse_device_read(struct cdev *dev, struct uio *uio, in > int buflen[3]; > int i; > > - SDT_PROBE2(fuse, , device, trace, 1, "fuse device read"); > + SDT_PROBE2(fusefs, , device, trace, 1, "fuse device read"); > > err = devfs_get_cdevpriv((void **)&data); > if (err != 0) > @@ -228,7 +297,7 @@ fuse_device_read(struct cdev *dev, struct uio *uio, in > fuse_lck_mtx_lock(data->ms_mtx); > again: > if (fdata_get_dead(data)) { > - SDT_PROBE2(fuse, , device, trace, 2, > + SDT_PROBE2(fusefs, , device, trace, 2, > "we know early on that reader should be kicked so we " > "don't wait for news"); > fuse_lck_mtx_unlock(data->ms_mtx); > @@ -256,7 +325,7 @@ again: > * -- and some other cases, too, tho not totally clear, when > * (cv_signal/wakeup_one signals the whole process ?) > */ > - SDT_PROBE2(fuse, , device, trace, 1, "no message on thread"); > + SDT_PROBE2(fusefs, , device, trace, 1, "no message on thread"); > goto again; > } > fuse_lck_mtx_unlock(data->ms_mtx); > @@ -266,9 +335,10 @@ again: > * somebody somewhere -- eg., umount routine -- > * wants this liaison finished off > */ > - SDT_PROBE2(fuse, , device, trace, 2, "reader is to be sacked"); > + SDT_PROBE2(fusefs, , device, trace, 2, > + "reader is to be sacked"); > if (tick) { > - SDT_PROBE2(fuse, , device, trace, 2, "weird -- " > + SDT_PROBE2(fusefs, , device, trace, 2, "weird -- " > "\"kick\" is set tho there is message"); > FUSE_ASSERT_MS_DONE(tick); > fuse_ticket_drop(tick); > @@ -276,7 +346,7 @@ again: > return (ENODEV); /* This should make the daemon get off > * of us */ > } > - SDT_PROBE2(fuse, , device, trace, 1, > + SDT_PROBE2(fusefs, , device, trace, 1, > "fuse device read message successfully"); > > KASSERT(tick->tk_ms_bufdata || tick->tk_ms_bufsize == 0, > @@ -311,7 +381,7 @@ again: > */ > if (uio->uio_resid < buflen[i]) { > fdata_set_dead(data); > - SDT_PROBE2(fuse, , device, trace, 2, > + SDT_PROBE2(fusefs, , device, trace, 2, > "daemon is stupid, kick it off..."); > err = ENODEV; > break; > @@ -331,23 +401,26 @@ static inline int > fuse_ohead_audit(struct fuse_out_header *ohead, struct uio *uio) > { > if (uio->uio_resid + sizeof(struct fuse_out_header) != ohead->len) { > - SDT_PROBE2(fuse, , device, trace, 1, "Format error: body size " > + SDT_PROBE2(fusefs, , device, trace, 1, > + "Format error: body size " > "differs from size claimed by header"); > return (EINVAL); > } > - if (uio->uio_resid && ohead->error) { > - SDT_PROBE2(fuse, , device, trace, 1, > + if (uio->uio_resid && ohead->unique != 0 && ohead->error) { > + SDT_PROBE2(fusefs, , device, trace, 1, > "Format error: non zero error but message had a body"); > return (EINVAL); > } > - /* Sanitize the linuxism of negative errnos */ > - ohead->error = -(ohead->error); > > return (0); > } > > -SDT_PROBE_DEFINE1(fuse, , device, fuse_device_write_bumped_into_callback, > - "uint64_t"); > +SDT_PROBE_DEFINE1(fusefs, , device, fuse_device_write_notify, > + "struct fuse_out_header*"); > +SDT_PROBE_DEFINE1(fusefs, , device, fuse_device_write_missing_ticket, > + "uint64_t"); > +SDT_PROBE_DEFINE1(fusefs, , device, fuse_device_write_found, > + "struct fuse_ticket*"); > /* > * fuse_device_write first reads the header sent by the daemon. > * If that's OK, looks up ticket/callback node by the unique id seen in header. > @@ -360,15 +433,17 @@ fuse_device_write(struct cdev *dev, struct uio *uio, i > struct fuse_out_header ohead; > int err = 0; > struct fuse_data *data; > - struct fuse_ticket *tick, *x_tick; > + struct mount *mp; > + struct fuse_ticket *tick, *itick, *x_tick; > int found = 0; > > err = devfs_get_cdevpriv((void **)&data); > if (err != 0) > return (err); > + mp = data->mp; > > if (uio->uio_resid < sizeof(struct fuse_out_header)) { > - SDT_PROBE2(fuse, , device, trace, 1, > + SDT_PROBE2(fusefs, , device, trace, 1, > "fuse_device_write got less than a header!"); > fdata_set_dead(data); > return (EINVAL); > @@ -393,15 +468,29 @@ fuse_device_write(struct cdev *dev, struct uio *uio, i > fuse_lck_mtx_lock(data->aw_mtx); > TAILQ_FOREACH_SAFE(tick, &data->aw_head, tk_aw_link, > x_tick) { > - SDT_PROBE1(fuse, , device, > - fuse_device_write_bumped_into_callback, > - tick->tk_unique); > if (tick->tk_unique == ohead.unique) { > + SDT_PROBE1(fusefs, , device, fuse_device_write_found, > + tick); > found = 1; > fuse_aw_remove(tick); > break; > } > } > + if (found && tick->irq_unique > 0) { > + /* > + * Discard the FUSE_INTERRUPT ticket that tried to interrupt > + * this operation > + */ > + TAILQ_FOREACH_SAFE(itick, &data->aw_head, tk_aw_link, > + x_tick) { > + if (itick->tk_unique == tick->irq_unique) { > + fuse_aw_remove(itick); > + fuse_ticket_drop(itick); > + break; > + } > + } > + tick->irq_unique = 0; > + } > fuse_lck_mtx_unlock(data->aw_mtx); > > if (found) { > @@ -414,13 +503,15 @@ fuse_device_write(struct cdev *dev, struct uio *uio, i > * via ticket_drop(), so no manual mucking > * around...) > */ > - SDT_PROBE2(fuse, , device, trace, 1, > + SDT_PROBE2(fusefs, , device, trace, 1, > "pass ticket to a callback"); > + /* Sanitize the linuxism of negative errnos */ > + ohead.error *= -1; > memcpy(&tick->tk_aw_ohead, &ohead, sizeof(ohead)); > err = tick->tk_aw_handler(tick, uio); > } else { > /* pretender doesn't wanna do anything with answer */ > - SDT_PROBE2(fuse, , device, trace, 1, > + SDT_PROBE2(fusefs, , device, trace, 1, > "stuff devalidated, so we drop it"); > } > > @@ -430,11 +521,51 @@ fuse_device_write(struct cdev *dev, struct uio *uio, i > * because fuse_ticket_drop() will deal with refcount anyway. > */ > fuse_ticket_drop(tick); > + } else if (ohead.unique == 0){ > + /* unique == 0 means asynchronous notification */ > + SDT_PROBE1(fusefs, , device, fuse_device_write_notify, &ohead); > + switch (ohead.error) { > + case FUSE_NOTIFY_INVAL_ENTRY: > + err = fuse_internal_invalidate_entry(mp, uio); > + break; > + case FUSE_NOTIFY_INVAL_INODE: > + err = fuse_internal_invalidate_inode(mp, uio); > + break; > + case FUSE_NOTIFY_RETRIEVE: > + case FUSE_NOTIFY_STORE: > + /* > + * Unimplemented. I don't know of any file systems > + * that use them, and the protocol isn't sound anyway, > + * since the notification messages don't include the > + * inode's generation number. Without that, it's > + * possible to manipulate the cache of the wrong vnode. > + * Finally, it's not defined what this message should > + * do for a file with dirty cache. > + */ > + case FUSE_NOTIFY_POLL: > + /* Unimplemented. See comments in fuse_vnops */ > + default: > + /* Not implemented */ > + err = ENOSYS; > + } > } else { > /* no callback at all! */ > - SDT_PROBE2(fuse, , device, trace, 1, > - "erhm, no handler for this response"); > - err = EINVAL; > + SDT_PROBE1(fusefs, , device, fuse_device_write_missing_ticket, > + ohead.unique); > + if (ohead.error == -EAGAIN) { > + /* > + * This was probably a response to a FUSE_INTERRUPT > + * operation whose original operation is already > + * complete. We can't store FUSE_INTERRUPT tickets > + * indefinitely because their responses are optional. > + * So we delete them when the original operation > + * completes. And sadly the fuse_header_out doesn't > + * identify the opcode, so we have to guess. > + */ > + err = 0; > + } else { > + err = EINVAL; > + } > } > > return (err); > @@ -445,7 +576,7 @@ fuse_device_init(void) > { > > fuse_dev = make_dev(&fuse_device_cdevsw, 0, UID_ROOT, GID_OPERATOR, > - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, "fuse"); > + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, "fuse"); > if (fuse_dev == NULL) > return (ENOMEM); > return (0); > > Modified: head/sys/fs/fuse/fuse_file.c > ============================================================================== > --- head/sys/fs/fuse/fuse_file.c Tue Aug 6 23:22:25 2019 (r350664) > +++ head/sys/fs/fuse/fuse_file.c Wed Aug 7 00:38:26 2019 (r350665) > @@ -33,6 +33,11 @@ > * Copyright (C) 2005 Csaba Henk. > * All rights reserved. > * > + * Copyright (c) 2019 The FreeBSD Foundation > + * > + * Portions of this software were developed by BFF Storage Systems, LLC under > + * sponsorship from the FreeBSD Foundation. > + * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > @@ -59,8 +64,9 @@ > __FBSDID("$FreeBSD$"); > > #include <sys/param.h> > -#include <sys/module.h> > #include <sys/systm.h> > +#include <sys/counter.h> > +#include <sys/module.h> > #include <sys/errno.h> > #include <sys/kernel.h> > #include <sys/conf.h> > @@ -79,52 +85,61 @@ __FBSDID("$FreeBSD$"); > #include "fuse.h" > #include "fuse_file.h" > #include "fuse_internal.h" > > *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6c7f7b6f-c0e3-e99c-bd00-8c5a8f729c23>