FILESYSTEM IN USERSPACE (FUSE) development
 help / color / mirror / Atom feed
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 07/17] fuse: prepare to setup backing inode passthrough on lookup
Date: Mon, 20 Apr 2026 15:16:27 -0700	[thread overview]
Message-ID: <20260420221637.2631478-8-joannelkoong@gmail.com> (raw)
In-Reply-To: <20260420221637.2631478-1-joannelkoong@gmail.com>

From: Amir Goldstein <amir73il@gmail.com>

Add a helper for requesting to associate a backing inode for inode
passthrough operations.

This helper is expected to be used to setup backing inode on lookup
response.

The minimal requirement for the backing inode is to support the
GETATTR passthrough op.

Unlike setting of passthrough from open, this mapping is created for
the entire lifetime of the inode and cannot be changed later.

Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/fuse/backing.c     | 32 ++++++++++++++++++++------------
 fs/fuse/fuse_i.h      |  6 ++++--
 fs/fuse/iomode.c      | 39 +++++++++++++++++++++++++++++++++++++++
 fs/fuse/passthrough.c | 12 +++++-------
 4 files changed, 68 insertions(+), 21 deletions(-)

diff --git a/fs/fuse/backing.c b/fs/fuse/backing.c
index 516f58e5ae18..85ac6f917779 100644
--- a/fs/fuse/backing.c
+++ b/fs/fuse/backing.c
@@ -16,6 +16,26 @@ struct fuse_backing *fuse_backing_get(struct fuse_backing *fb)
 	return NULL;
 }
 
+/*
+ * Get fuse backing object by backing id.
+ *
+ * Returns an fb object with elevated refcount to be stored in fuse inode.
+ */
+struct fuse_backing *fuse_backing_id_get(struct fuse_conn *fc, int backing_id)
+{
+	struct fuse_backing *fb;
+
+	if (backing_id <= 0)
+		return ERR_PTR(-EINVAL);
+
+	rcu_read_lock();
+	fb = idr_find(&fc->backing_files_map, backing_id);
+	fb = fuse_backing_get(fb);
+	rcu_read_unlock();
+
+	return fb;
+}
+
 static void fuse_backing_free(struct fuse_backing *fb)
 {
 	pr_debug("%s: fb=0x%p\n", __func__, fb);
@@ -177,15 +197,3 @@ int fuse_backing_close(struct fuse_conn *fc, int backing_id)
 
 	return err;
 }
-
-struct fuse_backing *fuse_backing_lookup(struct fuse_conn *fc, int backing_id)
-{
-	struct fuse_backing *fb;
-
-	rcu_read_lock();
-	fb = idr_find(&fc->backing_files_map, backing_id);
-	fb = fuse_backing_get(fb);
-	rcu_read_unlock();
-
-	return fb;
-}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 1f279b5b618a..a15fb508fd28 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1584,7 +1584,7 @@ void fuse_file_release(struct inode *inode, struct fuse_file *ff,
 #ifdef CONFIG_FUSE_PASSTHROUGH
 struct fuse_backing *fuse_backing_get(struct fuse_backing *fb);
 void fuse_backing_put(struct fuse_backing *fb);
-struct fuse_backing *fuse_backing_lookup(struct fuse_conn *fc, int backing_id);
+struct fuse_backing *fuse_backing_id_get(struct fuse_conn *fc, int backing_id);
 #else
 
 static inline struct fuse_backing *fuse_backing_get(struct fuse_backing *fb)
@@ -1595,7 +1595,7 @@ static inline struct fuse_backing *fuse_backing_get(struct fuse_backing *fb)
 static inline void fuse_backing_put(struct fuse_backing *fb)
 {
 }
-static inline struct fuse_backing *fuse_backing_lookup(struct fuse_conn *fc,
+static inline struct fuse_backing *fuse_backing_id_get(struct fuse_conn *fc,
 						       int backing_id)
 {
 	return NULL;
@@ -1650,6 +1650,8 @@ ssize_t fuse_passthrough_splice_write(struct pipe_inode_info *pipe,
 ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma);
 int fuse_passthrough_readdir(struct file *file, struct dir_context *ctx);
 
+int fuse_inode_set_passthrough(struct inode *inode, int backing_id);
+
 static inline struct fuse_backing *fuse_inode_passthrough(struct fuse_inode *fi)
 {
 #ifdef CONFIG_FUSE_PASSTHROUGH
diff --git a/fs/fuse/iomode.c b/fs/fuse/iomode.c
index 54259ead41a4..7c4053160b8a 100644
--- a/fs/fuse/iomode.c
+++ b/fs/fuse/iomode.c
@@ -181,6 +181,45 @@ static void fuse_file_uncached_io_release(struct fuse_file *ff,
 	fuse_inode_uncached_io_end(inode);
 }
 
+/* Setup passthrough for inode operations without an open file */
+int fuse_inode_set_passthrough(struct inode *inode, int backing_id)
+{
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	struct fuse_inode *fi = get_fuse_inode(inode);
+	struct fuse_backing *fb;
+	int err;
+
+	if (!IS_ENABLED(CONFIG_FUSE_PASSTHROUGH) || !fc->passthrough_ino)
+		return 0;
+
+	/* backing inode is set once for the lifetime of the inode */
+	if (fuse_inode_passthrough(fi))
+		return 0;
+
+	fb = fuse_backing_id_get(fc, backing_id);
+	if (IS_ERR_OR_NULL(fb)) {
+		err = fb ? PTR_ERR(fb) : -ENOENT;
+		fb = NULL;
+		goto fail;
+	}
+
+	/* Backing inode requires at least GETATTR op passthrough */
+	err = -EOPNOTSUPP;
+	if (!(fb->ops_mask & FUSE_PASSTHROUGH_OP_GETATTR))
+		goto fail;
+
+	err = fuse_inode_uncached_io_start(inode, NULL, fb);
+	if (err)
+		goto fail;
+
+	return 0;
+fail:
+	fuse_backing_put(fb);
+	pr_debug("failed to setup backing inode (ino=%lu, backing_id=%d, err=%i).\n",
+		 inode->i_ino, backing_id, err);
+	return err;
+}
+
 /*
  * Open flags that are allowed in combination with FOPEN_PASSTHROUGH.
  * A combination of FOPEN_PASSTHROUGH and FOPEN_DIRECT_IO means that read/write
diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c
index 1baac4f0cb68..514e4af46d79 100644
--- a/fs/fuse/passthrough.c
+++ b/fs/fuse/passthrough.c
@@ -181,14 +181,12 @@ struct fuse_backing *fuse_passthrough_open(struct file *file, int backing_id)
 	struct file *backing_file;
 	int err;
 
-	err = -EINVAL;
-	if (backing_id <= 0)
-		goto out;
-
-	err = -ENOENT;
-	fb = fuse_backing_lookup(fc, backing_id);
-	if (!fb)
+	fb = fuse_backing_id_get(fc, backing_id);
+	if (IS_ERR_OR_NULL(fb)) {
+		err = fb ? PTR_ERR(fb) : -ENOENT;
+		fb = NULL;
 		goto out;
+	}
 
 	/* Allocate backing file per fuse file to store fuse path */
 	backing_file = backing_file_open(&file->f_path, file->f_flags,
-- 
2.52.0


  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 ` Joanne Koong [this message]
2026-04-20 22:16 ` [PATCH v1 08/17] fuse: add passthrough ops gating Joanne Koong
2026-04-21 10:48   ` 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-8-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox