svn commit: r299753 - head/sys/fs/fuse

Rick Macklem rmacklem at FreeBSD.org
Sat May 14 20:03:23 UTC 2016


Author: rmacklem
Date: Sat May 14 20:03:22 2016
New Revision: 299753
URL: https://svnweb.freebsd.org/changeset/base/299753

Log:
  Fix fuse to use DIRECT_IO when required.
  
  When a file is opened write-only and a partial block was written,
  buffered I/O would try and read the whole block in. This would
  result in a hung thread, since there was no open (fuse filehandle)
  that allowed reading. This patch avoids the problem by forcing
  DIRECT_IO for this case.
  It also sets DIRECT_IO when the file system specifies the FN_DIRECTIO
  flag in its reply to the open.
  
  Tested by:	nishida at asusa.net, freebsd at moosefs.com
  PR:		194293, 206238
  MFC after:	2 weeks

Modified:
  head/sys/fs/fuse/fuse_file.c
  head/sys/fs/fuse/fuse_vnops.c

Modified: head/sys/fs/fuse/fuse_file.c
==============================================================================
--- head/sys/fs/fuse/fuse_file.c	Sat May 14 20:02:02 2016	(r299752)
+++ head/sys/fs/fuse/fuse_file.c	Sat May 14 20:03:22 2016	(r299753)
@@ -141,7 +141,17 @@ fuse_filehandle_open(struct vnode *vp,
 	foo = fdi.answ;
 
 	fuse_filehandle_init(vp, fufh_type, fufhp, foo->fh);
-	fuse_vnode_open(vp, foo->open_flags, td);
+
+	/*
+	 * For WRONLY opens, force DIRECT_IO.  This is necessary
+	 * since writing a partial block through the buffer cache
+	 * will result in a read of the block and that read won't
+	 * be allowed by the WRONLY open.
+	 */
+	if (fufh_type == FUFH_WRONLY)
+		fuse_vnode_open(vp, foo->open_flags | FOPEN_DIRECT_IO, td);
+	else
+		fuse_vnode_open(vp, foo->open_flags, td);
 
 out:
 	fdisp_destroy(&fdi);

Modified: head/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- head/sys/fs/fuse/fuse_vnops.c	Sat May 14 20:02:02 2016	(r299752)
+++ head/sys/fs/fuse/fuse_vnops.c	Sat May 14 20:03:22 2016	(r299753)
@@ -1125,6 +1125,7 @@ fuse_vnop_open(struct vop_open_args *ap)
 	struct fuse_vnode_data *fvdat;
 
 	int error, isdir = 0;
+	int32_t fuse_open_flags;
 
 	FS_DEBUG2G("inode=%ju mode=0x%x\n", (uintmax_t)VTOI(vp), mode);
 
@@ -1136,14 +1137,24 @@ fuse_vnop_open(struct vop_open_args *ap)
 	if (vnode_isdir(vp)) {
 		isdir = 1;
 	}
+	fuse_open_flags = 0;
 	if (isdir) {
 		fufh_type = FUFH_RDONLY;
 	} else {
 		fufh_type = fuse_filehandle_xlate_from_fflags(mode);
+		/*
+		 * For WRONLY opens, force DIRECT_IO.  This is necessary
+		 * since writing a partial block through the buffer cache
+		 * will result in a read of the block and that read won't
+		 * be allowed by the WRONLY open.
+		 */
+		if (fufh_type == FUFH_WRONLY ||
+		    (fvdat->flag & FN_DIRECTIO) != 0)
+			fuse_open_flags = FOPEN_DIRECT_IO;
 	}
 
 	if (fuse_filehandle_valid(vp, fufh_type)) {
-		fuse_vnode_open(vp, 0, td);
+		fuse_vnode_open(vp, fuse_open_flags, td);
 		return 0;
 	}
 	error = fuse_filehandle_open(vp, fufh_type, NULL, td, cred);


More information about the svn-src-head mailing list