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