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
Pedro Giffuni
pfg at FreeBSD.org
Wed Aug 7 15:49:14 UTC 2019
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 at 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 at 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 ***
>
More information about the svn-src-head
mailing list