Linux-Fsdevel Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Amir Goldstein <amir73il@gmail.com>
To: Alessio Balsini <balsini@android.com>
Cc: Miklos Szeredi <miklos@szeredi.hu>,
	Akilesh Kailash <akailash@google.com>,
	David Anderson <dvander@google.com>,
	Eric Yan <eric.yan@oneplus.com>, Jann Horn <jannh@google.com>,
	Jens Axboe <axboe@kernel.dk>, Martijn Coenen <maco@android.com>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Paul Lawrence <paullawrence@google.com>,
	Stefano Duo <stefanoduo@google.com>,
	Zimuzo Ezeozue <zezeozue@google.com>,
	fuse-devel <fuse-devel@lists.sourceforge.net>,
	kernel-team <kernel-team@android.com>,
	linux-fsdevel <linux-fsdevel@vger.kernel.org>,
	linux-kernel <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH V8 1/3] fuse: Definitions and ioctl() for passthrough
Date: Sat, 12 Sep 2020 14:06:02 +0300	[thread overview]
Message-ID: <CAOQ4uxiWK5dNMkrriApMVZQi6apmnMijcCw5j4fa2thHFdnFcw@mail.gmail.com> (raw)
In-Reply-To: <20200911163403.79505-2-balsini@android.com>

On Fri, Sep 11, 2020 at 7:34 PM Alessio Balsini <balsini@android.com> wrote:
>
> Introduce the new FUSE passthrough ioctl(), which allows userspace to
> specify a direct connection between a FUSE file and a lower file system
> file.
> Such ioctl() requires userspace to specify:
> - the file descriptor of one of its opened files,
> - the unique identifier of the FUSE request associated with a pending
>   open/create operation,
> both encapsulated into a fuse_passthrough_out data structure.
> The ioctl() will search for the pending FUSE request matching the unique
> identifier, and update the passthrough file pointer of the request with the
> file pointer referenced by the passed file descriptor.
> When that pending FUSE request is handled, the passthrough file pointer
> is copied to the fuse_file data structure, so that the link between FUSE
> and lower file system is consolidated.
>
> In order for the passthrough mode to be successfully activated, the lower
> file system file must implement both read_ and write_iter file operations.
> This extra check avoids special pseudofiles to be targets for this feature.
> An additional enforced limitation is that when FUSE passthrough is enabled,
> no further file system stacking is allowed.
>
> Signed-off-by: Alessio Balsini <balsini@android.com>
> ---
[...]
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index bba747520e9b..eb223130a917 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -965,6 +965,12 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_args *args,
>                                         min_t(unsigned int, FUSE_MAX_MAX_PAGES,
>                                         max_t(unsigned int, arg->max_pages, 1));
>                         }
> +                       if (arg->flags & FUSE_PASSTHROUGH) {
> +                               fc->passthrough = 1;
> +                               /* Prevent further stacking */
> +                               fc->sb->s_stack_depth =
> +                                       FILESYSTEM_MAX_STACK_DEPTH;
> +                       }

That seems a bit limiting.
I suppose what you really want to avoid is loops into FUSE fd.
There may be a way to do this with forbidding overlay over FUSE passthrough
or the other way around.

You can set fc->sb->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH - 1
here and in passthrough ioctl you can check for looping into a fuse fs with
passthrough enabled on the passed fd (see below) ...


