svn commit: r352351 - in stable/12: . etc/mtree sbin/mount_fusefs share/man/man5 sys/fs/fuse sys/sys tests/sys/fs tests/sys/fs/fusefs

Alan Somers asomers at FreeBSD.org
Sun Sep 15 04:14:33 UTC 2019


Author: asomers
Date: Sun Sep 15 04:14:31 2019
New Revision: 352351
URL: https://svnweb.freebsd.org/changeset/base/352351

Log:
  MFC the new fusefs driver
  
  MFC r350665, r350990, r350992, r351039, r351042, r351061, r351066, r351113, r351560, r351961, r351963, r352021, r352025, r352230
  
  r350665:
  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)
  Relnotes:	yes
  Sponsored by:	The FreeBSD Foundation
  Pull Request:	https://reviews.freebsd.org/D21110
  
  r350990:
  fusefs: add SVN Keywords to the test files
  
  Reported by:	SVN pre-commit hooks
  MFC-With:	r350665
  Sponsored by:	The FreeBSD Foundation
  
  r350992:
  fusefs: skip some tests when unsafe aio is disabled
  
  MFC-With:       r350665
  Sponsored by:   The FreeBSD Foundation
  
  r351039:
  fusefs: fix intermittency in the default_permissions.Unlink.ok test
  
  The test needs to expect a FUSE_FORGET operation. Most of the time the test
  would pass anyway, because by chance FUSE_FORGET would arrive after the
  unmount.
  
  MFC-With:	350665
  Sponsored by:	The FreeBSD Foundation
  
  r351042:
  fusefs: Fix the size of fuse_getattr_in
  
  In FUSE protocol 7.9, the size of the FUSE_GETATTR request has increased.
  However, the fusefs driver is currently not sending the additional fields.
  In our implementation, the additional fields are always zero, so I there
  haven't been any test failures until now.  But fusefs-lkl requires the
  request's length to be correct.
  
  Fix this bug, and also enhance the test suite to catch similar bugs.
  
  PR:		239830
  MFC-With:	350665
  Sponsored by:	The FreeBSD Foundation
  
  r351061:
  fusefs: fix the 32-bit build after 351042
  
  Reported by:	jhb
  MFC-With:	351042
  Sponsored by:	The FreeBSD Foundation
  
  r351066:
  fusefs: fix conditional from r351061
  
  The entirety of r351061 was a copy/paste error.  I'm sorry I've been
  comitting so hastily.
  
  Reported by:	rpokala
  Reviewed by:	rpokala
  MFC-With:	351061
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D21265
  
  r351113:
  fusefs: don't send the namespace during listextattr
  
  The FUSE_LISTXATTR operation always returns the full list of a file's
  extended attributes, in all namespaces. There's no way to filter the list
  server-side. However, currently FreeBSD's fusefs driver sends a namespace
  string with the FUSE_LISTXATTR request. That behavior was probably copied
  from fuse_vnop_getextattr, which has an attribute name argument. It's
  been there ever since extended attribute support was added in r324620. This
  commit removes it.
  
  Reviewed by:	cem
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D21280
  
  r351560:
  fusefs: Fix some bugs regarding the size of the LISTXATTR list
  
  * A small error in r338152 let to the returned size always being exactly
    eight bytes too large.
  
  * The FUSE_LISTXATTR operation works like Linux's listxattr(2): if the
    caller does not provide enough space, then the server should return ERANGE
    rather than return a truncated list.  That's true even though in FUSE's
    case the kernel doesn't provide space to the client at all; it simply
    requests a maximum size for the list.  We previously weren't handling the
    case where the server returns ERANGE even though the kernel requested as
    much size as the server had told us it needs; that can happen due to a
    race.
  
  * We also need to ensure that a pathological server that always returns
    ERANGE no matter what size we request in FUSE_LISTXATTR won't cause an
    infinite loop in the kernel.  As of this commit, it will instead cause an
    infinite loop that exits and enters the kernel on each iteration, allowing
    signals to be processed.
  
  Reviewed by:	cem
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D21287
  
  r351961:
  Coverity fixes in fusefs(5)
  
  CID 1404532 fixes a signed vs unsigned comparison error in fuse_vnop_bmap.
  It could potentially have resulted in VOP_BMAP reporting too many
  consecutive blocks.
  
  CID 1404364 is much worse. It was an array access by an untrusted,
  user-provided variable. It could potentially have resulted in a malicious
  file system crashing the kernel or worse.
  
  Reported by:	Coverity
  Reviewed by:	emaste
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D21466
  
  r351963:
  fusefs: coverity cleanup in the tests
  
  Address the following defects reported by Coverity:
  
  * Structurally dead code (CID 1404366): set m_quit before FAIL, not after
  
  * Unchecked return value of sysctlbyname (CID 1404321)
  
  * Unchecked return value of stat(2) (CID 1404471)
  
  * Unchecked return value of open(2) (CID 1404402, 1404529)
  
  * Unchecked return value of dup(2) (CID 1404478)
  
  * Buffer overflows. These are all false positives caused by the fact that
    Coverity thinks I'm using a buffer to store strings, when in fact I'm
    really just using it to store a byte array that happens to be initialized
    with a string. I'm changing the type from char to uint8_t in the hopes
    that it will placate Coverity. (CID 1404338, 1404350, 1404367, 1404376,
    1404379, 1404381, 1404388, 1404403, 1404425, 1404433, 1404434, 1404474,
    1404480, 1404484, 1404503, 1404505)
  
  * False positive file descriptor leak. I'm going to try to fix this with
    Coverity modeling, but I'll also change an EXPECT to ASSERT so we don't
    perform meaningless assertions after the failure. (CID 1404320, 1404324,
    1404440, 1404445).
  
  * Unannotated file descriptor leak. This will be followed up by a Coverity
    modeling change. (CID 1404326, 1404334, 1404336, 1404357, 1404361,
    1404372, 1404391, 1404395, 1404409, 1404430, 1404448, 1404451, 1404455,
    1404457, 1404458, 1404460)
  
  * Uninitialized variables in C++ constructors (CID 1404327, 1404346). In the
    case of m_maxphys, this actually led to part of the FUSE_INIT's response
    being set to stack garbage during the WriteCluster::clustering test.
  
  * Uninitialized sun_len field in struct sockaddr_un (CID 1404330, 1404371,
    1404429).
  
  Reported by:	Coverity
  Reviewed by:	emaste
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D21457
  
  r352021:
  fusefs: suppress some Coverity resource leak CIDs in the tests
  
  The fusefs tests deliberately leak file descriptors.  To do otherwise would
  add extra complications to the tests' mock FUSE server.  This annotation
  should hopefully convince Coverity to shut up about the leaks.
  
  Reviewed by:	uqs
  Sponsored by:	The FreeBSD Foundation
  
  r352025:
  mount_fusefs: fix a segfault on memory allocation failure
  
  Reported by:	Coverity
  Coverity CID:	1354188
  Sponsored by:	The FreeBSD Foundation
  
  r352230:
  fusefs: Fix iosize for FUSE_WRITE in 7.8 compat mode
  
  When communicating with a FUSE server that implements version 7.8 (or older)
  of the FUSE protocol, the FUSE_WRITE request structure is 16 bytes shorter
  than normal. The protocol version check wasn't applied universally, leading
  to an extra 16 bytes being sent to such servers. The extra bytes were
  allocated and bzero()d, so there was no information disclosure.
  
  Reviewed by:	emaste
  MFC-With:	r350665
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D21557

