Don't send FBT_DESTROY if the FUSE connection is still PENDING. Also
authorhelg <helg@openbsd.org>
Tue, 17 Jul 2018 13:12:08 +0000 (13:12 +0000)
committerhelg <helg@openbsd.org>
Tue, 17 Jul 2018 13:12:08 +0000 (13:12 +0000)
don't attempt to determine the size of the root inode. This is because
we don't need to know the size of directories and FBT_GETATTR will also
cause a deadlock if fuse_unmount(3) is called before the file system
has a chance to process fbufs.

Add corresponding regression test.

ok mpi@

regress/lib/libfuse/Makefile
regress/lib/libfuse/fuse-mount.c [new file with mode: 0644]
regress/lib/libfuse/fuse-null-check.c [new file with mode: 0644]
sys/miscfs/fuse/fuse_vfsops.c

index 33f75e6..a3c73a7 100644 (file)
@@ -1,4 +1,4 @@
-#       $OpenBSD: Makefile,v 1.2 2017/11/16 13:23:13 helg Exp $
+#       $OpenBSD: Makefile,v 1.3 2018/07/17 13:12:08 helg Exp $
 
 REGRESS_TARGETS=  run-fuse-opt-add-opt
 REGRESS_TARGETS+= run-fuse-opt-add-opt-escaped
@@ -7,6 +7,8 @@ REGRESS_TARGETS+= run-fuse-opt-insert-arg
 REGRESS_TARGETS+= run-fuse-opt-match
 REGRESS_TARGETS+= run-fuse-opt-parse
 REGRESS_TARGETS+= run-fuse-parse-cmdline
+REGRESS_TARGETS+= run-fuse-null-check
+REGRESS_TARGETS+= run-fuse-mount
 
 LDFLAGS+= -lfuse
 CLEANFILES= fuse-opt-add-opt
@@ -16,6 +18,8 @@ CLEANFILES+=fuse-opt-insert-arg
 CLEANFILES+=fuse-opt-match
 CLEANFILES+=fuse-opt-parse
 CLEANFILES+=fuse-parse-cmdline
+CLEANFILES+=fuse-null-check
+CLEANFILES+=fuse-mount
 
 .PHONY: ${REGRESS_TARGETS}
 
@@ -33,5 +37,9 @@ run-fuse-opt-parse: fuse-opt-parse
        ./fuse-opt-parse
 run-fuse-parse-cmdline: fuse-parse-cmdline
        ./fuse-parse-cmdline
+run-fuse-null-check: fuse-null-check
+       ./fuse-null-check
+run-fuse-mount: fuse-mount
+       ./fuse-mount
 
 .include <bsd.regress.mk>
diff --git a/regress/lib/libfuse/fuse-mount.c b/regress/lib/libfuse/fuse-mount.c
new file mode 100644 (file)
index 0000000..25cb562
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018 Helg Bredow <helg@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <fuse.h>
+
+int
+main(int argc, char **argv)
+{
+       struct fuse_chan *fc;
+       const char *dir = "/mnt";
+
+       fc = fuse_mount(dir, NULL);
+       if (fc == NULL)
+               return (1);
+
+       fuse_unmount(dir, fc);
+
+       return (0);
+}
diff --git a/regress/lib/libfuse/fuse-null-check.c b/regress/lib/libfuse/fuse-null-check.c
new file mode 100644 (file)
index 0000000..3d37001
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018 Helg Bredow <helg@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <fuse.h>
+#include <stdlib.h>
+
+int
+main(void)
+{
+       fuse_main(0, NULL, NULL, NULL);
+       fuse_new(NULL, NULL, NULL, 0, NULL);
+       fuse_setup(0, NULL, NULL, 0, NULL, NULL, NULL);
+       fuse_mount(NULL, NULL);
+       fuse_remove_signal_handlers(NULL);
+       fuse_set_signal_handlers(NULL);
+       fuse_get_session(NULL);
+       fuse_is_lib_option(NULL);
+       fuse_loop(NULL);
+       fuse_chan_fd(NULL);
+       fuse_unmount(NULL, NULL);
+       fuse_destroy(NULL);
+       fuse_teardown(NULL, NULL);
+       fuse_invalidate(NULL, NULL);
+
+       return (0);
+}
index a7f957f..cf45969 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: fuse_vfsops.c,v 1.41 2018/07/16 16:44:09 helg Exp $ */
+/* $OpenBSD: fuse_vfsops.c,v 1.42 2018/07/17 13:12:08 helg Exp $ */
 /*
  * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
  *
@@ -157,8 +157,7 @@ fusefs_unmount(struct mount *mp, int mntflags, struct proc *p)
        if ((error = vflush(mp, NULLVP, flags)))
                return (error);
 
-       if (fmp->sess_init) {
-               fmp->sess_init = 0;
+       if (fmp->sess_init && fmp->sess_init != PENDING) {
                fbuf = fb_setup(0, 0, FBT_DESTROY, p);
 
                error = fb_queue(fmp->dev, fbuf);
@@ -168,6 +167,7 @@ fusefs_unmount(struct mount *mp, int mntflags, struct proc *p)
 
                fb_delete(fbuf);
        }
+       fmp->sess_init = 0;
 
        fuse_device_cleanup(fmp->dev);
        fuse_device_set_fmp(fmp, 0);
@@ -314,17 +314,18 @@ retry:
 
        if (ino == FUSE_ROOTINO)
                nvp->v_flag |= VROOT;
-
-       /*
-        * Initialise the file size so that file size changes can be
-        * detected during file operations.
-        */
-       error = VOP_GETATTR(nvp, &vattr, curproc->p_ucred, curproc);
-       if (error) {
-               vrele(nvp);
-               return (error);
+       else {
+               /*
+                * Initialise the file size so that file size changes can be
+                * detected during file operations.
+                */
+               error = VOP_GETATTR(nvp, &vattr, curproc->p_ucred, curproc);
+               if (error) {
+                       vrele(nvp);
+                       return (error);
+               }
+               ip->filesize = vattr.va_size;
        }
-       ip->filesize = vattr.va_size;
 
        *vpp = nvp;