linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Miklos Szeredi <miklos@szeredi.hu>
To: Bernd Schubert <bschubert@ddn.com>
Cc: linux-fsdevel@vger.kernel.org, dsingh@ddn.com,
	 Amir Goldstein <amir73il@gmail.com>
Subject: Re: [PATCH v2 5/5] fuse: introduce inode io modes
Date: Thu, 1 Feb 2024 15:47:01 +0100	[thread overview]
Message-ID: <CAJfpegvUfQw4TF7Vz_=GMO9Ta=6Yb8zUfRaGMm4AzCXOTdYEAA@mail.gmail.com> (raw)
In-Reply-To: <20240131230827.207552-6-bschubert@ddn.com>

On Thu, 1 Feb 2024 at 00:09, Bernd Schubert <bschubert@ddn.com> wrote:
>
> From: Amir Goldstein <amir73il@gmail.com>
>
> The fuse inode io mode is determined by the mode of its open files/mmaps
> and parallel dio.
>
> - caching io mode - files open in caching mode or mmap on direct_io file
> - direct io mode - no files open in caching mode and no files mmaped
> - parallel dio mode - direct io mode with parallel dio in progress

Specifically if iocachectr is:

> 0 -> caching io
== 0 -> direct io
< 0 -> parallel io

>
> We use a new FOPEN_CACHE_IO flag to explicitly mark a file that was open
> in caching mode.

This is really confusing.  FOPEN_CACHE_IO is apparently an internally
used flag, but it's defined on the userspace API.

a) what is the meaning of this flag on the external API?
b) what is the purpose of this flag internally?

>
> direct_io mmap uses page cache, so first mmap will mark the file as
> FOPEN_DIRECT_IO|FOPEN_CACHE_IO (i.e. mixed mode) and inode will enter
> the caching io mode.
>
> If the server opens the file with flags FOPEN_DIRECT_IO|FOPEN_CACHE_IO,
> the inode enters caching io mode already on open.
>
> This allows executing parallel dio when inode is not in caching mode
> even if shared mmap is allowed, but no mmaps have been performed on
> the inode in question.
>
> An open in caching mode and mmap on direct_io file now waits for all
> in-progress parallel dio writes to complete, so paralle dio writes
> together with FUSE_DIRECT_IO_ALLOW_MMAP is enabled by this commit.

I think the per file state is wrong, the above can be done with just
the per-inode state.


>
> Signed-off-by: Bernd Schubert <bschubert@ddn.com>
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> ---
>  fs/fuse/file.c            | 215 ++++++++++++++++++++++++++++++++++++--
>  fs/fuse/fuse_i.h          |  79 +++++++++++++-
>  include/uapi/linux/fuse.h |   2 +
>  3 files changed, 286 insertions(+), 10 deletions(-)
>
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index 7d2f4b0eb36a..eb9929ff9f60 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -105,10 +105,177 @@ static void fuse_release_end(struct fuse_mount *fm, struct fuse_args *args,
>         kfree(ra);
>  }
>
> +static bool fuse_file_is_direct_io(struct file *file)
> +{
> +       struct fuse_file *ff = file->private_data;
> +
> +       return ff->open_flags & FOPEN_DIRECT_IO || file->f_flags & O_DIRECT;
> +}

This is one of the issues with the per-file state. O_DIRECT can be
changed with fcntl(fd, F_SETFL, ...), so state calculated at open can
go stale.

> +
> +/*
> + * Wait for cached io to be allowed -
> + * Blocks new parallel dio writes and waits for the in-progress parallel dio
> + * writes to complete.
> + */
> +static int fuse_inode_wait_for_cached_io(struct fuse_inode *fi)
> +{
> +       int err = 0;
> +
> +       assert_spin_locked(&fi->lock);
> +
> +       while (!err && !fuse_inode_get_io_cache(fi)) {
> +               /*
> +                * Setting the bit advises new direct-io writes
> +                * to use an exclusive lock - without it the wait below
> +                * might be forever.
> +                */
> +               set_bit(FUSE_I_CACHE_IO_MODE, &fi->state);
> +               spin_unlock(&fi->lock);
> +               err = wait_event_killable(fi->direct_io_waitq,
> +                                         fuse_is_io_cache_allowed(fi));
> +               spin_lock(&fi->lock);
> +       }
> +       /* Clear FUSE_I_CACHE_IO_MODE flag if failed to enter caching mode */
> +       if (err && fi->iocachectr <= 0)
> +               clear_bit(FUSE_I_CACHE_IO_MODE, &fi->state);
> +
> +       return err;
> +}

I suggest moving all infrastructure, including the inline helpers in
fuse_i.h into a separate source file.