Added:
  stable/12/tests/sys/fs/fusefs/
     - copied from r350665, head/tests/sys/fs/fusefs/
Deleted:
  stable/12/sys/fs/fuse/fuse_param.h
Modified:
  stable/12/MAINTAINERS
  stable/12/UPDATING
  stable/12/etc/mtree/BSD.tests.dist
  stable/12/sbin/mount_fusefs/mount_fusefs.8
  stable/12/sbin/mount_fusefs/mount_fusefs.c
  stable/12/share/man/man5/fusefs.5
  stable/12/sys/fs/fuse/fuse.h
  stable/12/sys/fs/fuse/fuse_device.c
  stable/12/sys/fs/fuse/fuse_file.c
  stable/12/sys/fs/fuse/fuse_file.h
  stable/12/sys/fs/fuse/fuse_internal.c
  stable/12/sys/fs/fuse/fuse_internal.h
  stable/12/sys/fs/fuse/fuse_io.c
  stable/12/sys/fs/fuse/fuse_io.h
  stable/12/sys/fs/fuse/fuse_ipc.c
  stable/12/sys/fs/fuse/fuse_ipc.h
  stable/12/sys/fs/fuse/fuse_kernel.h
  stable/12/sys/fs/fuse/fuse_main.c
  stable/12/sys/fs/fuse/fuse_node.c
  stable/12/sys/fs/fuse/fuse_node.h
  stable/12/sys/fs/fuse/fuse_vfsops.c
  stable/12/sys/fs/fuse/fuse_vnops.c
  stable/12/sys/sys/param.h
  stable/12/tests/sys/fs/Makefile
  stable/12/tests/sys/fs/fusefs/access.cc
  stable/12/tests/sys/fs/fusefs/allow_other.cc
  stable/12/tests/sys/fs/fusefs/bmap.cc
  stable/12/tests/sys/fs/fusefs/create.cc
  stable/12/tests/sys/fs/fusefs/default_permissions.cc
  stable/12/tests/sys/fs/fusefs/default_permissions_privileged.cc
  stable/12/tests/sys/fs/fusefs/destroy.cc
  stable/12/tests/sys/fs/fusefs/dev_fuse_poll.cc
  stable/12/tests/sys/fs/fusefs/fifo.cc
  stable/12/tests/sys/fs/fusefs/flush.cc
  stable/12/tests/sys/fs/fusefs/forget.cc
  stable/12/tests/sys/fs/fusefs/fsync.cc
  stable/12/tests/sys/fs/fusefs/fsyncdir.cc
  stable/12/tests/sys/fs/fusefs/getattr.cc
  stable/12/tests/sys/fs/fusefs/interrupt.cc
  stable/12/tests/sys/fs/fusefs/io.cc
  stable/12/tests/sys/fs/fusefs/link.cc
  stable/12/tests/sys/fs/fusefs/locks.cc
  stable/12/tests/sys/fs/fusefs/lookup.cc
  stable/12/tests/sys/fs/fusefs/mkdir.cc
  stable/12/tests/sys/fs/fusefs/mknod.cc
  stable/12/tests/sys/fs/fusefs/mockfs.cc
  stable/12/tests/sys/fs/fusefs/mockfs.hh   (contents, props changed)
  stable/12/tests/sys/fs/fusefs/mount.cc
  stable/12/tests/sys/fs/fusefs/nfs.cc
  stable/12/tests/sys/fs/fusefs/notify.cc
  stable/12/tests/sys/fs/fusefs/open.cc
  stable/12/tests/sys/fs/fusefs/opendir.cc
  stable/12/tests/sys/fs/fusefs/read.cc
  stable/12/tests/sys/fs/fusefs/readdir.cc
  stable/12/tests/sys/fs/fusefs/readlink.cc
  stable/12/tests/sys/fs/fusefs/release.cc
  stable/12/tests/sys/fs/fusefs/releasedir.cc
  stable/12/tests/sys/fs/fusefs/rename.cc
  stable/12/tests/sys/fs/fusefs/rmdir.cc
  stable/12/tests/sys/fs/fusefs/setattr.cc
  stable/12/tests/sys/fs/fusefs/statfs.cc
  stable/12/tests/sys/fs/fusefs/symlink.cc
  stable/12/tests/sys/fs/fusefs/unlink.cc
  stable/12/tests/sys/fs/fusefs/utils.cc
  stable/12/tests/sys/fs/fusefs/utils.hh   (contents, props changed)
  stable/12/tests/sys/fs/fusefs/write.cc
  stable/12/tests/sys/fs/fusefs/xattr.cc
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/MAINTAINERS
==============================================================================
--- stable/12/MAINTAINERS	Sun Sep 15 02:59:53 2019	(r352350)
+++ stable/12/MAINTAINERS	Sun Sep 15 04:14:31 2019	(r352351)
@@ -50,6 +50,7 @@ dev/usb/wlan	adrian	Pre-commit review requested, send 
 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: stable/12/UPDATING
