summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhelg <helg@openbsd.org>2018-06-21 14:53:36 +0000
committerhelg <helg@openbsd.org>2018-06-21 14:53:36 +0000
commit13907cded777a2f976ccbdda4417a7daf0417ba4 (patch)
tree7a6a106e72ff3265c8a899a02d7dc64b5e1fbe92
parentDrop redundant "node == parent node" checks from VOP_RMDIR() (diff)
downloadwireguard-openbsd-13907cded777a2f976ccbdda4417a7daf0417ba4.tar.xz
wireguard-openbsd-13907cded777a2f976ccbdda4417a7daf0417ba4.zip
Don't timeout on fb_queue(9). The current process will block
indefinitely and cannot be interrupted or killed. This is consistent with how VFS system calls should behave. If the file system becomes unresponsive then the only sane solution is for the user to kill the file system daemon. Implementing the equivalent of nfs -osoft or -ointr to either timeout or allow the blocking FUSE operation to be interrupted can be considered in a future patch. ok mpi@
-rw-r--r--sys/miscfs/fuse/fuse_device.c16
-rw-r--r--sys/miscfs/fuse/fuse_lookup.c6
-rw-r--r--sys/miscfs/fuse/fusebuf.c30
-rw-r--r--sys/miscfs/fuse/fusefs.h5
4 files changed, 32 insertions, 25 deletions
diff --git a/sys/miscfs/fuse/fuse_device.c b/sys/miscfs/fuse/fuse_device.c
index ca0b1af2e35..85ced5d01e7 100644
--- a/sys/miscfs/fuse/fuse_device.c
+++ b/sys/miscfs/fuse/fuse_device.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fuse_device.c,v 1.26 2018/05/17 11:25:11 helg Exp $ */
+/* $OpenBSD: fuse_device.c,v 1.27 2018/06/21 14:53:36 helg Exp $ */
/*
* Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
*
@@ -157,7 +157,6 @@ void
fuse_destroy(dev_t dev, struct fuse_d *fd)
{
LIST_REMOVE(fd, fd_list);
- fuse_device_cleanup(dev, NULL);
free(fd, M_DEVBUF, sizeof(*fd));
}
@@ -187,10 +186,8 @@ fuse_device_cleanup(dev_t dev, struct fusebuf *fbuf)
fb_next);
stat_fbufs_in--;
- if (fbuf == NULL)
- fb_delete(f);
- else
- break;
+ f->fb_err = ENXIO;
+ wakeup(f);
}
lprev = f;
}
@@ -208,10 +205,8 @@ fuse_device_cleanup(dev_t dev, struct fusebuf *fbuf)
fb_next);
stat_fbufs_wait--;
- if (fbuf == NULL)
- fb_delete(f);
- else
- break;
+ f->fb_err = ENXIO;
+ wakeup(f);
}
lprev = f;
}
@@ -277,6 +272,7 @@ fuseclose(dev_t dev, int flags, int fmt, struct proc *p)
if (fd->fd_fmp) {
printf("fuse: device close without umount\n");
fd->fd_fmp->sess_init = 0;
+ fuse_device_cleanup(dev, NULL);
if ((vfs_busy(fd->fd_fmp->mp, VB_WRITE|VB_NOWAIT)) != 0)
goto end;
error = dounmount(fd->fd_fmp->mp, MNT_FORCE, curproc);
diff --git a/sys/miscfs/fuse/fuse_lookup.c b/sys/miscfs/fuse/fuse_lookup.c
index 3210dd09546..7e19d2449ee 100644
--- a/sys/miscfs/fuse/fuse_lookup.c
+++ b/sys/miscfs/fuse/fuse_lookup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fuse_lookup.c,v 1.20 2018/05/22 12:52:14 helg Exp $ */
+/* $OpenBSD: fuse_lookup.c,v 1.21 2018/06/21 14:53:36 helg Exp $ */
/*
* Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
*
@@ -84,8 +84,8 @@ fusefs_lookup(void *v)
if (error) {
fb_delete(fbuf);
- /* tsleep return */
- if (error == EWOULDBLOCK)
+ /* file system is dead */
+ if (error == ENXIO)
return (error);
if ((nameiop == CREATE || nameiop == RENAME) &&
diff --git a/sys/miscfs/fuse/fusebuf.c b/sys/miscfs/fuse/fusebuf.c
index edc5a9ca3d2..9673491bcba 100644
--- a/sys/miscfs/fuse/fusebuf.c
+++ b/sys/miscfs/fuse/fusebuf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fusebuf.c,v 1.15 2018/06/19 11:27:54 helg Exp $ */
+/* $OpenBSD: fusebuf.c,v 1.16 2018/06/21 14:53:36 helg Exp $ */
/*
* Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
*
@@ -58,17 +58,31 @@ fb_setup(size_t len, ino_t ino, int op, struct proc *p)
return (fbuf);
}
+/*
+ * Puts the fbuf on the queue and waits for the file system to process
+ * it. The current process will block indefinitely and cannot be
+ * interrupted or killed. This is consistent with how VFS system calls
+ * should behave. nfs supports the -ointr or -i mount option and FUSE
+ * can too but this is non-trivial. The file system daemon must be
+ * multi-threaded and also support being interrupted. Note that
+ * libfuse currently only supports single-threaded deamons.
+ *
+ * Why not timeout similar to mount_nfs -osoft?
+ * It introduces another point of failure and a possible mount option
+ * (to specify the timeout) that users need to understand and tune to
+ * avoid premature timeouts for slow file systems. More complexity,
+ * less reliability.
+ *
+ * In the case where the daemon has become unresponsive the daemon
+ * will have to be killed in order for the current process to
+ * wakeup. The FUSE device is automatically closed when the daemon
+ * terminates and any waiting fbuf is woken up.
+ */
int
fb_queue(dev_t dev, struct fusebuf *fbuf)
{
- int error = 0;
-
fuse_device_queue_fbuf(dev, fbuf);
-
- if ((error = tsleep(fbuf, PWAIT, "fuse", TSLEEP_TIMEOUT * hz))) {
- fuse_device_cleanup(dev, fbuf);
- return (error);
- }
+ tsleep(fbuf, PWAIT, "fuse", 0);
return (fbuf->fb_err);
}
diff --git a/sys/miscfs/fuse/fusefs.h b/sys/miscfs/fuse/fusefs.h
index cf318150c97..ef57d837955 100644
--- a/sys/miscfs/fuse/fusefs.h
+++ b/sys/miscfs/fuse/fusefs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fusefs.h,v 1.10 2018/06/19 13:01:34 helg Exp $ */
+/* $OpenBSD: fusefs.h,v 1.11 2018/06/21 14:53:36 helg Exp $ */
/*
* Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
*
@@ -72,9 +72,6 @@ struct fusefs_mnt {
extern struct vops fusefs_vops;
extern struct pool fusefs_fbuf_pool;
-/* fuse helpers */
-#define TSLEEP_TIMEOUT 5
-
/* files helpers. */
int fusefs_file_open(struct fusefs_mnt *, struct fusefs_node *, enum fufh_type,
int, int, struct proc *);