All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amir Goldstein <amir73il@gmail.com>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: Bernd Schubert <bernd.schubert@fastmail.fm>,
	Daniel Rosenberg <drosen@google.com>,
	Paul Lawrence <paullawrence@google.com>,
	Alessio Balsini <balsini@android.com>,
	Christian Brauner <brauner@kernel.org>,
	fuse-devel@lists.sourceforge.net, linux-fsdevel@vger.kernel.org
Subject: [PATCH v14 06/12] fuse: introduce FUSE_PASSTHROUGH capability
Date: Mon, 16 Oct 2023 19:08:56 +0300	[thread overview]
Message-ID: <20231016160902.2316986-7-amir73il@gmail.com> (raw)
In-Reply-To: <20231016160902.2316986-1-amir73il@gmail.com>

FUSE_PASSTHROUGH capability to passthrough FUSE operations to backing
files will be made available with kernel config CONFIG_FUSE_PASSTHROUGH.

When requesting FUSE_PASSTHROUGH, userspace needs to specify the
max_stack_depth that is allowed for FUSE on top of backing files.

Introduce a refcounted fuse_backing object that will be used to
associate an open backing file with a fuse inode.

This association will be used when replying to OPEN with the flag
FOPEN_PASSTHROUGH to setup passthrough of read/write operations on the
open fuse file to the associated backing file.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/fuse/Kconfig           | 11 +++++++++++
 fs/fuse/Makefile          |  1 +
 fs/fuse/fuse_i.h          | 19 +++++++++++++++++++
 fs/fuse/inode.c           | 20 ++++++++++++++++++++
 fs/fuse/passthrough.c     | 30 ++++++++++++++++++++++++++++++
 include/uapi/linux/fuse.h | 12 ++++++++++--
 6 files changed, 91 insertions(+), 2 deletions(-)
 create mode 100644 fs/fuse/passthrough.c

diff --git a/fs/fuse/Kconfig b/fs/fuse/Kconfig
index 038ed0b9aaa5..8674dbfbe59d 100644
--- a/fs/fuse/Kconfig
+++ b/fs/fuse/Kconfig
@@ -52,3 +52,14 @@ config FUSE_DAX
 
 	  If you want to allow mounting a Virtio Filesystem with the "dax"
 	  option, answer Y.
+
+config FUSE_PASSTHROUGH
+	bool "FUSE passthrough operations support"
+	default y
+	depends on FUSE_FS
+	select FS_STACK
+	help
+	  This allows bypassing FUSE server by mapping specific FUSE operations
+	  to be performed directly on a backing file.
+
+	  If you want to allow passthrough operations, answer Y.
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile
index 0c48b35c058d..504acfb71402 100644
--- a/fs/fuse/Makefile
+++ b/fs/fuse/Makefile
@@ -9,5 +9,6 @@ obj-$(CONFIG_VIRTIO_FS) += virtiofs.o
 
 fuse-y := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o ioctl.o
 fuse-$(CONFIG_FUSE_DAX) += dax.o
+fuse-$(CONFIG_FUSE_PASSTHROUGH) += passthrough.o
 
 virtiofs-y := virtio_fs.o
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 6e6e721f421b..5be51358542e 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -63,6 +63,15 @@ struct fuse_forget_link {
 	struct fuse_forget_link *next;
 };
 