==============================================================================
--- stable/12/UPDATING	Sun Sep 15 02:59:53 2019	(r352350)
+++ stable/12/UPDATING	Sun Sep 15 04:14:31 2019	(r352351)
@@ -16,6 +16,18 @@ from older versions of FreeBSD, try WITHOUT_CLANG and 
 the tip of head, and then rebuild without this option. The bootstrap process
 from older version of current across the gcc/clang cutover is a bit fragile.
 
+20190914:
+	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.
+
 20190906:
 	The fuse(4) module has been renamed to fusefs(4) for consistency with
 	other filesystems.  You should update any kld_load="fuse" entries in

Modified: stable/12/etc/mtree/BSD.tests.dist
==============================================================================
--- stable/12/etc/mtree/BSD.tests.dist	Sun Sep 15 02:59:53 2019	(r352350)
+++ stable/12/etc/mtree/BSD.tests.dist	Sun Sep 15 04:14:31 2019	(r352351)
@@ -717,6 +717,8 @@
         file
         ..
         fs
+            fusefs
+            ..
             tmpfs
             ..
         ..

Modified: stable/12/sbin/mount_fusefs/mount_fusefs.8
==============================================================================
--- stable/12/sbin/mount_fusefs/mount_fusefs.8	Sun Sep 15 02:59:53 2019	(r352350)
+++ stable/12/sbin/mount_fusefs/mount_fusefs.8	Sun Sep 15 04:14:31 2019	(r352351)
@@ -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: stable/12/sbin/mount_fusefs/mount_fusefs.c
==============================================================================
--- stable/12/sbin/mount_fusefs/mount_fusefs.c	Sun Sep 15 02:59:53 2019	(r352350)
+++ stable/12/sbin/mount_fusefs/mount_fusefs.c	Sun Sep 15 04:14:31 2019	(r352351)
@@ -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[])
@@ -206,6 +212,8 @@ main(int argc, char *argv[])
 							q++;
 						mv->mv_len = q - p + 1;
 						mv->mv_value = malloc(mv->mv_len);
