summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/fuse/fuse_file.c12
-rw-r--r--sys/fs/fuse/fuse_vnops.c13
2 files changed, 23 insertions, 2 deletions
diff --git a/sys/fs/fuse/fuse_file.c b/sys/fs/fuse/fuse_file.c
index d9fb67b..cde99dc 100644
--- a/sys/fs/fuse/fuse_file.c
+++ b/sys/fs/fuse/fuse_file.c
@@ -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);
diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c
index f2d0188..afced58 100644
--- a/sys/fs/fuse/fuse_vnops.c
+++ b/sys/fs/fuse/fuse_vnops.c
@@ -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);
OpenPOWER on IntegriCloud