+/** Container for data related to mapping to backing file */
+struct fuse_backing {
+	struct file *file;
+
+	/** refcount */
+	refcount_t count;
+	struct rcu_head rcu;
+};
+
 /** FUSE inode */
 struct fuse_inode {
 	/** Inode data */
@@ -803,6 +812,12 @@ struct fuse_conn {
 	/* Is statx not implemented by fs? */
 	unsigned int no_statx:1;
 
+	/** Passthrough support for read/write IO */
+	unsigned int passthrough:1;
+
+	/** Maximum stack depth for passthrough backing files */
+	int max_stack_depth;
+
 	/** The number of requests waiting for completion */
 	atomic_t num_waiting;
 
@@ -1340,4 +1355,8 @@ 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);
 
+/* passthrough.c */
+struct fuse_backing *fuse_backing_get(struct fuse_backing *fb);
+void fuse_backing_put(struct fuse_backing *fb);
+
 #endif /* _FS_FUSE_I_H */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 2e4eb7cf26fb..7e01eb5a04dc 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1234,6 +1234,24 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
 				fc->create_supp_group = 1;
 			if (flags & FUSE_DIRECT_IO_RELAX)
 				fc->direct_io_relax = 1;
+			/*
+			 * max_stack_depth is the max stack depth of FUSE fs,
+			 * so it has to be at least 1 to support passthrough
+			 * to backing files.
+			 *
+			 * with max_stack_depth > 1, the backing files can be
+			 * on a stacked fs (e.g. overlayfs) themselves and with
+			 * max_stack_depth == 1, FUSE fs can be stacked as the
+			 * underlying fs of a stacked fs (e.g. overlayfs).
+			 */
+			if (IS_ENABLED(CONFIG_FUSE_PASSTHROUGH) &&
+			    (flags & FUSE_PASSTHROUGH) &&
+			    arg->max_stack_depth > 0 &&
+			    arg->max_stack_depth <= FILESYSTEM_MAX_STACK_DEPTH) {
+				fc->passthrough = 1;
+				fc->max_stack_depth = arg->max_stack_depth;
+				fm->sb->s_stack_depth = arg->max_stack_depth;
+			}
 		} else {
 			ra_pages = fc->max_read / PAGE_SIZE;
 			fc->no_lock = 1;
@@ -1289,6 +1307,8 @@ void fuse_send_init(struct fuse_mount *fm)
 #endif
 	if (fm->fc->auto_submounts)
 		flags |= FUSE_SUBMOUNTS;
+	if (IS_ENABLED(CONFIG_FUSE_PASSTHROUGH))
+		flags |= FUSE_PASSTHROUGH;
 
 	ia->in.flags = flags;
 	ia->in.flags2 = flags >> 32;
diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c
new file mode 100644
index 000000000000..e8639c0a9ac6
--- /dev/null
+++ b/fs/fuse/passthrough.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FUSE passthrough to backing file.
+ *
+ * Copyright (c) 2023 CTERA Networks.
+ */
+
+#include "fuse_i.h"
+
+#include <linux/file.h>
+
+struct fuse_backing *fuse_backing_get(struct fuse_backing *fb)
+{
+	if (fb && refcount_inc_not_zero(&fb->count))
+		return fb;
+	return NULL;
+}
+
+static void fuse_backing_free(struct fuse_backing *fb)
+{
+	if (fb->file)
+		fput(fb->file);
+	kfree_rcu(fb, rcu);
+}
+
+void fuse_backing_put(struct fuse_backing *fb)
+{
+	if (fb && refcount_dec_and_test(&fb->count))
+		fuse_backing_free(fb);
+}
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index db92a7202b34..acb42a76f7ff 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -211,6 +211,10 @@
  *  7.39
  *  - add FUSE_DIRECT_IO_RELAX
  *  - add FUSE_STATX and related structures
+ *
+ *  7.40
+ *  - add max_stack_depth to fuse_init_out, add FUSE_PASSTHROUGH flag
+ *  - add FOPEN_PASSTHROUGH
  */
 
 #ifndef _LINUX_FUSE_H
@@ -246,7 +250,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 39
+#define FUSE_KERNEL_MINOR_VERSION 40
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -353,6 +357,7 @@ struct fuse_file_lock {
  * FOPEN_STREAM: the file is stream-like (no file position at all)
  * FOPEN_NOFLUSH: don't flush data cache on close (unless FUSE_WRITEBACK_CACHE)
  * FOPEN_PARALLEL_DIRECT_WRITES: Allow concurrent direct writes on the same inode
+ * FOPEN_PASSTHROUGH: passthrough read/write operations for this open file
  */
 #define FOPEN_DIRECT_IO		(1 << 0)
 #define FOPEN_KEEP_CACHE	(1 << 1)
@@ -361,6 +366,7 @@ struct fuse_file_lock {
 #define FOPEN_STREAM		(1 << 4)
 #define FOPEN_NOFLUSH		(1 << 5)
 #define FOPEN_PARALLEL_DIRECT_WRITES	(1 << 6)
+#define FOPEN_PASSTHROUGH	(1 << 7)
 
 /**
  * INIT request/reply flags
@@ -450,6 +456,7 @@ struct fuse_file_lock {
 #define FUSE_CREATE_SUPP_GROUP	(1ULL << 34)
 #define FUSE_HAS_EXPIRE_ONLY	(1ULL << 35)
 #define FUSE_DIRECT_IO_RELAX	(1ULL << 36)
+#define FUSE_PASSTHROUGH	(1ULL << 37)
 
 /**
  * CUSE INIT request/reply flags
@@ -875,7 +882,8 @@ struct fuse_init_out {
 	uint16_t	max_pages;
 	uint16_t	map_alignment;
 	uint32_t	flags2;
-	uint32_t	unused[7];
+	uint32_t	max_stack_depth;
+	uint32_t	unused[6];
 };
 
 #define CUSE_INIT_INFO_MAX 4096
-- 
2.34.1


  parent reply	other threads:[~2023-10-16 16:09 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-16 16:08 [PATCH v14 00/12] FUSE passthrough for file io Amir Goldstein
2023-10-16 16:08 ` [PATCH v14 01/12] fs: prepare for stackable filesystems backing file helpers Amir Goldstein
2023-10-16 16:08 ` [PATCH v14 02/12] fs: factor out backing_file_{read,write}_iter() helpers Amir Goldstein
2023-10-16 16:08 ` [PATCH v14 03/12] fs: factor out backing_file_splice_{read,write}() helpers Amir Goldstein
2023-10-16 16:08 ` [PATCH v14 04/12] fs: factor out backing_file_mmap() helper Amir Goldstein
2023-10-16 16:08 ` [PATCH v14 05/12] fuse: factor out helper for FUSE_DEV_IOC_CLONE Amir Goldstein
2023-10-16 16:08 ` Amir Goldstein [this message]
2023-10-16 16:08 ` [PATCH v14 07/12] fuse: pass optional backing_id in struct fuse_open_out Amir Goldstein
2023-10-16 16:08 ` [PATCH v14 08/12] fuse: implement ioctls to manage backing files Amir Goldstein
2023-10-17  9:45   ` Amir Goldstein
2023-10-16 16:08 ` [PATCH v14 09/12] fuse: implement read/write passthrough Amir Goldstein
2023-10-16 16:09 ` [PATCH v14 10/12] fuse: implement splice_{read/write} passthrough Amir Goldstein
2023-10-16 16:09 ` [PATCH v14 11/12] fuse: implement passthrough for mmap Amir Goldstein
2023-10-16 16:09 ` [PATCH v14 12/12] fuse: implement passthrough for readdir Amir Goldstein
2023-10-19 14:33 ` [PATCH v14 00/12] FUSE passthrough for file io Amir Goldstein
2023-10-30 10:16   ` Miklos Szeredi
2023-10-31 10:28     ` Amir Goldstein
2023-10-31 11:16       ` Miklos Szeredi
2023-10-31 12:31         ` Amir Goldstein
2023-10-31 15:01           ` Miklos Szeredi
2023-10-31 17:44             ` Amir Goldstein
2023-11-01 11:32               ` Miklos Szeredi
2023-11-01 13:23                 ` Amir Goldstein
2023-11-01 14:42                   ` Miklos Szeredi
2023-11-01 15:06                     ` Amir Goldstein
2023-11-01 15:25                       ` Miklos Szeredi
2023-11-01 18:32                         ` Amir Goldstein
2023-11-02 10:46                           ` Miklos Szeredi
2023-11-02 13:07                             ` Amir Goldstein
2023-11-02 13:13                               ` Miklos Szeredi
2024-01-26 12:13                                 ` Amir Goldstein
2023-11-29  7:25                     ` Amir Goldstein
2023-11-29 14:13                       ` Miklos Szeredi
2023-11-29 15:06                         ` Amir Goldstein
2023-11-29 15:21                           ` Miklos Szeredi
2023-11-29 15:52                             ` Amir Goldstein
2023-11-29 16:55                               ` Miklos Szeredi
2023-11-29 17:39                                 ` Amir Goldstein
2023-11-29 20:46                                   ` Bernd Schubert
2023-11-29 21:39                                     ` Antonio SJ Musumeci
2023-11-29 22:01                                       ` Bernd Schubert
2023-11-30  7:29                                         ` Amir Goldstein
2023-11-30  7:12                                       ` Amir Goldstein
2023-11-30  8:17                                         ` Miklos Szeredi
2023-12-06  9:59                                 ` Amir Goldstein
2023-12-06 23:11                                   ` Bernd Schubert
2023-12-07  7:23                                     ` Amir Goldstein
2023-12-07  8:56                                       ` Bernd Schubert

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=20231016160902.2316986-7-amir73il@gmail.com \
    --to=amir73il@gmail.com \
    --cc=balsini@android.com \
    --cc=bernd.schubert@fastmail.fm \
    --cc=brauner@kernel.org \
    --cc=drosen@google.com \
    --cc=fuse-devel@lists.sourceforge.net \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=paullawrence@google.com \
    /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.