>                 } else {
>                         ra_pages = fc->max_read / PAGE_SIZE;
>                         fc->no_lock = 1;
> @@ -1002,7 +1008,8 @@ void fuse_send_init(struct fuse_conn *fc)
>                 FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT |
>                 FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL |
>                 FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS |
> -               FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA;
> +               FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA |
> +               FUSE_PASSTHROUGH;
>         ia->args.opcode = FUSE_INIT;
>         ia->args.in_numargs = 1;
>         ia->args.in_args[0].size = sizeof(ia->in);
> diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c
> new file mode 100644
> index 000000000000..86ab4eafa7bf
> --- /dev/null
> +++ b/fs/fuse/passthrough.c
> @@ -0,0 +1,55 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include "fuse_i.h"
> +
> +int fuse_passthrough_setup(struct fuse_req *req, unsigned int fd)
> +{
> +       int ret;
> +       int fs_stack_depth;
> +       struct file *passthrough_filp;
> +       struct inode *passthrough_inode;
> +       struct super_block *passthrough_sb;
> +
> +       /* Passthrough mode can only be enabled at file open/create time */
> +       if (req->in.h.opcode != FUSE_OPEN && req->in.h.opcode != FUSE_CREATE) {
> +               pr_err("FUSE: invalid OPCODE for request.\n");
> +               return -EINVAL;
> +       }
> +
> +       passthrough_filp = fget(fd);
> +       if (!passthrough_filp) {
> +               pr_err("FUSE: invalid file descriptor for passthrough.\n");
> +               return -EINVAL;
> +       }
> +
> +       ret = -EINVAL;
> +       if (!passthrough_filp->f_op->read_iter ||
> +           !passthrough_filp->f_op->write_iter) {
> +               pr_err("FUSE: passthrough file misses file operations.\n");
> +               goto out;
> +       }
> +
> +       passthrough_inode = file_inode(passthrough_filp);
> +       passthrough_sb = passthrough_inode->i_sb;
> +       fs_stack_depth = passthrough_sb->s_stack_depth + 1;

... for example:

       if (fs_stack_depth && passthrough_sb->s_type == fuse_fs_type) {
               pr_err("FUSE: stacked passthrough file\n");
               goto out;
       }

But maybe we want to ban passthrough to any lower FUSE at least for start.

> +       ret = -EEXIST;

Why EEXIST? Why not EINVAL?

> +       if (fs_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
> +               pr_err("FUSE: maximum fs stacking depth exceeded for passthrough\n");
> +               goto out;
> +       }
> +
> +       req->args->passthrough_filp = passthrough_filp;
> +       return 0;
> +out:
> +       fput(passthrough_filp);
> +       return ret;
> +}
> +

And speaking of overlayfs, I believe you may be able to test your code with
fuse-overlayfs (passthrough to upper files).

This is a project with real users running real workloads who may be
able to provide you with valuable feedback from testing.

Thanks,
Amir.

[1] https://github.com/containers/fuse-overlayfs

  reply	other threads:[~2020-09-12 11:06 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-11 16:34 [PATCH V8 0/3] fuse: Add support for passthrough read/write Alessio Balsini
2020-09-11 16:34 ` [PATCH V8 1/3] fuse: Definitions and ioctl() for passthrough Alessio Balsini
2020-09-12 11:06   ` Amir Goldstein [this message]
2020-09-18 16:33     ` Alessio Balsini
2020-09-18 19:59       ` Amir Goldstein
2020-09-22 12:15         ` Alessio Balsini
2020-09-22 16:08           ` Amir Goldstein
2020-09-29 14:30             ` Alessio Balsini
2020-09-11 16:34 ` [PATCH V8 2/3] fuse: Introduce synchronous read and write " Alessio Balsini
2020-09-12  9:55   ` Amir Goldstein
2020-09-21 11:01     ` Alessio Balsini
2020-09-21 13:07       ` Amir Goldstein
2020-09-11 16:34 ` [PATCH V8 3/3] fuse: Handle AIO read and write in passthrough Alessio Balsini
2020-09-11 17:23   ` Jens Axboe
2020-09-21 15:28     ` Alessio Balsini
2020-09-11 18:46 ` [fuse-devel] [PATCH V8 0/3] fuse: Add support for passthrough read/write Antonio SJ Musumeci
2020-09-18 16:03   ` Alessio Balsini

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=CAOQ4uxiWK5dNMkrriApMVZQi6apmnMijcCw5j4fa2thHFdnFcw@mail.gmail.com \
    --to=amir73il@gmail.com \
    --cc=akailash@google.com \
    --cc=axboe@kernel.dk \
    --cc=balsini@android.com \
    --cc=dvander@google.com \
    --cc=eric.yan@oneplus.com \
    --cc=fuse-devel@lists.sourceforge.net \
    --cc=jannh@google.com \
    --cc=kernel-team@android.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maco@android.com \
    --cc=miklos@szeredi.hu \
    --cc=palmer@dabbelt.com \
    --cc=paullawrence@google.com \
    --cc=stefanoduo@google.com \
    --cc=zezeozue@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).