From: Joanne Koong <joannelkoong@gmail.com>
To: miklos@szeredi.hu
Cc: amir73il@gmail.com, fuse-devel@lists.linux.dev, luis@igalia.com
Subject: [PATCH v1 08/17] fuse: add passthrough ops gating
Date: Mon, 20 Apr 2026 15:16:28 -0700 [thread overview]
Message-ID: <20260420221637.2631478-9-joannelkoong@gmail.com> (raw)
In-Reply-To: <20260420221637.2631478-1-joannelkoong@gmail.com>
Route existing callers through a passthrough ops mask check to verify
whether passthrough can be called for the operation or not. The check is
only done when FUSE_PASSTHROUGH_INO mode is enabled, which preserves
backwards compatibility with prior passthrough behavior.
It is safe to get the backing file by accessing ff->passthrough directly
in passthrough.c because passthrough.c is only compiled with
CONFIG_FUSE_PASSTHROUGH=y and the caller has already done the ops check.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
fs/fuse/file.c | 14 ++++++++------
fs/fuse/fuse_i.h | 14 +++++++++++++-
fs/fuse/passthrough.c | 12 ++++++------
fs/fuse/readdir.c | 2 +-
4 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index e719c54c12d2..a1de70bc589d 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -324,7 +324,7 @@ static void fuse_prepare_release(struct fuse_inode *fi, struct fuse_file *ff,
struct fuse_conn *fc = ff->fm->fc;
struct fuse_release_args *ra = &ff->args->release_args;
- if (fuse_file_passthrough(ff))
+ if (fuse_file_passthrough(&fi->inode, ff, 0))
fuse_passthrough_release(ff, fuse_inode_backing(fi));
/* Inode is NULL on error path of fuse_create_open() */
@@ -1838,7 +1838,7 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
/* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */
if (ff->open_flags & FOPEN_DIRECT_IO)
return fuse_direct_read_iter(iocb, to);
- else if (fuse_file_passthrough(ff))
+ else if (fuse_file_passthrough(inode, ff, FUSE_PASSTHROUGH_OP_READ))
return fuse_passthrough_read_iter(iocb, to);
else
return fuse_cache_read_iter(iocb, to);
@@ -1859,7 +1859,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
/* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */
if (ff->open_flags & FOPEN_DIRECT_IO)
return fuse_direct_write_iter(iocb, from);
- else if (fuse_file_passthrough(ff))
+ else if (fuse_file_passthrough(inode, ff, FUSE_PASSTHROUGH_OP_WRITE))
return fuse_passthrough_write_iter(iocb, from);
else
return fuse_cache_write_iter(iocb, from);
@@ -1872,7 +1872,8 @@ static ssize_t fuse_splice_read(struct file *in, loff_t *ppos,
struct fuse_file *ff = in->private_data;
/* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */
- if (fuse_file_passthrough(ff) && !(ff->open_flags & FOPEN_DIRECT_IO))
+ if (fuse_file_passthrough(file_inode(in), ff, FUSE_PASSTHROUGH_OP_READ) &&
+ !(ff->open_flags & FOPEN_DIRECT_IO))
return fuse_passthrough_splice_read(in, ppos, pipe, len, flags);
else
return filemap_splice_read(in, ppos, pipe, len, flags);
@@ -1884,7 +1885,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_file_passthrough(file_inode(out), ff, FUSE_PASSTHROUGH_OP_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);
@@ -2397,7 +2399,7 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
* in passthrough mode, either mmap to backing file or fail mmap,
* because mixing cached mmap and passthrough io mode is not allowed.
*/
- if (fuse_file_passthrough(ff))
+ if (fuse_file_passthrough(inode, ff, FUSE_PASSTHROUGH_RW_OPS))
return fuse_passthrough_mmap(file, vma);
else if (fuse_inode_backing(get_fuse_inode(inode)))
return -ENODEV;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index a15fb508fd28..45d9184d0f7a 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1630,9 +1630,21 @@ static inline struct fuse_backing *fuse_inode_backing_set(struct fuse_inode *fi,
struct fuse_backing *fuse_passthrough_open(struct file *file, int backing_id);
void fuse_passthrough_release(struct fuse_file *ff, struct fuse_backing *fb);
-static inline struct file *fuse_file_passthrough(struct fuse_file *ff)
+static inline struct file *fuse_file_passthrough(struct inode *inode,
+ struct fuse_file *ff,
+ u64 passthrough_ops)
{
#ifdef CONFIG_FUSE_PASSTHROUGH
+ if (!ff->passthrough)
+ return NULL;
+
+ if (ff->fm->fc->passthrough_ino && passthrough_ops) {
+ struct fuse_backing *fb = fuse_inode_backing(get_fuse_inode(inode));
+
+ if (!fb || (fb->ops_mask & passthrough_ops) != passthrough_ops)
+ return NULL;
+ }
+
return ff->passthrough;
#else
return NULL;
diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c
index 514e4af46d79..8ecce2a97ee8 100644
--- a/fs/fuse/passthrough.c
+++ b/fs/fuse/passthrough.c
@@ -29,7 +29,7 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *iter)
{
struct file *file = iocb->ki_filp;
struct fuse_file *ff = file->private_data;
- struct file *backing_file = fuse_file_passthrough(ff);
+ struct file *backing_file = ff->passthrough;
size_t count = iov_iter_count(iter);
ssize_t ret;
struct backing_file_ctx ctx = {
@@ -56,7 +56,7 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb,
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
struct fuse_file *ff = file->private_data;
- struct file *backing_file = fuse_file_passthrough(ff);
+ struct file *backing_file = ff->passthrough;
size_t count = iov_iter_count(iter);
ssize_t ret;
struct backing_file_ctx ctx = {
@@ -83,7 +83,7 @@ ssize_t fuse_passthrough_splice_read(struct file *in, loff_t *ppos,
size_t len, unsigned int flags)
{
struct fuse_file *ff = in->private_data;
- struct file *backing_file = fuse_file_passthrough(ff);
+ struct file *backing_file = ff->passthrough;
struct backing_file_ctx ctx = {
.cred = ff->cred,
.accessed = fuse_file_accessed,
@@ -107,8 +107,8 @@ ssize_t fuse_passthrough_splice_write(struct pipe_inode_info *pipe,
size_t len, unsigned int flags)
{
struct fuse_file *ff = out->private_data;
- struct file *backing_file = fuse_file_passthrough(ff);
struct inode *inode = file_inode(out);
+ struct file *backing_file = ff->passthrough;
ssize_t ret;
struct backing_file_ctx ctx = {
.cred = ff->cred,
@@ -132,7 +132,7 @@ ssize_t fuse_passthrough_splice_write(struct pipe_inode_info *pipe,
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 file *backing_file = ff->passthrough;
struct backing_file_ctx ctx = {
.cred = ff->cred,
.accessed = fuse_file_accessed,
@@ -150,7 +150,7 @@ int fuse_passthrough_readdir(struct file *file, struct dir_context *ctx)
const struct cred *old_cred;
struct inode *inode = file_inode(file);
struct fuse_file *ff = file->private_data;
- struct file *backing_file = fuse_file_passthrough(ff);
+ struct file *backing_file = ff->passthrough;
bool locked;
pr_debug("%s: backing_file=0x%p, pos=%lld\n", __func__,
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
index 49226f022339..1f2ff63cd317 100644
--- a/fs/fuse/readdir.c
+++ b/fs/fuse/readdir.c
@@ -593,7 +593,7 @@ int fuse_readdir(struct file *file, struct dir_context *ctx)
if (fuse_is_bad(inode))
return -EIO;
- if (fuse_file_passthrough(ff))
+ if (fuse_file_passthrough(inode, ff, FUSE_PASSTHROUGH_OP_READDIR))
return fuse_passthrough_readdir(file, ctx);
err = UNCACHED;
--
2.52.0
next prev parent reply other threads:[~2026-04-20 22:18 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-20 22:16 [PATCH v1 00/17] fuse: extend passthrough to inode operations Joanne Koong
2026-04-20 22:16 ` [PATCH v1 01/17] fuse: introduce FUSE_PASSTHROUGH_INO mode Joanne Koong
2026-04-21 21:11 ` Darrick J. Wong
2026-04-21 23:38 ` Joanne Koong
2026-04-20 22:16 ` [PATCH v1 02/17] fuse: prepare for passthrough of inode operations Joanne Koong
2026-04-21 21:16 ` Darrick J. Wong
2026-04-22 1:12 ` Joanne Koong
2026-04-20 22:16 ` [PATCH v1 03/17] fuse: prepare for readdir passthrough on directories Joanne Koong
2026-04-21 21:17 ` Darrick J. Wong
2026-04-21 23:12 ` Joanne Koong
2026-04-20 22:16 ` [PATCH v1 04/17] fuse: implement passthrough for readdir Joanne Koong
2026-04-20 22:16 ` [PATCH v1 05/17] fuse: prepare for long lived reference on backing file Joanne Koong
2026-04-20 22:16 ` [PATCH v1 06/17] fuse: implement passthrough for getattr/statx Joanne Koong
2026-04-20 22:16 ` [PATCH v1 07/17] fuse: prepare to setup backing inode passthrough on lookup Joanne Koong
2026-04-20 22:16 ` Joanne Koong [this message]
2026-04-21 10:48 ` [PATCH v1 08/17] fuse: add passthrough ops gating Amir Goldstein
2026-04-22 2:57 ` Joanne Koong
2026-04-22 7:27 ` Amir Goldstein
2026-04-23 1:47 ` Joanne Koong
2026-04-20 22:16 ` [PATCH v1 09/17] fuse: prepare to cache statx attributes from entry replies Joanne Koong
2026-04-21 12:26 ` Amir Goldstein
2026-04-20 22:16 ` [PATCH v1 10/17] fuse: add struct fuse_entry2_out and helpers for extended " Joanne Koong
2026-04-21 12:25 ` Amir Goldstein
2026-04-22 0:50 ` Joanne Koong
2026-04-20 22:16 ` [PATCH v1 11/17] fuse: add passthrough lookup Joanne Koong
2026-04-21 13:23 ` Amir Goldstein
2026-04-22 3:17 ` Joanne Koong
2026-04-20 22:16 ` [PATCH v1 12/17] fuse: add passthrough support for entry creation Joanne Koong
2026-04-21 14:08 ` Amir Goldstein
2026-04-22 3:01 ` Joanne Koong
2026-04-20 22:16 ` [PATCH v1 13/17] fuse: add passthrough support for atomic file creation Joanne Koong
2026-04-21 19:51 ` Amir Goldstein
2026-04-22 0:40 ` Joanne Koong
2026-04-22 5:10 ` Amir Goldstein
2026-04-20 22:16 ` [PATCH v1 14/17] fuse: use passthrough getattr in setattr suid/sgid handling Joanne Koong
2026-04-21 14:25 ` Amir Goldstein
2026-04-22 3:48 ` Joanne Koong
2026-04-22 5:22 ` Amir Goldstein
2026-04-23 0:03 ` Joanne Koong
2026-04-20 22:16 ` [PATCH v1 15/17] fuse: add passthrough setattr Joanne Koong
2026-04-21 14:20 ` Amir Goldstein
2026-04-21 14:32 ` Amir Goldstein
2026-04-22 1:09 ` Joanne Koong
2026-04-20 22:16 ` [PATCH v1 16/17] fuse: add passthrough open Joanne Koong
2026-04-21 20:20 ` Amir Goldstein
2026-04-22 4:19 ` Joanne Koong
2026-04-22 4:23 ` Joanne Koong
2026-04-22 6:51 ` Amir Goldstein
2026-04-20 22:16 ` [PATCH v1 17/17] docs: fuse: document extended passthrough (FUSE_PASSTHROUGH_INO) Joanne Koong
2026-04-21 11:09 ` Amir Goldstein
2026-04-22 1:04 ` Joanne Koong
2026-04-21 9:37 ` [PATCH v1 00/17] fuse: extend passthrough to inode operations Amir Goldstein
2026-04-21 13:55 ` Amir Goldstein
2026-04-21 21:05 ` Joanne Koong
2026-04-22 6:02 ` Amir Goldstein
2026-04-23 1:02 ` 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=20260420221637.2631478-9-joannelkoong@gmail.com \
--to=joannelkoong@gmail.com \
--cc=amir73il@gmail.com \
--cc=fuse-devel@lists.linux.dev \
--cc=luis@igalia.com \
--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.