summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhelg <helg@cvs.openbsd.org>2018-05-20 03:06:51 +0000
committerhelg <helg@cvs.openbsd.org>2018-05-20 03:06:51 +0000
commit055d61db631a5149b11a75248d416ae5ecd694e4 (patch)
tree1a7cf3ffaf1effd52fb7d8a04ab099eb6b80163f
parenta72a2cbe6b1ed4a7dbcd28b886be6b759029b7d4 (diff)
Prevent race condition if file system is accessed before it is
initialised. Rather than failing, requests are now queued. ok mpi@
-rw-r--r--sys/miscfs/fuse/fuse_vfsops.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/sys/miscfs/fuse/fuse_vfsops.c b/sys/miscfs/fuse/fuse_vfsops.c
index 6914a0b3099..acfa712dbdb 100644
--- a/sys/miscfs/fuse/fuse_vfsops.c
+++ b/sys/miscfs/fuse/fuse_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fuse_vfsops.c,v 1.36 2018/05/17 11:25:11 helg Exp $ */
+/* $OpenBSD: fuse_vfsops.c,v 1.37 2018/05/20 03:06:50 helg Exp $ */
/*
* Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
*
@@ -68,6 +68,8 @@ const struct vfsops fusefs_vfsops = {
struct pool fusefs_fbuf_pool;
+#define PENDING 2 /* FBT_INIT reply not yet received */
+
int
fusefs_mount(struct mount *mp, const char *path, void *data,
struct nameidata *ndp, struct proc *p)
@@ -98,7 +100,7 @@ fusefs_mount(struct mount *mp, const char *path, void *data,
fmp = malloc(sizeof(*fmp), M_FUSEFS, M_WAITOK | M_ZERO);
fmp->mp = mp;
- fmp->sess_init = 0;
+ fmp->sess_init = PENDING;
fmp->dev = vp->v_rdev;
if (args->max_read > 0)
fmp->max_read = MIN(args->max_read, FUSEBUFMAXSIZE);
@@ -202,7 +204,24 @@ fusefs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
copy_statfs_info(sbp, mp);
- if (fmp->sess_init) {
+ /*
+ * Both FBT_INIT and FBT_STATFS are sent to the FUSE file system
+ * daemon when it is mounted. However, the daemon is the process
+ * that called mount(2) so to prevent a deadlock return dummy
+ * values until the response to FBT_INIT init is received. All
+ * other VFS syscalls are queued.
+ */
+ if (!fmp->sess_init || fmp->sess_init == PENDING) {
+ sbp->f_bavail = 0;
+ sbp->f_bfree = 0;
+ sbp->f_blocks = 0;
+ sbp->f_ffree = 0;
+ sbp->f_favail = 0;
+ sbp->f_files = 0;
+ sbp->f_bsize = 0;
+ sbp->f_iosize = 0;
+ sbp->f_namemax = 0;
+ } else {
fbuf = fb_setup(0, FUSE_ROOTINO, FBT_STATFS, p);
error = fb_queue(fmp->dev, fbuf);
@@ -222,16 +241,6 @@ fusefs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
sbp->f_iosize = fbuf->fb_stat.f_bsize;
sbp->f_namemax = fbuf->fb_stat.f_namemax;
fb_delete(fbuf);
- } else {
- sbp->f_bavail = 0;
- sbp->f_bfree = 0;
- sbp->f_blocks = 0;
- sbp->f_ffree = 0;
- sbp->f_favail = 0;
- sbp->f_files = 0;
- sbp->f_bsize = 0;
- sbp->f_iosize = 0;
- sbp->f_namemax = 0;
}
return (0);