[PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set

Jim Harris posted 1 patch 1 month, 1 week ago
fs/fuse/dir.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
[PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Jim Harris 1 month, 1 week ago
From: Jim Harris <jim.harris@nvidia.com>

When O_CREAT is set, we don't need the lookup. The lookup doesn't
harm anything, but it's an extra FUSE operation that's not required.

Signed-off-by: Jim Harris <jim.harris@nvidia.com>
---
 fs/fuse/dir.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index f25ee47822ad..35f65d49ed2a 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -895,7 +895,8 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir,
 		goto out_err;
 	}
 	kfree(forget);
-	d_instantiate(entry, inode);
+	d_drop(entry);
+	d_splice_alias(inode, entry);
 	entry->d_time = epoch;
 	fuse_change_entry_timeout(entry, &outentry);
 	fuse_dir_changed(dir);
@@ -936,14 +937,15 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
 	if (fuse_is_bad(dir))
 		return -EIO;
 
-	if (d_in_lookup(entry)) {
-		struct dentry *res = fuse_lookup(dir, entry, 0);
-		if (res || d_really_is_positive(entry))
-			return finish_no_open(file, res);
-	}
+	if (!(flags & O_CREAT)) {
+		if (d_in_lookup(entry)) {
+			struct dentry *res = fuse_lookup(dir, entry, 0);
 
-	if (!(flags & O_CREAT))
+			if (res || d_really_is_positive(entry))
+				return finish_no_open(file, res);
+		}
 		return finish_no_open(file, NULL);
+	}
 
 	/* Only creates */
 	file->f_mode |= FMODE_CREATED;
-- 
2.43.0
Re: [PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Bernd Schubert 1 month, 1 week ago
On 2/20/26 21:41, Jim Harris wrote:
> From: Jim Harris <jim.harris@nvidia.com>
> 
> When O_CREAT is set, we don't need the lookup. The lookup doesn't
> harm anything, but it's an extra FUSE operation that's not required.

Problem is that it is a change of behavior - it might cause issues for
some fuse server implementations that expect that a node-id was obtained
before open of an existing file is done.


Thanks,
Bernd
Re: [PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Miklos Szeredi 1 month, 1 week ago
On Fri, 20 Feb 2026 at 21:41, Jim Harris <jim.harris@nvidia.com> wrote:
>
> From: Jim Harris <jim.harris@nvidia.com>
>
> When O_CREAT is set, we don't need the lookup. The lookup doesn't
> harm anything, but it's an extra FUSE operation that's not required.
>
> Signed-off-by: Jim Harris <jim.harris@nvidia.com>
> ---
>  fs/fuse/dir.c | 16 +++++++++-------
>  1 file changed, 9 insertions(+), 7 deletions(-)
>
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index f25ee47822ad..35f65d49ed2a 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -895,7 +895,8 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir,
>                 goto out_err;
>         }
>         kfree(forget);
> -       d_instantiate(entry, inode);
> +       d_drop(entry);
> +       d_splice_alias(inode, entry);
>         entry->d_time = epoch;
>         fuse_change_entry_timeout(entry, &outentry);
>         fuse_dir_changed(dir);
> @@ -936,14 +937,15 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
>         if (fuse_is_bad(dir))
>                 return -EIO;
>
> -       if (d_in_lookup(entry)) {
> -               struct dentry *res = fuse_lookup(dir, entry, 0);
> -               if (res || d_really_is_positive(entry))
> -                       return finish_no_open(file, res);
> -       }
> +       if (!(flags & O_CREAT)) {
> +               if (d_in_lookup(entry)) {
> +                       struct dentry *res = fuse_lookup(dir, entry, 0);
>
> -       if (!(flags & O_CREAT))
> +                       if (res || d_really_is_positive(entry))
> +                               return finish_no_open(file, res);
> +               }
>                 return finish_no_open(file, NULL);
> +       }
>
>         /* Only creates */
>         file->f_mode |= FMODE_CREATED;

Now this is not necessarily true.  Setting FMODE_CREATED in case of an
existing file will have the effect of not checking permissions to open
(think open(path, O_CREAT | O_RDWR, 0444)).

Sad fact is that the same thing could happen with current code: a file
created on a remote client during the window between LOOKUP and
CREATE.

To prevent that with the current protocol we'd need to add O_EXCL and
retry on -EEXIST.

Better fix would be to add a flag to the CREATE reply indicating if
the file was created or not.

Thanks,
Miklos
Re: [PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Horst Birthelmer 1 month, 1 week ago
Hi Jim,

On Fri, Feb 20, 2026 at 01:41:02PM -0700, Jim Harris wrote:
> From: Jim Harris <jim.harris@nvidia.com>
> 
> When O_CREAT is set, we don't need the lookup. The lookup doesn't
> harm anything, but it's an extra FUSE operation that's not required.
> 
> Signed-off-by: Jim Harris <jim.harris@nvidia.com>
> ---
>  fs/fuse/dir.c | 16 +++++++++-------
>  1 file changed, 9 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index f25ee47822ad..35f65d49ed2a 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -895,7 +895,8 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir,
>  		goto out_err;
>  	}
>  	kfree(forget);
> -	d_instantiate(entry, inode);
> +	d_drop(entry);
> +	d_splice_alias(inode, entry);
>  	entry->d_time = epoch;
>  	fuse_change_entry_timeout(entry, &outentry);
>  	fuse_dir_changed(dir);
> @@ -936,14 +937,15 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
>  	if (fuse_is_bad(dir))
>  		return -EIO;
>  
> -	if (d_in_lookup(entry)) {
> -		struct dentry *res = fuse_lookup(dir, entry, 0);
> -		if (res || d_really_is_positive(entry))
> -			return finish_no_open(file, res);
> -	}
> +	if (!(flags & O_CREAT)) {
> +		if (d_in_lookup(entry)) {
> +			struct dentry *res = fuse_lookup(dir, entry, 0);
>  
> -	if (!(flags & O_CREAT))
> +			if (res || d_really_is_positive(entry))
> +				return finish_no_open(file, res);
> +		}
>  		return finish_no_open(file, NULL);
> +	}
>  
>  	/* Only creates */
>  	file->f_mode |= FMODE_CREATED;
> -- 
> 2.43.0
> 
> 

I have been looking at that code lately a lot since I was planning to
replace it with a compound.
I'm not entirely convinced that your proposal is the right direction. 
I would involve O_EXCL as well, since that lookup could actually 
help in that case.

Take a look at what Miklos wrote here:
https://lore.kernel.org/linux-fsdevel/CAJfpegsDxsMsyfP4a_5H1q91xFtwcEdu9-WBnzWKwjUSrPNdmw@mail.gmail.com/

Cheers,
Horst
Re: [PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Miklos Szeredi 1 month, 1 week ago
On Sat, 21 Feb 2026 at 16:19, Horst Birthelmer <horst@birthelmer.de> wrote:

> I have been looking at that code lately a lot since I was planning to
> replace it with a compound.
> I'm not entirely convinced that your proposal is the right direction.
> I would involve O_EXCL as well, since that lookup could actually
> help in that case.
>
> Take a look at what Miklos wrote here:
> https://lore.kernel.org/linux-fsdevel/CAJfpegsDxsMsyfP4a_5H1q91xFtwcEdu9-WBnzWKwjUSrPNdmw@mail.gmail.com/

Bernd had actual patches, that got sidetracked unfortunately:

https://lore.kernel.org/all/20231023183035.11035-1-bschubert@ddn.com/

Thanks,
Miklos
Re: [PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Bernd Schubert 1 month, 1 week ago

On 2/23/26 16:09, Miklos Szeredi wrote:
> On Sat, 21 Feb 2026 at 16:19, Horst Birthelmer <horst@birthelmer.de> wrote:
> 
>> I have been looking at that code lately a lot since I was planning to
>> replace it with a compound.
>> I'm not entirely convinced that your proposal is the right direction.
>> I would involve O_EXCL as well, since that lookup could actually
>> help in that case.
>>
>> Take a look at what Miklos wrote here:
>> https://lore.kernel.org/linux-fsdevel/CAJfpegsDxsMsyfP4a_5H1q91xFtwcEdu9-WBnzWKwjUSrPNdmw@mail.gmail.com/
> 
> Bernd had actual patches, that got sidetracked unfortunately:
> 
> https://lore.kernel.org/all/20231023183035.11035-1-bschubert@ddn.com/


After the discussion about LOOKUO_HANDLE my impression was actually that
we want to use compounds for the atomic open.


Thanks,
Bernd
Re: [PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Miklos Szeredi 1 month, 1 week ago
On Mon, 23 Feb 2026 at 16:37, Bernd Schubert <bernd@bsbernd.com> wrote:

> After the discussion about LOOKUO_HANDLE my impression was actually that
> we want to use compounds for the atomic open.

I think we want to introduce an atomic operation that does a lookup +
an optional mknod, lets call this LOOKUP_CREATE_FH, this would return
a flag indicating whether the file was created or if it existed prior
to the operation.

Then, instead of the current CREATE operation there would be a
compound with LOOKUP_CREATE_FH + OPEN.

Does that make sense?

Thanks,
Miklos
Re: Re: [PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Horst Birthelmer 1 month, 1 week ago
On Mon, Feb 23, 2026 at 04:53:33PM +0100, Miklos Szeredi wrote:
> On Mon, 23 Feb 2026 at 16:37, Bernd Schubert <bernd@bsbernd.com> wrote:
> 
> > After the discussion about LOOKUO_HANDLE my impression was actually that
> > we want to use compounds for the atomic open.
> 
> I think we want to introduce an atomic operation that does a lookup +
> an optional mknod, lets call this LOOKUP_CREATE_FH, this would return
> a flag indicating whether the file was created or if it existed prior
> to the operation.
> 
> Then, instead of the current CREATE operation there would be a
> compound with LOOKUP_CREATE_FH + OPEN.
> 
> Does that make sense?

What is wrong with a compound doing LOOKUP + MKNOD + OPEN?
If the fuse server knows how to process that 'group' atomically
in one big step it will do the right thing, 
if not, we will call those in series and sort out the data 
in kernel afterwards.

If we preserve all flags and the real results we can do pretty
much exactly the same thing that is done at the moment with just
one call to user space.

That was actually what I was experimenting with.

The MKNOD in the middle is optional depending on the O_CREAT flag.

> 
> Thanks,
> Miklos

Cheers,
Horst
Re: Re: [PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Miklos Szeredi 1 month, 1 week ago
On Mon, 23 Feb 2026 at 19:55, Horst Birthelmer <horst@birthelmer.de> wrote:

> What is wrong with a compound doing LOOKUP + MKNOD + OPEN?
> If the fuse server knows how to process that 'group' atomically
> in one big step it will do the right thing,
> if not, we will call those in series and sort out the data
> in kernel afterwards.
>
> If we preserve all flags and the real results we can do pretty
> much exactly the same thing that is done at the moment with just
> one call to user space.
>
> That was actually what I was experimenting with.
>
> The MKNOD in the middle is optional depending on the O_CREAT flag.

Okay, I won't stop you experimenting.

My thinking is that it's simpler as a separate op (dir handle and name
are the same for LOOKUP and MKNOD).   But adding this special "stop if
error or non-regular, else skip create if positive" dependency would
also work.

Thanks,
Miklos
Re: [PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Bernd Schubert 1 month, 1 week ago

On 2/23/26 16:53, Miklos Szeredi wrote:
> On Mon, 23 Feb 2026 at 16:37, Bernd Schubert <bernd@bsbernd.com> wrote:
> 
>> After the discussion about LOOKUO_HANDLE my impression was actually that
>> we want to use compounds for the atomic open.
> 
> I think we want to introduce an atomic operation that does a lookup +
> an optional mknod, lets call this LOOKUP_CREATE_FH, this would return
> a flag indicating whether the file was created or if it existed prior
> to the operation.
> 
> Then, instead of the current CREATE operation there would be a
> compound with LOOKUP_CREATE_FH + OPEN.
> 
> Does that make sense?

Fine with me, but I need to process a bit if we want to that lookup to
return attributes or if it should be LOOKUP_CREATE_FH + OPEN + GETATTR.
Currently in the wrong time zone to do that today and also not much time
in general this week.


Thanks,
Bernd
Re: [PATCH] fuse: skip lookup during atomic_open() when O_CREAT is set
Posted by Luis Henriques 1 month, 1 week ago
On Mon, Feb 23 2026, Miklos Szeredi wrote:

> On Mon, 23 Feb 2026 at 16:37, Bernd Schubert <bernd@bsbernd.com> wrote:
>
>> After the discussion about LOOKUO_HANDLE my impression was actually that
>> we want to use compounds for the atomic open.
>
> I think we want to introduce an atomic operation that does a lookup +
> an optional mknod, lets call this LOOKUP_CREATE_FH, this would return
> a flag indicating whether the file was created or if it existed prior
> to the operation.
>
> Then, instead of the current CREATE operation there would be a
> compound with LOOKUP_CREATE_FH + OPEN.
>
> Does that make sense?

FWIW, what I've been doing is something slightly different.  I have been
working on implementing MKOBJ_HANDLE+STATX+OPEN.  And the plan was to rely
on the compound flags, leaving it to user-space to handle the atomicity
(e.g. MKOBJ_HANDLE would fail if O_EXCL was set).

I was hoping to share a draft of this very soon, though it's still
incomplete.  For example, not all required compound operations are already
implemented, most notably readdirplus!

Cheers,
-- 
Luís