> +
> +/* Start cached io mode where parallel dio writes are not allowed */
> +static int fuse_file_cached_io_start(struct inode *inode)
> +{
> +       struct fuse_inode *fi = get_fuse_inode(inode);
> +       int err;
> +
> +       spin_lock(&fi->lock);
> +       err = fuse_inode_wait_for_cached_io(fi);
> +       spin_unlock(&fi->lock);
> +       return err;
> +}
> +
> +static void fuse_file_cached_io_end(struct inode *inode)
> +{
> +       struct fuse_inode *fi = get_fuse_inode(inode);
> +
> +       spin_lock(&fi->lock);
> +       fuse_inode_put_io_cache(get_fuse_inode(inode));
> +       spin_unlock(&fi->lock);
> +}
> +
> +/* Start strictly uncached io mode where cache access is not allowed */
> +static int fuse_file_uncached_io_start(struct inode *inode)
> +{
> +       struct fuse_inode *fi = get_fuse_inode(inode);
> +       bool ok;
> +
> +       spin_lock(&fi->lock);
> +       ok = fuse_inode_deny_io_cache(fi);
> +       spin_unlock(&fi->lock);
> +       return ok ? 0 : -ETXTBSY;
> +}
> +
> +static void fuse_file_uncached_io_end(struct inode *inode)
> +{
> +       struct fuse_inode *fi = get_fuse_inode(inode);
> +       bool allow_cached_io;
> +
> +       spin_lock(&fi->lock);
> +       allow_cached_io = fuse_inode_allow_io_cache(fi);
> +       spin_unlock(&fi->lock);
> +       if (allow_cached_io)
> +               wake_up(&fi->direct_io_waitq);
> +}
> +
> +/* Open flags to determine regular file io mode */
> +#define FOPEN_IO_MODE_MASK \
> +       (FOPEN_DIRECT_IO | FOPEN_CACHE_IO)
> +
> +/* Request access to submit new io to inode via open file */
> +static int fuse_file_io_open(struct file *file, struct inode *inode)
> +{
> +       struct fuse_file *ff = file->private_data;
> +       int iomode_flags = ff->open_flags & FOPEN_IO_MODE_MASK;
> +       int err;
> +
> +       err = -EBUSY;
> +       if (WARN_ON(ff->io_opened))
> +               goto fail;
> +
> +       if (!S_ISREG(inode->i_mode) || FUSE_IS_DAX(inode)) {

This S_ISREG check can also go away with separating the directory opens.

  reply	other threads:[~2024-02-01 14:47 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-31 23:08 [PATCH v2 0/5] fuse: inode IO modes and mmap Bernd Schubert
2024-01-31 23:08 ` [PATCH v2 1/5] fuse: Fix VM_MAYSHARE and direct_io_allow_mmap Bernd Schubert
2024-02-01  8:45   ` Miklos Szeredi
2024-02-01 14:36     ` Bernd Schubert
2024-02-01 14:52       ` Miklos Szeredi
2024-02-01 15:39         ` Bernd Schubert
2024-02-01 15:43           ` Miklos Szeredi
2024-02-01 15:48             ` Amir Goldstein
2024-02-01 16:16               ` Bernd Schubert
2024-02-02 14:47             ` Bernd Schubert
2024-01-31 23:08 ` [PATCH v2 2/5] fuse: Create helper function if DIO write needs exclusive lock Bernd Schubert
2024-02-06  9:20   ` Jingbo Xu
2024-02-07 13:38     ` Bernd Schubert
2024-02-07 13:44       ` Jingbo Xu
2024-02-07 14:13         ` Bernd Schubert
2024-02-08  0:04           ` Jingbo Xu
2024-01-31 23:08 ` [PATCH v2 3/5] fuse: Add fuse_dio_lock/unlock helper functions Bernd Schubert
2024-01-31 23:08 ` [PATCH v2 4/5] fuse: prepare for failing open response Bernd Schubert
2024-02-01  9:23   ` Miklos Szeredi
2024-02-01 10:16     ` Amir Goldstein
2024-02-01 10:28       ` Miklos Szeredi
2024-02-01 10:41         ` Amir Goldstein
2024-02-01 10:51           ` Miklos Szeredi
2024-02-01 16:46             ` Amir Goldstein
2024-02-02 12:03               ` Amir Goldstein
2024-02-02 15:49                 ` Miklos Szeredi
2024-02-02 15:55   ` Miklos Szeredi
2024-02-02 16:07     ` Amir Goldstein
2024-01-31 23:08 ` [PATCH v2 5/5] fuse: introduce inode io modes Bernd Schubert
2024-02-01 14:47   ` Miklos Szeredi [this message]
2024-02-01 16:33     ` Amir Goldstein
2024-02-01 17:53       ` Bernd Schubert
2024-02-02 19:40         ` Amir Goldstein
2024-02-06 12:39       ` Amir Goldstein
2024-02-06 12:53         ` Miklos Szeredi
2024-02-06 13:07           ` Amir Goldstein
2024-02-01 10:30 ` [PATCH v2 0/5] fuse: inode IO modes and mmap Amir Goldstein
2024-02-01 14:30   ` Bernd Schubert
2024-02-01 15:56     ` Amir Goldstein
2024-02-01 16:01       ` 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='CAJfpegvUfQw4TF7Vz_=GMO9Ta=6Yb8zUfRaGMm4AzCXOTdYEAA@mail.gmail.com' \
    --to=miklos@szeredi.hu \
    --cc=amir73il@gmail.com \
    --cc=bschubert@ddn.com \
    --cc=dsingh@ddn.com \
    --cc=linux-fsdevel@vger.kernel.org \
    /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).