From: Amir Goldstein <amir73il@gmail.com>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: Daniel Rosenberg <drosen@google.com>,
Paul Lawrence <paullawrence@google.com>,
Alessio Balsini <balsini@android.com>,
fuse-devel@lists.sourceforge.net, linux-fsdevel@vger.kernel.org
Subject: [PATCH v13 03/10] fuse: Passthrough initialization and release
Date: Fri, 19 May 2023 15:56:58 +0300 [thread overview]
Message-ID: <20230519125705.598234-4-amir73il@gmail.com> (raw)
In-Reply-To: <20230519125705.598234-1-amir73il@gmail.com>
Implement the FUSE passthrough ioctl that associates a backing
(passthrough) file with the fuse_file.
The file descriptor passed to the ioctl by the FUSE daemon is used to
access the relative file pointer, that will be copied to the fuse_file
data structure to consolidate the link between the FUSE and the backing
file.
To enable the passthrough mode, FUSE daemon calls the
FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl and, if the call succeeds, receives
back an identifier that will be used at open/create response time in the
fuse_open_out field to associate the FUSE file to the backing file.
The value returned by the ioctl to user space can be:
> 0: success, the value can be used as part of an open/create reply.
<= 0: an error occurred.
== 0: represents an error to preserve backward compatibility - the
fuse_open_out field that is used to pass the backing_id back to the
kernel uses the same bits that were previously as struct padding, and is
commonly zero-initialized (e.g., in the libfuse implementation).
Removing 0 from the correct values fixes the ambiguity between the case
in which 0 corresponds to a real backing_id, a missing implementation
of FUSE passthrough or a request for a normal FUSE file, simplifying the
user space implementation.
For the passthrough mode to be successfully activated, the backing file
filesystem must implement both read_iter and write_iter file operations.
This extra check avoids special pseudo files to be used for passhrough.
Passthrough comes with another limitation: no further filesystem stacking
is allowed for those FUSE filesystems using passthrough.
The FUSE daemon must call FUSE_DEV_IOC_PASSTHROUGH_CLOSE ioctl to drop
the reference on the backing file. This can be done immediattely after
responding to open or at a later time.
In any case, the backing file will be kept open by the FUSE driver until
the last fuse_file that was setup to passthrough to that backing file is
closed AND the FUSE_DEV_IOC_PASSTHROUGH_CLOSE ioctl was called.
Signed-off-by: Alessio Balsini <balsini@android.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
fs/fuse/fuse_i.h | 1 +
fs/fuse/inode.c | 1 +
fs/fuse/passthrough.c | 89 +++++++++++++++++++++++++++++++++++++++++--
3 files changed, 87 insertions(+), 4 deletions(-)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index f52604534ff6..9ad1cc37a5c4 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -181,6 +181,7 @@ struct fuse_passthrough {
/** refcount */
refcount_t count;
+ struct rcu_head rcu;
};
/** FUSE specific file data */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 271586fac008..4200fb13883e 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1301,6 +1301,7 @@ static int fuse_passthrough_id_free(int id, void *p, void *data)
WARN_ON_ONCE(refcount_read(&passthrough->count) != 1);
fuse_passthrough_free(passthrough);
+
return 0;
}
diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c
index fc723e004de9..8d090ae252f2 100644
--- a/fs/fuse/passthrough.c
+++ b/fs/fuse/passthrough.c
@@ -3,6 +3,7 @@
#include "fuse_i.h"
#include <linux/file.h>
+#include <linux/idr.h>
/*
* Returns passthrough_fh id that can be passed with FOPEN_PASSTHROUGH
@@ -10,18 +11,98 @@
*/
int fuse_passthrough_open(struct fuse_conn *fc, int backing_fd)
{
- return -EINVAL;
+ struct file *passthrough_filp;
+ struct inode *passthrough_inode;
+ struct super_block *passthrough_sb;
+ struct fuse_passthrough *passthrough;
+ int res;
+
+ if (!fc->passthrough)
+ return -EPERM;
+
+ passthrough_filp = fget(backing_fd);
+ if (!passthrough_filp)
+ return -EBADF;
+
+ res = -EOPNOTSUPP;
+ if (!passthrough_filp->f_op->read_iter ||
+ !passthrough_filp->f_op->write_iter)
+ goto out_fput;
+
+ passthrough_inode = file_inode(passthrough_filp);
+ passthrough_sb = passthrough_inode->i_sb;
+ res = -ELOOP;
+ if (passthrough_sb->s_stack_depth >= FILESYSTEM_MAX_STACK_DEPTH)
+ goto out_fput;
+
+ passthrough = kmalloc(sizeof(struct fuse_passthrough), GFP_KERNEL);
+ res = -ENOMEM;
+ if (!passthrough)
+ goto out_fput;
+
+ passthrough->filp = passthrough_filp;
+ refcount_set(&passthrough->count, 1);
+
+ idr_preload(GFP_KERNEL);
+ spin_lock(&fc->lock);
+ res = idr_alloc_cyclic(&fc->passthrough_files_map, passthrough, 1, 0,
+ GFP_ATOMIC);
+ spin_unlock(&fc->lock);
+ idr_preload_end();
+
+ if (res < 0)
+ fuse_passthrough_free(passthrough);
+
+ return res;
+
+out_fput:
+ fput(passthrough_filp);
+
+ return res;
}
int fuse_passthrough_close(struct fuse_conn *fc, int passthrough_fh)
{
- return -EINVAL;
+ struct fuse_passthrough *passthrough;
+
+ if (!fc->passthrough)
+ return -EPERM;
+
+ if (passthrough_fh <= 0)
+ return -EINVAL;
+
+ spin_lock(&fc->lock);
+ passthrough = idr_remove(&fc->passthrough_files_map, passthrough_fh);
+ spin_unlock(&fc->lock);
+
+ if (!passthrough)
+ return -ENOENT;
+
+ fuse_passthrough_put(passthrough);
+
+ return 0;
}
int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff,
struct fuse_open_out *openarg)
{
- return -EINVAL;
+ int passthrough_fh = openarg->passthrough_fh;
+ struct fuse_passthrough *passthrough;
+
+ if (passthrough_fh <= 0)
+ return -EINVAL;
+
+ rcu_read_lock();
+ passthrough = idr_find(&fc->passthrough_files_map, passthrough_fh);
+ if (passthrough && !refcount_inc_not_zero(&passthrough->count))
+ passthrough = NULL;
+ rcu_read_unlock();
+ if (!passthrough)
+ return -ENOENT;
+
+ ff->passthrough = passthrough;
+
+ return 0;
}
void fuse_passthrough_put(struct fuse_passthrough *passthrough)
@@ -36,5 +117,5 @@ void fuse_passthrough_free(struct fuse_passthrough *passthrough)
fput(passthrough->filp);
passthrough->filp = NULL;
}
- kfree(passthrough);
+ kfree_rcu(passthrough, rcu);
}
--
2.34.1
next prev parent reply other threads:[~2023-05-19 12:58 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-19 12:56 [PATCH v13 00/10] fuse: Add support for passthrough read/write Amir Goldstein
2023-05-19 12:56 ` [PATCH v13 01/10] fs: Generic function to convert iocb to rw flags Amir Goldstein
2023-05-19 12:56 ` [PATCH v13 02/10] fuse: Definitions and ioctl for passthrough Amir Goldstein
2023-05-19 15:12 ` Miklos Szeredi
2023-05-20 10:20 ` Amir Goldstein
2023-05-22 14:50 ` Miklos Szeredi
2023-05-24 10:00 ` Amir Goldstein
2023-05-19 12:56 ` Amir Goldstein [this message]
2023-05-19 12:56 ` [PATCH v13 04/10] fuse: Introduce synchronous read and write " Amir Goldstein
2023-05-19 12:57 ` [PATCH v13 05/10] fuse: Handle asynchronous read and write in passthrough Amir Goldstein
2023-05-22 15:20 ` Miklos Szeredi
2023-05-24 10:03 ` Amir Goldstein
2023-08-21 15:27 ` Amir Goldstein
2023-08-22 10:18 ` Amir Goldstein
2023-08-22 11:03 ` Miklos Szeredi
2023-08-22 13:22 ` Amir Goldstein
2023-08-22 14:06 ` Miklos Szeredi
2023-08-24 12:11 ` Amir Goldstein
2023-08-29 12:42 ` Miklos Szeredi
2023-05-19 12:57 ` [PATCH v13 06/10] fuse: Use daemon creds in passthrough mode Amir Goldstein
2023-05-19 12:57 ` [PATCH v13 07/10] fuse: Introduce passthrough for mmap Amir Goldstein
2023-05-19 12:57 ` [PATCH v13 08/10] fuse: update inode size/mtime after passthrough write Amir Goldstein
2023-09-25 6:41 ` [External] " Zhang Tianci
2023-09-25 10:43 ` Amir Goldstein
2023-09-26 15:31 ` Jens Axboe
2023-09-26 15:48 ` Amir Goldstein
2023-09-26 16:19 ` Jens Axboe
2023-09-26 16:56 ` Amir Goldstein
2023-05-19 12:57 ` [PATCH v13 09/10] fuse: invalidate atime after passthrough read/mmap Amir Goldstein
2023-05-19 12:57 ` [PATCH v13 10/10] fuse: setup a passthrough fd without a permanent backing id Amir Goldstein
2023-06-06 10:22 ` Fwd: " Miklos Szeredi
2023-06-06 11:00 ` [fuse-devel] " Amir Goldstein
2023-06-06 12:46 ` Miklos Szeredi
2023-05-20 10:28 ` [PATCH v13 00/10] fuse: Add support for passthrough read/write Amir Goldstein
2023-06-06 9:13 ` Amir Goldstein
2023-06-06 9:49 ` Miklos Szeredi
2023-06-06 11:19 ` Amir Goldstein
2023-06-06 13:06 ` Miklos Szeredi
2023-08-29 18:14 ` Amir Goldstein
2023-09-20 13:56 ` Amir Goldstein
2023-09-20 18:15 ` Miklos Szeredi
2023-09-21 7:33 ` Amir Goldstein
2023-09-21 8:21 ` Miklos Szeredi
2023-09-21 9:17 ` Amir Goldstein
2023-09-21 9:30 ` Miklos Szeredi
2023-09-21 10:31 ` Amir Goldstein
2023-09-21 11:50 ` Miklos Szeredi
2023-09-22 12:45 ` Amir Goldstein
2023-10-08 17:53 ` Amir Goldstein
2023-10-10 14:31 ` Miklos Szeredi
2023-10-10 15:14 ` Amir Goldstein
2023-10-14 16:01 ` Amir Goldstein
2023-10-16 10:30 ` Amir Goldstein
2023-10-16 13:21 ` Miklos Szeredi
2023-10-16 19:16 ` 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=20230519125705.598234-4-amir73il@gmail.com \
--to=amir73il@gmail.com \
--cc=balsini@android.com \
--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.