aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlan Somers <asomers@FreeBSD.org>2019-07-18 17:55:13 +0000
committerAlan Somers <asomers@FreeBSD.org>2019-07-18 17:55:13 +0000
commited74f781c9f704092556f860a00b0bb53fdedff7 (patch)
treea0debdb972a97d02e135b2ba8ed5940f64fc87b2 /sys
parentf05962453e84168a0c0e616372bc99f10754a947 (diff)
fusefs: add a intr/nointr mount option
FUSE file systems can optionally support interrupting outstanding operations. However, the file system does not identify to the kernel at mount time whether it's capable of doing that. Instead it signals its noncapability by returning ENOSYS to the first FUSE_INTERRUPT operation it receives. That's a problem for reliable signal delivery, because the kernel must choose which thread should get a signal before it knows whether the FUSE server can handle interrupts. The problem is even worse because the FUSE protocol allows a file system to simply ignore all FUSE_INTERRUPT operations. Fix the signal delivery logic by making interruptibility an opt-in mount option. This will require a corresponding change to libfuse, but not to most file systems that link to libfuse. Bump __FreeBSD_version due to the new mount option. Sponsored by: The FreeBSD Foundation
Notes
Notes: svn path=/projects/fuse2/; revision=350115
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/fuse/fuse_ipc.c6
-rw-r--r--sys/fs/fuse/fuse_ipc.h3
-rw-r--r--sys/fs/fuse/fuse_vfsops.c1
-rw-r--r--sys/sys/param.h2
4 files changed, 7 insertions, 5 deletions
diff --git a/sys/fs/fuse/fuse_ipc.c b/sys/fs/fuse/fuse_ipc.c
index 85a3e3ea3bcb..a7e89337bd0c 100644
--- a/sys/fs/fuse/fuse_ipc.c
+++ b/sys/fs/fuse/fuse_ipc.c
@@ -438,10 +438,11 @@ fticket_wait_answer(struct fuse_ticket *ftick)
struct thread *td = curthread;
sigset_t blockedset, oldset;
int err = 0, stops_deferred;
- struct fuse_data *data;
+ struct fuse_data *data = ftick->tk_data;
bool interrupted = false;
- if (fsess_isimpl(ftick->tk_data->mp, FUSE_INTERRUPT)) {
+ if (fsess_isimpl(ftick->tk_data->mp, FUSE_INTERRUPT) &&
+ data->dataflags & FSESS_INTR) {
SIGEMPTYSET(blockedset);
} else {
/* Block all signals except (implicitly) SIGKILL */
@@ -456,7 +457,6 @@ retry:
if (fticket_answered(ftick)) {
goto out;
}
- data = ftick->tk_data;
if (fdata_get_dead(data)) {
err = ENOTCONN;
diff --git a/sys/fs/fuse/fuse_ipc.h b/sys/fs/fuse/fuse_ipc.h
index 8a7b000b209c..281a0f357359 100644
--- a/sys/fs/fuse/fuse_ipc.h
+++ b/sys/fs/fuse/fuse_ipc.h
@@ -232,9 +232,10 @@ struct fuse_data {
#define FSESS_ASYNC_READ 0x1000 /* allow multiple reads of some file */
#define FSESS_POSIX_LOCKS 0x2000 /* daemon supports POSIX locks */
#define FSESS_EXPORT_SUPPORT 0x10000 /* daemon supports NFS-style lookups */
+#define FSESS_INTR 0x20000 /* interruptible mounts */
#define FSESS_MNTOPTS_MASK ( \
FSESS_DAEMON_CAN_SPY | FSESS_PUSH_SYMLINKS_IN | \
- FSESS_DEFAULT_PERMISSIONS)
+ FSESS_DEFAULT_PERMISSIONS | FSESS_INTR)
extern int fuse_data_cache_mode;
diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c
index 8229163d88a9..fff2cca67e77 100644
--- a/sys/fs/fuse/fuse_vfsops.c
+++ b/sys/fs/fuse/fuse_vfsops.c
@@ -336,6 +336,7 @@ fuse_vfsop_mount(struct mount *mp)
FUSE_FLAGOPT(allow_other, FSESS_DAEMON_CAN_SPY);
FUSE_FLAGOPT(push_symlinks_in, FSESS_PUSH_SYMLINKS_IN);
FUSE_FLAGOPT(default_permissions, FSESS_DEFAULT_PERMISSIONS);
+ FUSE_FLAGOPT(intr, FSESS_INTR);
(void)vfs_scanopt(opts, "max_read=", "%u", &max_read);
if (vfs_scanopt(opts, "timeout=", "%u", &daemon_timeout) == 1) {
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 9a68762388f2..bf1dc5e6d0ca 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1300034 /* Master, propagated to newvers */
+#define __FreeBSD_version 1300035 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,