fixing a Fuse bug when writing (PR#194293?)

Rick Macklem rmacklem at uoguelph.ca
Mon Dec 28 17:15:41 UTC 2015


Hi,

I sent a rather long email to a few people, but forgot to cc freebsd-fs at .
Here's a shorter version:
- When a file on a Fuse mounted fs is opened WRONLY and a partial block
  is written (when using the buffer cache, not DIRECT_IO), it gets wedged
  because the buffer cache code attempts to read in the whole block and
  the read isn't allowed. (I can reproduce this using GlusterFS and I think
  PR#194293 might be the same problem.)

I can think of two ways to fix this:
1 - Make any WRONLY open actually do a RDWR open. The patch at the end of
    the email does that and fixes the problem for my test case.
XXX - I think the problem is that if a process has write but not read access
    for the file, this RDWR open will fail and that won't make much sense,
    since it has write access.

2 - Make Fuse always do DIRECT_IO when a file is opened WRONLY. (This seems
    to happen for GlusterFS, since it seems to always set FOPEN_DIRECT_IO in
    the Fuse reply to the open for WRONLY, but I suspect other Fuse filesystems
    don't do this? I reproduced the problem by hacking the code to ignore the
    FOPEN_DIRECT_IO in the reply for GlusterFS.)

I have coded #1 but not #2. However I am now thinking #2 is the better solution,
given (XXX) above.

Any other ideas or opinions w.r.t. how to fix this?

Thanks, rick
ps: Here's the patch I came up with for #1:
--- fs/fuse/fuse_file.h.xxx	2015-12-27 16:02:53.241174000 -0500
+++ fs/fuse/fuse_file.h	2015-12-27 15:25:01.865156000 -0500
@@ -101,6 +101,9 @@ fuse_filehandle_xlate_from_fflags(int ff
     if ((fflags & FREAD) && (fflags & FWRITE)) {
         return FUFH_RDWR;
     } else if (fflags & (FWRITE)) {
+	/* See comment in fuse_vnop_open() w.r.t. why FUFH_RDWR is needed. */
+        if (datacache != 0)
+            return FUFH_RDWR;
         return FUFH_WRONLY;
     } else if (fflags & (FREAD)) {
         return FUFH_RDONLY;
--- fs/fuse/fuse_vnops.c.sav	2015-12-16 16:24:43.577000000 -0500
+++ fs/fuse/fuse_vnops.c	2015-12-27 16:07:06.683806000 -0500
@@ -276,7 +276,8 @@ fuse_vnop_close(struct vop_close_args *a
 	if (fflag & IO_NDELAY) {
 		return 0;
 	}
-	fufh_type = fuse_filehandle_xlate_from_fflags(fflag);
+	fufh_type = fuse_filehandle_xlate_from_fflags(fflag,
+	    fsess_opt_datacache(vnode_mount(vp)));
 
 	if (!fuse_filehandle_valid(vp, fufh_type)) {
 		int i;
@@ -1139,7 +1140,8 @@ fuse_vnop_open(struct vop_open_args *ap)
 	if (isdir) {
 		fufh_type = FUFH_RDONLY;
 	} else {
-		fufh_type = fuse_filehandle_xlate_from_fflags(mode);
+		fufh_type = fuse_filehandle_xlate_from_fflags(mode,
+		    fsess_opt_datacache(vnode_mount(vp)));
 	}
 
 	if (fuse_filehandle_valid(vp, fufh_type)) {


More information about the freebsd-fs mailing list