All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: Joanne Koong <joannelkoong@gmail.com>
Cc: miklos@szeredi.hu, amir73il@gmail.com,
	fuse-devel@lists.linux.dev, luis@igalia.com
Subject: Re: [PATCH v1 03/17] fuse: prepare for readdir passthrough on directories
Date: Tue, 21 Apr 2026 14:17:32 -0700	[thread overview]
Message-ID: <20260421211732.GC7739@frogsfrogsfrogs> (raw)
In-Reply-To: <20260420221637.2631478-4-joannelkoong@gmail.com>

On Mon, Apr 20, 2026 at 03:16:23PM -0700, Joanne Koong wrote:
> From: Amir Goldstein <amir73il@gmail.com>
> 
> In preparation for readdir passthrough, allow the inode iomode state
> to be applicable to directory inodes and prepare the helper
> fuse_sync_release() for directories.
> 
> Directory inodes will support cached mode, "direct" uncached readdir
> mode and readdir passthrough mode, but will not need to wait for
> parallel dio like regular files.
> 
> Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> ---
>  fs/fuse/cuse.c   |  2 +-
>  fs/fuse/dir.c    |  4 ++--
>  fs/fuse/file.c   | 11 ++++++-----
>  fs/fuse/fuse_i.h | 12 ++++++------
>  fs/fuse/inode.c  |  2 +-
>  fs/fuse/iomode.c | 31 ++++++++++++++++++-------------
>  6 files changed, 34 insertions(+), 28 deletions(-)
> 
> diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
> index dfcb98a654d8..e168740351a0 100644
> --- a/fs/fuse/cuse.c
> +++ b/fs/fuse/cuse.c
> @@ -147,7 +147,7 @@ static int cuse_release(struct inode *inode, struct file *file)
>  	struct fuse_file *ff = file->private_data;
>  	struct fuse_mount *fm = ff->fm;
>  
> -	fuse_sync_release(NULL, ff, file->f_flags);
> +	fuse_sync_release(NULL, ff, file->f_flags, false);
>  	fuse_conn_put(fm->fc);
>  
>  	return 0;
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index b658b6baf72f..015f0c103d06 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -893,7 +893,7 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir,
>  			  &outentry.attr, ATTR_TIMEOUT(&outentry), 0, 0);
>  	if (!inode) {
>  		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
> -		fuse_sync_release(NULL, ff, flags);
> +		fuse_sync_release(NULL, ff, flags, false);
>  		fuse_queue_forget(fm->fc, forget, outentry.nodeid, 1);
>  		err = -ENOMEM;
>  		goto out_err;
> @@ -910,7 +910,7 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir,
>  	}
>  	if (err) {
>  		fi = get_fuse_inode(inode);
> -		fuse_sync_release(fi, ff, flags);
> +		fuse_sync_release(fi, ff, flags, false);
>  	} else {
>  		if (fm->fc->atomic_o_trunc && trunc)
>  			truncate_pagecache(inode, 0);
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index f239c8a888cb..3da4ce73e11b 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -285,7 +285,7 @@ static int fuse_open(struct inode *inode, struct file *file)
>  		ff = file->private_data;
>  		err = fuse_finish_open(inode, file);
>  		if (err)
> -			fuse_sync_release(fi, ff, file->f_flags);
> +			fuse_sync_release(fi, ff, file->f_flags, false);
>  		else if (is_truncate)
>  			fuse_truncate_update_attr(inode, file);
>  	}
> @@ -408,10 +408,12 @@ static int fuse_release(struct inode *inode, struct file *file)
>  }
>  
>  void fuse_sync_release(struct fuse_inode *fi, struct fuse_file *ff,
> -		       unsigned int flags)
> +		       unsigned int flags, bool isdir)
>  {
> +	int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE;

Can't you figure this out from S_ISDIR(fi->inode.i_mode), and thereby
obviate the need for the extra parameter?

--D

> +
>  	WARN_ON(refcount_read(&ff->count) > 1);
> -	fuse_prepare_release(fi, ff, flags, FUSE_RELEASE, true);
> +	fuse_prepare_release(fi, ff, flags, opcode, true);
>  	fuse_file_put(ff, true);
>  }
>  EXPORT_SYMBOL_GPL(fuse_sync_release);
> @@ -1456,13 +1458,12 @@ static void fuse_dio_lock(struct kiocb *iocb, struct iov_iter *from,
>  static void fuse_dio_unlock(struct kiocb *iocb, bool exclusive)
>  {
>  	struct inode *inode = file_inode(iocb->ki_filp);
> -	struct fuse_inode *fi = get_fuse_inode(inode);
>  
>  	if (exclusive) {
>  		inode_unlock(inode);
>  	} else {
>  		/* Allow opens in caching mode after last parallel dio end */
> -		fuse_inode_uncached_io_end(fi);
> +		fuse_inode_uncached_io_end(inode);
>  		inode_unlock_shared(inode);
>  	}
>  }
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index eb974739dd5e..1c4646ad7c25 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -161,9 +161,6 @@ struct fuse_inode {
>  			 * (FUSE_NOWRITE) means more writes are blocked */
>  			int writectr;
>  
> -			/** Number of files/maps using page cache */
> -			int iocachectr;
> -
>  			/* Waitq for writepage completion */
>  			wait_queue_head_t page_waitq;
>  
> @@ -206,6 +203,9 @@ struct fuse_inode {
>  	/** Lock to protect write related fields */
>  	spinlock_t lock;
>  
> +	/** Number of files/maps using page cache (negative for passthrough) */
> +	int iocachectr;
> +
>  #ifdef CONFIG_FUSE_DAX
>  	/*
>  	 * Dax specific inode data
> @@ -238,7 +238,7 @@ enum {
>  	FUSE_I_BAD,
>  	/* Has btime */
>  	FUSE_I_BTIME,
> -	/* Wants or already has page cache IO */
> +	/* Regular file wants or already has page cache IO */
>  	FUSE_I_CACHE_IO_MODE,
>  	/*
>  	 * Client has exclusive access to the inode, either because fs is local
> @@ -1192,7 +1192,7 @@ void fuse_file_free(struct fuse_file *ff);
>  int fuse_finish_open(struct inode *inode, struct file *file);
>  
>  void fuse_sync_release(struct fuse_inode *fi, struct fuse_file *ff,
> -		       unsigned int flags);
> +		       unsigned int flags, bool isdir);
>  
>  /**
>   * Send RELEASE or RELEASEDIR request
> @@ -1542,7 +1542,7 @@ int fuse_fileattr_set(struct mnt_idmap *idmap,
>  /* iomode.c */
>  int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff);
>  int fuse_inode_uncached_io_start(struct inode *inode, struct fuse_backing *fb);
> -void fuse_inode_uncached_io_end(struct fuse_inode *fi);
> +void fuse_inode_uncached_io_end(struct inode *inode);
>  
>  int fuse_file_io_open(struct file *file, struct inode *inode);
>  void fuse_file_io_release(struct fuse_file *ff, struct inode *inode);
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index 014b9af42909..bdc135f9fe3e 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -192,10 +192,10 @@ static void fuse_evict_inode(struct inode *inode)
>  			atomic64_inc(&fc->evict_ctr);
>  	}
>  	if (S_ISREG(inode->i_mode) && !fuse_is_bad(inode)) {
> -		WARN_ON(fi->iocachectr != 0);
>  		WARN_ON(!list_empty(&fi->write_files));
>  		WARN_ON(!list_empty(&fi->queued_writes));
>  	}
> +	WARN_ON(fi->iocachectr != 0);
>  }
>  
>  static int fuse_reconfigure(struct fs_context *fsc)
> diff --git a/fs/fuse/iomode.c b/fs/fuse/iomode.c
> index 6815b4506007..2360b32793c2 100644
> --- a/fs/fuse/iomode.c
> +++ b/fs/fuse/iomode.c
> @@ -15,9 +15,12 @@
>  /*
>   * Return true if need to wait for new opens in caching mode.
>   */
> -static inline bool fuse_is_io_cache_wait(struct fuse_inode *fi)
> +static inline bool fuse_is_io_cache_wait(struct inode *inode)
>  {
> -	return READ_ONCE(fi->iocachectr) < 0 && !fuse_inode_backing(fi);
> +	struct fuse_inode *fi = get_fuse_inode(inode);
> +
> +	return S_ISREG(inode->i_mode) &&
> +		READ_ONCE(fi->iocachectr) < 0 && !fuse_inode_backing(fi);
>  }
>  
>  /*
> @@ -40,10 +43,10 @@ int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff)
>  	 * Setting the bit advises new direct-io writes to use an exclusive
>  	 * lock - without it the wait below might be forever.
>  	 */
> -	while (fuse_is_io_cache_wait(fi)) {
> +	while (fuse_is_io_cache_wait(inode)) {
>  		set_bit(FUSE_I_CACHE_IO_MODE, &fi->state);
>  		spin_unlock(&fi->lock);
> -		wait_event(fi->direct_io_waitq, !fuse_is_io_cache_wait(fi));
> +		wait_event(fi->direct_io_waitq, !fuse_is_io_cache_wait(inode));
>  		spin_lock(&fi->lock);
>  	}
>  
> @@ -69,8 +72,10 @@ int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff)
>  }
>  
>  static void fuse_file_cached_io_release(struct fuse_file *ff,
> -					struct fuse_inode *fi)
> +					struct inode *inode)
>  {
> +	struct fuse_inode *fi = get_fuse_inode(inode);
> +
>  	spin_lock(&fi->lock);
>  	WARN_ON(fi->iocachectr <= 0);
>  	WARN_ON(ff->iomode != IOM_CACHED);
> @@ -141,15 +146,17 @@ static int fuse_file_uncached_io_open(struct inode *inode,
>  	return 0;
>  }
>  
> -void fuse_inode_uncached_io_end(struct fuse_inode *fi)
> +void fuse_inode_uncached_io_end(struct inode *inode)
>  {
> +	struct fuse_inode *fi = get_fuse_inode(inode);
>  	struct fuse_backing *oldfb = NULL;
>  
>  	spin_lock(&fi->lock);
>  	WARN_ON(fi->iocachectr >= 0);
>  	fi->iocachectr++;
>  	if (!fi->iocachectr) {
> -		wake_up(&fi->direct_io_waitq);
> +		if (S_ISREG(inode->i_mode))
> +			wake_up(&fi->direct_io_waitq);
>  		oldfb = fuse_inode_backing_set(fi, NULL);
>  	}
>  	spin_unlock(&fi->lock);
> @@ -159,11 +166,11 @@ void fuse_inode_uncached_io_end(struct fuse_inode *fi)
>  
>  /* Drop uncached_io reference from passthrough open */
>  static void fuse_file_uncached_io_release(struct fuse_file *ff,
> -					  struct fuse_inode *fi)
> +					  struct inode *inode)
>  {
>  	WARN_ON(ff->iomode != IOM_UNCACHED);
>  	ff->iomode = IOM_NONE;
> -	fuse_inode_uncached_io_end(fi);
> +	fuse_inode_uncached_io_end(inode);
>  }
>  
>  /*
> @@ -267,8 +274,6 @@ int fuse_file_io_open(struct file *file, struct inode *inode)
>  /* No more pending io and no new io possible to inode via open/mmapped file */
>  void fuse_file_io_release(struct fuse_file *ff, struct inode *inode)
>  {
> -	struct fuse_inode *fi = get_fuse_inode(inode);
> -
>  	/*
>  	 * Last passthrough file close allows caching inode io mode.
>  	 * Last caching file close exits caching inode io mode.
> @@ -278,10 +283,10 @@ void fuse_file_io_release(struct fuse_file *ff, struct inode *inode)
>  		/* Nothing to do */
>  		break;
>  	case IOM_UNCACHED:
> -		fuse_file_uncached_io_release(ff, fi);
> +		fuse_file_uncached_io_release(ff, inode);
>  		break;
>  	case IOM_CACHED:
> -		fuse_file_cached_io_release(ff, fi);
> +		fuse_file_cached_io_release(ff, inode);
>  		break;
>  	}
>  }
> -- 
> 2.52.0
> 
> 

  reply	other threads:[~2026-04-21 21:17 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 [this message]
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 ` [PATCH v1 07/17] fuse: prepare to setup backing inode passthrough on lookup Joanne Koong
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=20260421211732.GC7739@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=amir73il@gmail.com \
    --cc=fuse-devel@lists.linux.dev \
    --cc=joannelkoong@gmail.com \
    --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 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.