Merge tag 'vfs-7.1-rc1.directory' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs directory updates from Christian Brauner:
 "Recently 'start_creating', 'start_removing', 'start_renaming' and
  related interfaces were added which combine the locking and the
  lookup.

  At that time many callers were changed to use the new interfaces.
  However there are still an assortment of places out side of the core
  vfs where the directory is locked explictly, whether with inode_lock()
  or lock_rename() or similar. These were missed in the first pass for
  an assortment of uninteresting reasons.

  This addresses the remaining places where explicit locking is used,
  and changes them to use the new interfaces, or otherwise removes the
  explicit locking.

  The biggest changes are in overlayfs. The other changes are quite
  simple, though maybe the cachefiles changes is the least simple of
  those"

* tag 'vfs-7.1-rc1.directory' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  VFS: unexport lock_rename(), lock_rename_child(), unlock_rename()
  ovl: remove ovl_lock_rename_workdir()
  ovl: use is_subdir() for testing if one thing is a subdir of another
  ovl: change ovl_create_real() to get a new lock when re-opening created file.
  ovl: pass name buffer to ovl_start_creating_temp()
  cachefiles: change cachefiles_bury_object to use start_renaming_dentry()
  ovl: Simplify ovl_lookup_real_one()
  VFS: make lookup_one_qstr_excl() static.
  nfsd: switch purge_old() to use start_removing_noperm()
  selinux: Use simple_start_creating() / simple_done_creating()
  Apparmor: Use simple_start_creating() / simple_done_creating()
  libfs: change simple_done_creating() to use end_creating()
  VFS: move the start_dirop() kerndoc comment to before start_dirop()
  fs/proc: Don't lock root inode when creating "self" and "thread-self"
  VFS: note error returns in documentation for various lookup functions
This commit is contained in:
Linus Torvalds
2026-04-13 10:24:33 -07:00
15 changed files with 190 additions and 244 deletions

View File

