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