Re: [PATCH 04/18] VFS: add vfs_lookup_open()

Jori Koolstra <jkoolstra-qWit8jRvyhVmR6Xm/[email protected]>
Newsgroups gmane.linux.nfs,gmane.linux.file-systems
Message-ID <[email protected]>
> Op 01-06-2026 08:37 CEST schreef NeilBrown <[email protected]>:
> 
>  
> From: NeilBrown <neil-+NVA1uvv1dVBDLzU/[email protected]>
> 
> vfs_lookup_open() is a limited version of lookup_open() which is
> exported for nfsd to use - to replace dentry_create().
> 
> It is limited in that no filename is given (thus no auditing) and no
> LOOKUP_ flags are passed.  A few "intent" LOOKUP flags are deduced from
> the open flags.
> 
> Signed-off-by: NeilBrown <neil-+NVA1uvv1dVBDLzU/[email protected]>
> ---
>  fs/namei.c            | 54 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/namei.h |  3 +++
>  2 files changed, 57 insertions(+)
> 
> diff --git a/fs/namei.c b/fs/namei.c
> index 18a43c24d7f1..db3fddbccd21 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -4571,6 +4571,60 @@ static struct dentry *lookup_open(const struct path *path, struct file *file,
>  	goto out;
>  }
>  
> +/**
> + * vfs_lookup_open - open and possibly create a regular file
> + * @parent: directory to contain file
> + * @last: final component of file name
> + * @open_flag: O_flags
> + * @mode: initial permissions for file
> + *
> + * Open a file after lookup and/or create.  This provides similar
> + * functionality open_last_lookups() for in-kernel users, particularly
> + * nfsd.
> + * It uses ->atomic_open or ->lookup / ->create / ->open as appropriate.
> + *
> + * Returns: the opened struct file, or an error.
> + */
> +struct file *vfs_lookup_open(struct path *parent, struct qstr *last,
> +			     int open_flag, umode_t mode)
> +{
> +	struct file *file __free(fput) = NULL;
> +	unsigned int lookup_flags = LOOKUP_OPEN;
> +	struct dentry *dentry;
> +	int error = 0;
> +
> +	error = lookup_noperm_common(last, parent->dentry);
> +	if (error)
> +		return ERR_PTR(error);
> +
> +	file = alloc_empty_file(open_flag, current_cred());
> +	if (IS_ERR(file))
> +		return file;
> +
> +	if (open_flag & O_CREAT) {
> +		lookup_flags |= LOOKUP_CREATE;
> +		if (open_flag & O_EXCL)
> +			lookup_flags |= LOOKUP_EXCL;

Is O_EXCL enforced anywhere in this call path? I don't really know nfsd, but
for the standard O_CREAT call chain, this happens in do_open(), and EEXIST is
returned.

Also, maybe warn when nonsensical bits here, like __O_TMPFILE, are set in
open_flag?

> +	}
> +	dentry = lookup_open(parent, file, last, lookup_flags, NULL,
> +			     open_flag, S_IFREG | mode);
> +	if (IS_ERR(dentry))
> +		return ERR_CAST(dentry);
> +
> +	if (d_really_is_negative(dentry)) {
> +		error = -ENOENT;
> +	} else if (!(file->f_mode & FMODE_OPENED)) {
> +		struct path path = {.mnt = parent->mnt, .dentry = dentry };
> +
> +		error = vfs_open(&path, file);

Ah, good, this fixes the bug in dentry_create() where on failing the open
part of atomic_open() no other attempt was done by the vfs to do the open.

> +	}
> +	dput(dentry);
> +
> +	if (error)
> +		return ERR_PTR(error);
> +	return no_free_ptr(file);
> +}
> +
>  static inline bool trailing_slashes(struct nameidata *nd)
>  {
>  	return (bool)nd->last.name[nd->last.len];
> diff --git a/include/linux/namei.h b/include/linux/namei.h
> index 2ad6dd9987b9..8c048c97a7f7 100644
> --- a/include/linux/namei.h
> +++ b/include/linux/namei.h
> @@ -103,6 +103,9 @@ struct dentry *start_creating_dentry(struct dentry *parent,
>  struct dentry *start_removing_dentry(struct dentry *parent,
>  				     struct dentry *child);
>  
> +struct file *vfs_lookup_open(struct path *parent, struct qstr *last,
> +			     int open_flag, umode_t mode);
> +
>  /* end_creating - finish action started with start_creating
>   * @child: dentry returned by start_creating() or vfs_mkdir()
>   *
> -- 
> 2.50.0.107.gf914562f5916.dirty
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.