diff options
author | 2018-06-21 14:53:36 +0000 | |
---|---|---|
committer | 2018-06-21 14:53:36 +0000 | |
commit | 13907cded777a2f976ccbdda4417a7daf0417ba4 (patch) | |
tree | 7a6a106e72ff3265c8a899a02d7dc64b5e1fbe92 | |
parent | Drop redundant "node == parent node" checks from VOP_RMDIR() (diff) | |
download | wireguard-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.c | 16 | ||||
-rw-r--r-- | sys/miscfs/fuse/fuse_lookup.c | 6 | ||||
-rw-r--r-- | sys/miscfs/fuse/fusebuf.c | 30 | ||||
-rw-r--r-- | sys/miscfs/fuse/fusefs.h | 5 |
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 *); |