+						if (mv->mv_value == NULL)
+							err(1, "malloc");
 						memcpy(mv->mv_value, p, mv->mv_len - 1);
 						((char *)mv->mv_value)[mv->mv_len - 1] = '\0';
 						break;
@@ -409,12 +417,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 +473,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 +484,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 +493,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: stable/12/share/man/man5/fusefs.5
==============================================================================
--- stable/12/share/man/man5/fusefs.5	Sun Sep 15 02:59:53 2019	(r352350)
+++ stable/12/share/man/man5/fusefs.5	Sun Sep 15 04:14:31 2019	(r352351)
@@ -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: stable/12/sys/fs/fuse/fuse.h
==============================================================================
--- stable/12/sys/fs/fuse/fuse.h	Sun Sep 15 02:59:53 2019	(r352350)
+++ stable/12/sys/fs/fuse/fuse.h	Sun Sep 15 04:14:31 2019	(r352351)
@@ -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: stable/12/sys/fs/fuse/fuse_device.c
==============================================================================
--- stable/12/sys/fs/fuse/fuse_device.c	Sun Sep 15 02:59:53 2019	(r352350)
+++ stable/12/sys/fs/fuse/fuse_device.c	Sun Sep 15 04:14:31 2019	(r352351)
@@ -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: stable/12/sys/fs/fuse/fuse_file.c
==============================================================================
--- stable/12/sys/fs/fuse/fuse_file.c	Sun Sep 15 02:59:53 2019	(r352350)
+++ stable/12/sys/fs/fuse/fuse_file.c	Sun Sep 15 04:14:31 2019	(r352351)
@@ -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>

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-stable-12 mailing list