@@ -1782,8 +1782,8 @@ static struct dentry *lookup_dcache(const struct qstr *name,
* Will return -ENOENT if name isn't found and LOOKUP_CREATE wasn't passed.
* Will return -EEXIST if name is found and LOOKUP_EXCL was passed.
*/
struct dentry *lookup_one_qstr_excl(const struct qstr *name,
struct dentry *base, unsigned int flags)
static struct dentry *lookup_one_qstr_excl(const struct qstr *name,
struct dentry *base, unsigned int flags)
{
struct dentry *dentry;
struct dentry *old;
@@ -1820,7 +1820,6 @@ found:
}
return dentry;
}
EXPORT_SYMBOL(lookup_one_qstr_excl);
/**
* lookup_fast - do fast lockless (but racy) lookup of a dentry
@@ -2899,20 +2898,6 @@ static int filename_parentat(int dfd, struct filename *name,
return __filename_parentat(dfd, name, flags, parent, last, type, NULL);
}
/**
* __start_dirop - begin a create or remove dirop, performing locking and lookup
* @parent: the dentry of the parent in which the operation will occur
* @name: a qstr holding the name within that parent
* @lookup_flags: intent and other lookup flags.
* @state: task state bitmask
*
* The lookup is performed and necessary locks are taken so that, on success,
* the returned dentry can be operated on safely.
* The qstr must already have the hash value calculated.
*
* Returns: a locked dentry, or an error.
*
*/
static struct dentry *__start_dirop(struct dentry *parent, struct qstr *name,
unsigned int lookup_flags,
unsigned int state)
@@ -2934,6 +2919,19 @@ static struct dentry *__start_dirop(struct dentry *parent, struct qstr *name,
return dentry;
}
/**
* start_dirop - begin a create or remove dirop, performing locking and lookup
* @parent: the dentry of the parent in which the operation will occur
* @name: a qstr holding the name within that parent
* @lookup_flags: intent and other lookup flags.
*
* The lookup is performed and necessary locks are taken so that, on success,
* the returned dentry can be operated on safely.
* The qstr must already have the hash value calculated.
*
* Returns: a locked dentry, or an error.
*
*/
struct dentry *start_dirop(struct dentry *parent, struct qstr *name,
unsigned int lookup_flags)
{
@@ -3130,7 +3128,8 @@ static int lookup_one_common(struct mnt_idmap *idmap,
* @base: base directory to lookup from
*
* Look up a dentry by name in the dcache, returning NULL if it does not
* currently exist. The function does not try to create a dentry and if one
* currently exist or an error if there is a problem with the name.
* The function does not try to create a dentry and if one
* is found it doesn't try to revalidate it.
*
* Note that this routine is purely a helper for filesystem usage and should
@@ -3138,6 +3137,11 @@ static int lookup_one_common(struct mnt_idmap *idmap,
*
* No locks need be held - only a counted reference to @base is needed.
*
* Returns:
* - ref-counted dentry on success, or
* - %NULL if name could not be found, or
* - ERR_PTR(-EACCES) if name is dot or dotdot or contains a slash or nul, or
* - ERR_PTR() if fs provide ->d_hash, and this returned an error.
*/
struct dentry *try_lookup_noperm(struct qstr *name, struct dentry *base)
{
@@ -3214,6 +3218,11 @@ EXPORT_SYMBOL(lookup_one);
*
* Unlike lookup_one, it should be called without the parent
* i_rwsem held, and will take the i_rwsem itself if necessary.
*
* Returns: - A dentry, possibly negative, or
* - same errors as try_lookup_noperm() or
* - ERR_PTR(-ENOENT) if parent has been removed, or
* - ERR_PTR(-EACCES) if parent directory is not searchable.
*/
struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap, struct qstr *name,
struct dentry *base)
@@ -3250,6 +3259,10 @@ EXPORT_SYMBOL(lookup_one_unlocked);
* It should be called without the parent i_rwsem held, and will take
* the i_rwsem itself if necessary. If a fatal signal is pending or
* delivered, it will return %-EINTR if the lock is needed.
*
* Returns: A dentry, possibly negative, or
* - same errors as lookup_one_unlocked() or
* - ERR_PTR(-EINTR) if a fatal signal is pending.
*/
struct dentry *lookup_one_positive_killable(struct mnt_idmap *idmap,
struct qstr *name,
@@ -3289,6 +3302,10 @@ EXPORT_SYMBOL(lookup_one_positive_killable);
* This can be used for in-kernel filesystem clients such as file servers.
*
* The helper should be called without i_rwsem held.
*
* Returns: A positive dentry, or
* - ERR_PTR(-ENOENT) if the name could not be found, or
* - same errors as lookup_one_unlocked().
*/
struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap,
struct qstr *name,
@@ -3317,6 +3334,10 @@ EXPORT_SYMBOL(lookup_one_positive_unlocked);
*
* Unlike try_lookup_noperm() it *does* revalidate the dentry if it already
* existed.
*
* Returns: A dentry, possibly negative, or
* - ERR_PTR(-ENOENT) if parent has been removed, or
* - same errors as try_lookup_noperm()
*/
struct dentry *lookup_noperm_unlocked(struct qstr *name, struct dentry *base)
{
@@ -3341,6 +3362,10 @@ EXPORT_SYMBOL(lookup_noperm_unlocked);
* _can_ become positive at any time, so callers of lookup_noperm_unlocked()
* need to be very careful; pinned positives have ->d_inode stable, so
* this one avoids such problems.
*
* Returns: A positive dentry, or
* - ERR_PTR(-ENOENT) if name cannot be found or parent has been removed, or
* - same errors as try_lookup_noperm()
*/
struct dentry *lookup_noperm_positive_unlocked(struct qstr *name,
struct dentry *base)
@@ -3756,7 +3781,7 @@ static struct dentry *lock_two_directories(struct dentry *p1, struct dentry *p2)
/*
* p1 and p2 should be directories on the same fs.
*/
struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
static struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
{
if (p1 == p2) {
inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
@@ -3766,12 +3791,11 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
mutex_lock(&p1->d_sb->s_vfs_rename_mutex);
return lock_two_directories(p1, p2);
}
EXPORT_SYMBOL(lock_rename);
/*
* c1 and p2 should be on the same fs.
*/
struct dentry *lock_rename_child(struct dentry *c1, struct dentry *p2)
static struct dentry *lock_rename_child(struct dentry *c1, struct dentry *p2)
{
if (READ_ONCE(c1->d_parent) == p2) {
/*
@@ -3808,9 +3832,8 @@ struct dentry *lock_rename_child(struct dentry *c1, struct dentry *p2)
mutex_unlock(&c1->d_sb->s_vfs_rename_mutex);
return NULL;
}
EXPORT_SYMBOL(lock_rename_child);
void unlock_rename(struct dentry *p1, struct dentry *p2)
static void unlock_rename(struct dentry *p1, struct dentry *p2)
{
inode_unlock(p1->d_inode);
if (p1 != p2) {
@@ -3818,7 +3841,6 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
mutex_unlock(&p1->d_sb->s_vfs_rename_mutex);
}
}
EXPORT_SYMBOL(unlock_rename);
/**
* __start_renaming - lookup and lock names for rename