]> git.ipfire.org Git - thirdparty/kernel/linux.git/commit
ovl: change ovl_create_real() to get a new lock when re-opening created file.
authorNeilBrown <neil@brown.name>
Tue, 24 Feb 2026 22:16:57 +0000 (09:16 +1100)
committerChristian Brauner <brauner@kernel.org>
Mon, 9 Mar 2026 08:43:03 +0000 (09:43 +0100)
commit8348278650bca7a51c274bdf898aa9a73ce4b67f
tree703c07c9213ddbd1d3e382b71a99d2a1cb521315
parent85bb1420a850099fd44e8ba212d4e56575b45322
ovl: change ovl_create_real() to get a new lock when re-opening created file.

When ovl_create_real() is used to create a file on the upper filesystem
it needs to return the resulting dentry - positive and hashed.
It is usually the case the that dentry passed to the create function
(e.g.  vfs_create()) will be suitable but this is not guaranteed.  The
filesystem may unhash that dentry forcing a repeat lookup next time the
name is wanted.

So ovl_create_real() must be (and is) aware of this and prepared to
perform that lookup to get a hash positive dentry.

This is currently done under that same directory lock that provided
exclusion for the create.  Proposed changes to locking will make this
not possible - as the name, rather than the directory, will be locked.
The new APIs provided for lookup and locking do not and cannot support
this pattern.

The lock isn't needed.  ovl_create_real() can drop the lock and then get
a new lock for the lookup - then check that the lookup returned the
correct inode.  In a well-behaved configuration where the upper
filesystem is not being modified by a third party, this will always work
reliably, and if there are separate modification it will fail cleanly.

So change ovl_create_real() to drop the lock and call
ovl_start_creating_upper() to find the correct dentry.  Note that
start_creating doesn't fail if the name already exists.

The lookup previously used the name from newdentry which was guaranteed
to be stable because the parent directory was locked.  As we now drop
the lock we lose that guarantee.  As newdentry is unhashed it is
unlikely for the name to change, but safest not to depend on that.  So
the expected name is now passed in to ovl_create_real() and that is
used.

This removes the only remaining use of ovl_lookup_upper, so it is
removed.

Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: NeilBrown <neil@brown.name>
Link: https://patch.msgid.link/20260224222542.3458677-13-neilb@ownmail.net
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/overlayfs/dir.c
fs/overlayfs/overlayfs.h
fs/overlayfs/super.c