All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joanne Koong <joannelkoong@gmail.com>
To: amir73il@gmail.com, miklos@szeredi.hu
Cc: fuse-devel@lists.linux.dev, linux-unionfs@vger.kernel.org
Subject: [PATCH v2 09/21] fuse: handle partial io passthrough for read/write, splice, and mmap
Date: Fri, 15 May 2026 17:39:52 -0700	[thread overview]
Message-ID: <20260516004004.1455526-10-joannelkoong@gmail.com> (raw)
In-Reply-To: <20260516004004.1455526-1-joannelkoong@gmail.com>

Servers can now pass through only reads or writes instead of being
required to pass through both. When the read or write operation is not
passed through, fall back to direct io for handling it. This avoids
cache coherency issues from mixing the backing file's page cache with
the fuse inode's page cache.

Reject mmap when passthrough is partial or not set for read/writes since
mmap requires both read and write access to the backing page cache.

The FOPEN_DIRECT_IO check in the read/write fallback is not strictly
needed as the caller already handles it, but including it here makes
the fallback logic self-contained.

Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
 fs/fuse/file.c        |  7 ++++---
 fs/fuse/fuse_i.h      |  3 +++
 fs/fuse/passthrough.c | 18 ++++++++++++++++++
 3 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 1173811b2ea7..5b70d8272700 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1781,7 +1781,7 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
 
 static ssize_t fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter);
 
-static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
 	ssize_t res;
 
@@ -1796,7 +1796,7 @@ static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
 	return res;
 }
 
-static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
 	struct inode *inode = file_inode(iocb->ki_filp);
 	ssize_t res;
@@ -1884,7 +1884,8 @@ static ssize_t fuse_splice_write(struct pipe_inode_info *pipe, struct file *out,
 	struct fuse_file *ff = out->private_data;
 
 	/* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */
-	if (fuse_file_passthrough(ff) && !(ff->open_flags & FOPEN_DIRECT_IO))
+	if (fuse_passthrough_op(file_inode(out), FUSE_WRITE) &&
+	    !(ff->open_flags & FOPEN_DIRECT_IO))
 		return fuse_passthrough_splice_write(pipe, out, ppos, len, flags);
 	else
 		return iter_file_splice_write(pipe, out, ppos, len, flags);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 9e5142a94a09..a1034533ce60 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1261,6 +1261,9 @@ struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid,
 void fuse_file_release(struct inode *inode, struct fuse_file *ff,
 		       unsigned int open_flags, fl_owner_t id, bool isdir);
 
+ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to);
+ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from);
+
 /* passthrough.c */
 
 /* READ/WRITE are implied by FOPEN_PASSTHROUGH, but defined for completeness */
diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c
index f2025772c9c1..d62a1c751157 100644
--- a/fs/fuse/passthrough.c
+++ b/fs/fuse/passthrough.c
@@ -44,6 +44,10 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *iter)
 	if (!count)
 		return 0;
 
+	if ((ff->open_flags & FOPEN_DIRECT_IO) ||
+	    !fuse_passthrough_op(file_inode(file), FUSE_READ))
+		return fuse_direct_read_iter(iocb, iter);
+
 	ret = backing_file_read_iter(backing_file, iter, iocb, iocb->ki_flags,
 				     &ctx);
 
@@ -70,6 +74,10 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb,
 	if (!count)
 		return 0;
 
+	if ((ff->open_flags & FOPEN_DIRECT_IO) ||
+	    !fuse_passthrough_op(inode, FUSE_WRITE))
+		return fuse_direct_write_iter(iocb, iter);
+
 	inode_lock(inode);
 	ret = backing_file_write_iter(backing_file, iter, iocb, iocb->ki_flags,
 				      &ctx);
