There were two code paths direct-io writes could take. When daemon/server side did not set FOPEN_DIRECT_IO fuse_cache_write_iter -> direct_write_fallback and with FOPEN_DIRECT_IO being set fuse_direct_write_iter Advantage of fuse_direct_write_iter is that it has optimizations for parallel DIO writes - it might only take a shared inode lock, instead of the exclusive lock. With commits b5a2a3a0b776/80e4f25262f9 the fuse_direct_write_iter path also handles concurrent page IO (dirty flush and page release), just the condition on fc->direct_io_relax had to be removed. Performance wise this basically gives the same improvements as commit 153524053bbb, just O_DIRECT is sufficient, without the need that server side sets FOPEN_DIRECT_IO (it has to set FOPEN_PARALLEL_DIRECT_WRITES), though. Cc: Hao Xu <howeyxu@xxxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxxxxxxxxx> Cc: Miklos Szeredi <miklos@xxxxxxxxxx> Cc: Dharmendra Singh <dsingh@xxxxxxx> Cc: linux-fsdevel@xxxxxxxxxxxxxxx --- fs/fuse/file.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 1cdb6327511e..a5414f46d254 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1338,15 +1338,8 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from) if (err) goto out; - if (iocb->ki_flags & IOCB_DIRECT) { - written = generic_file_direct_write(iocb, from); - if (written < 0 || !iov_iter_count(from)) - goto out; - written = direct_write_fallback(iocb, from, written, - fuse_perform_write(iocb, from)); - } else { - written = fuse_perform_write(iocb, from); - } + written = fuse_perform_write(iocb, from); + out: inode_unlock(inode); if (written > 0) @@ -1441,19 +1434,16 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, int err = 0; struct fuse_io_args *ia; unsigned int max_pages; - bool fopen_direct_io = ff->open_flags & FOPEN_DIRECT_IO; max_pages = iov_iter_npages(iter, fc->max_pages); ia = fuse_io_alloc(io, max_pages); if (!ia) return -ENOMEM; - if (fopen_direct_io && fc->direct_io_relax) { - res = filemap_write_and_wait_range(mapping, pos, pos + count - 1); - if (res) { - fuse_io_free(ia); - return res; - } + res = filemap_write_and_wait_range(mapping, pos, pos + count - 1); + if (res) { + fuse_io_free(ia); + return res; } if (!cuse && fuse_range_is_writeback(inode, idx_from, idx_to)) { if (!write) @@ -1463,7 +1453,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, inode_unlock(inode); } - if (fopen_direct_io && write) { + if (write) { res = invalidate_inode_pages2_range(mapping, idx_from, idx_to); if (res) { fuse_io_free(ia); @@ -1646,7 +1636,8 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (FUSE_IS_DAX(inode)) return fuse_dax_write_iter(iocb, from); - if (!(ff->open_flags & FOPEN_DIRECT_IO)) + if (!(ff->open_flags & FOPEN_DIRECT_IO) && + !(iocb->ki_flags & IOCB_DIRECT)) return fuse_cache_write_iter(iocb, from); else return fuse_direct_write_iter(iocb, from); -- 2.39.2