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:    nish...@asusa.net, free...@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);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to