@@ -91,6 +99,9 @@ ssize_t fuse_passthrough_splice_read(struct file *in, loff_t *ppos,
 	struct kiocb iocb;
 	ssize_t ret;
 
+	if (!fuse_passthrough_op(file_inode(in), FUSE_READ))
+		return copy_splice_read(in, ppos, pipe, len, flags);
+
 	pr_debug("%s: backing_file=0x%p, pos=%lld, len=%zu, flags=0x%x\n", __func__,
 		 backing_file, *ppos, len, flags);
 
@@ -133,6 +144,9 @@ ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct fuse_file *ff = file->private_data;
 	struct file *backing_file = fuse_file_passthrough(ff);
+	struct inode *inode = file_inode(file);
+	struct fuse_inode *fi = get_fuse_inode(inode);
+	struct fuse_backing *fb = fuse_inode_backing(fi);
 	struct backing_file_ctx ctx = {
 		.cred = ff->cred,
 		.accessed = fuse_file_accessed,
@@ -141,6 +155,10 @@ ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma)
 	pr_debug("%s: backing_file=0x%p, start=%lu, end=%lu\n", __func__,
 		 backing_file, vma->vm_start, vma->vm_end);
 
+	/* mmap requires both read and write passthrough */
+	if ((fb->ops_mask & FUSE_PASSTHROUGH_RW_OPS) != FUSE_PASSTHROUGH_RW_OPS)
+		return -ENODEV;
+
 	return backing_file_mmap(backing_file, vma, &ctx);
 }
 
-- 
2.52.0


  parent reply	other threads:[~2026-05-16  0:52 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-16  0:39 [PATCH v2 00/21] fuse: extend passthrough to inode operations Joanne Koong
2026-05-16  0:39 ` [PATCH v2 01/21] fuse: introduce FUSE_PASSTHROUGH_INO mode Joanne Koong
2026-05-16  0:39 ` [PATCH v2 02/21] fuse: prepare for passthrough of inode operations Joanne Koong
2026-05-16  1:34   ` Joanne Koong
2026-05-16  0:39 ` [PATCH v2 03/21] fuse: prepare for readdir passthrough on directories Joanne Koong
2026-05-16  0:39 ` [PATCH v2 04/21] fuse: implement passthrough for readdir Joanne Koong
2026-05-16  0:39 ` [PATCH v2 05/21] fuse: prepare for long lived reference on backing file Joanne Koong
2026-05-16  0:39 ` [PATCH v2 06/21] fuse: implement passthrough for getattr/statx Joanne Koong
2026-05-16 12:42   ` Amir Goldstein
2026-05-16  0:39 ` [PATCH v2 07/21] fuse: prepare to setup backing inode passthrough on lookup Joanne Koong
2026-05-16  0:39 ` [PATCH v2 08/21] fuse: handle zero ops_mask in FUSE_DEV_IOC_BACKING_OPEN Joanne Koong
2026-05-16  0:39 ` Joanne Koong [this message]
2026-05-16  0:39 ` [PATCH v2 10/21] fuse: prepare to cache statx attributes from entry replies Joanne Koong
2026-05-16  0:39 ` [PATCH v2 11/21] fuse: clean up fuse_dentry_revalidate() Joanne Koong
2026-05-16  0:39 ` [PATCH v2 12/21] fuse: add struct fuse_entry2_out and helpers for extended entry replies Joanne Koong
2026-05-16  0:39 ` [PATCH v2 13/21] fuse: add passthrough lookup Joanne Koong
2026-05-16  0:39 ` [PATCH v2 14/21] fuse: add passthrough support for entry creation Joanne Koong
2026-05-16  0:39 ` [PATCH v2 15/21] fuse: add passthrough support for create+open Joanne Koong
2026-05-16  0:39 ` [PATCH v2 16/21] fuse: allow backing_id=0 in open to inherit inode's backing file Joanne Koong
2026-05-16  0:40 ` [PATCH v2 17/21] backing-inode: add backing_inode_copyattr() Joanne Koong
2026-05-16  0:40 ` [PATCH v2 18/21] backing-inode: add backing_inode_setattr() Joanne Koong
2026-05-16  0:40 ` [PATCH v2 19/21] fuse: add passthrough setattr Joanne Koong
2026-05-16  1:04   ` Joanne Koong
2026-05-16  0:40 ` [PATCH v2 20/21] fuse: use passthrough getattr in setattr suid/sgid handling Joanne Koong
2026-05-16  1:20   ` Joanne Koong
2026-05-16  0:40 ` [PATCH v2 21/21] docs: fuse: document extended passthrough (FUSE_PASSTHROUGH_INO) Joanne Koong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260516004004.1455526-10-joannelkoong@gmail.com \
    --to=joannelkoong@gmail.com \
    --cc=amir73il@gmail.com \
    --cc=fuse-devel@lists.linux.dev \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.