From: NeilBrown <neil@xxxxxxxxxx> If the dentry is found to be negative (not d_in_lookup() and not positive) and if O_CREATE wasn't requested then we do not have exclusive access the dentry. If we pass it to ->atomic_open() the filesystem will need to ensure any lookup+open operations are serialised so that two threads don't both try to instantiate the dentry. This is an unnecessary burden to put on the filesystem. If the filesystem wants to perform such a lookup+open operation when a negative dentry is found, it should return 0 from ->d_revalidate in that case (when LOOKUP_OPEN) so that the calls serialise in d_alloc_parallel(). All filesystems with ->atomic_open() currently handle the case of a negative dentry without O_CREAT either by returning -ENOENT or by calling finish_no_open(), either with NULL or with the negative dentry. All of these have the same effect. For filesystems without ->atomic_open(), lookup_open() will, in this case, also call finish_no_open(). So this patch removes the burden from filesystems by calling finish_no_open() early on a negative cached dentry when O_CREAT isn't requested. With this change any ->atomic_open() function can be certain that it has exclusive access to the dentry, either because an exclusive lock is held on the parent directory or because DCACHE_PAR_LOOKUP is set implying an exclusive lock on the dentry itself. Signed-off-by: NeilBrown <neil@xxxxxxxxxx> --- Documentation/filesystems/vfs.rst | 4 ++++ fs/namei.c | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index 486a91633474..be7dd654f5fd 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -678,6 +678,10 @@ otherwise noted. flag should be set in file->f_mode. In case of O_EXCL the method must only succeed if the file didn't exist and hence FMODE_CREATED shall always be set on success. + atomic_open() will always have exclusive access to the dentry + as if O_CREAT hasn't caused the directory to be locked exclusively, + then the dentry will have DCACHE_PAR_LOOKUP will also + provides exclusivity. ``tmpfile`` called in the end of O_TMPFILE open(). Optional, equivalent to diff --git a/fs/namei.c b/fs/namei.c index ba8bf73d2f9c..5f732b9cd2db 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3647,6 +3647,14 @@ static struct dentry *lookup_open(struct nameidata *nd, struct file *file, /* Cached positive dentry: will open in f_op->open */ return dentry; } + if ((open_flag & O_CREAT) == 0 && !d_in_lookup(dentry)) { + /* Cached negative dentry and no create requested. + * If a filesystem wants to be called in this case + * it should trigger dentry invalidation in + * ->d_revalidate. + */ + return dentry; + } if (open_flag & O_CREAT) audit_inode(nd->name, dir, AUDIT_INODE_PARENT); -- 2.50.0.107.gf914562f5916.dirty