mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/7] multiple-filesystems: prepare for changes to VFS locking
@ 2026-09-29  3:36 NeilBrown
  2026-09-29  3:36 ` [PATCH 1/7] VFS/xfs/ntfs: drop parent lock across d_alloc_parallel() in d_add_ci() NeilBrown
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: NeilBrown @ 2026-09-29  3:36 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein, Kees Cook, Joel Granados,
	Richard Weinberger, Anton Ivanov, Johannes Berg, Breno Leitao,
	Andreas Hindborg, Jan Harkes, Hugh Dickins, Baolin Wang,
	Namjae Jeon, Hyunchul Lee, Carlos Maiolino, Alexander Viro,
	Christian Brauner
  Cc: Jeff Layton, Jan Kara, linux-fsdevel, fuse-devel, linux-kernel,
	linux-unionfs, linux-um, codalist, coda, linux-mm, ntfs,
	linux-xfs

I am working on changes to directory locking.  The medium term goal is
to lift d_alloc_parallel() locking above i_rwsem, so d_alloc_paralle()
can be run unlocked, and consequently cannot be called when ->i_rwsem is
held.

This patch set makes small changes to a number of filesystems which each
require just one patch.  Patch series for nfs, afs, cifs, fuse, cephfs
have been posted separately

The maint requirements are:
 1/ that d_alloc_parallel() not be called while i_rwsem is held.
    Places which currently do this can be changed to use d_alloc_trylock(),
    or d_duplicate(), or change to drop and retake the parent lock.


 2/ a dentry must not be d_drop()ed while an operation is ongoing, as an
    unlocked d_alloc_parallel() would then be able to create a new
    dentry with the same name.  d_splice_alias() can now work with a
    hash dentry, so often the d_drop() can simply be dropped.  Other
    tims it can be moved to after the operation has completed.

Though not strictly a requirement, the recent change to d_splice_alias()
means that there is nothing that d_add() which d_splice_alias() can do,
so it makes sense to deprecate d_add().  So d_add() calls have been changed
to d_splice_alias() in a few places.


The patches depend on patches recently added to the vfs tree.  I would
prefer these land in that tree too with an Acked-by or similar from
relevant maintainers.

Thanks,
NeilBrown


 [PATCH 1/7] VFS/xfs/ntfs: drop parent lock across d_alloc_parallel()
 [PATCH 2/7] shmem: use d_duplicate()
 [PATCH 3/7] coda: don't d_drop() early.
 [PATCH 4/7] configfs: remove d_add() calls before
 [PATCH 5/7] hostfs: don't d_drop() before d_splice_alias() in
 [PATCH 6/7] procfs: drop parent lock for d_alloc_parallel() in
 [PATCH 7/7] ovl: stop using lookup_one() in ovl_iterate().

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/7] VFS/xfs/ntfs: drop parent lock across d_alloc_parallel() in d_add_ci()
  2026-09-29  3:36 [PATCH 0/7] multiple-filesystems: prepare for changes to VFS locking NeilBrown
@ 2026-09-29  3:36 ` NeilBrown
  2026-09-29  3:36 ` [PATCH 2/7] shmem: use d_duplicate() NeilBrown
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: NeilBrown @ 2026-09-29  3:36 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein, Kees Cook, Joel Granados,
	Richard Weinberger, Anton Ivanov, Johannes Berg, Breno Leitao,
	Andreas Hindborg, Jan Harkes, Hugh Dickins, Baolin Wang,
	Namjae Jeon, Hyunchul Lee, Carlos Maiolino, Alexander Viro,
	Christian Brauner
  Cc: Jeff Layton, Jan Kara, linux-fsdevel, fuse-devel, linux-kernel,
	linux-unionfs, linux-um, codalist, coda, linux-mm, ntfs,
	linux-xfs

From: NeilBrown <neil@brown.name>

A proposed change will invert the lock ordering between
d_alloc_parallel() and inode_lock() on the parent.
When that happens it will not be safe to call d_alloc_parallel() while
holding the parent lock - even shared.

We don't need to keep the parent lock held when d_add_ci() is run - the
VFS doesn't need it as dentry is exclusively held due to
DCACHE_PAR_LOOKUP and the filesystem has finished its work.

So drop and reclaim the lock (shared or exclusive as determined by
LOOKUP_SHARED) to avoid future deadlock.

Signed-off-by: NeilBrown <neil@brown.name>
---
 Documentation/filesystems/porting.rst |  7 ++++++
 fs/dcache.c                           | 32 +++++++++++++++++++++++----
 fs/ntfs/namei.c                       |  2 +-
 fs/xfs/xfs_iops.c                     |  2 +-
 include/linux/dcache.h                |  3 ++-
 5 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 4e015f1bf1f8..f6a38bd9c68e 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1409,3 +1409,10 @@ use only if you have no alternative.
 The .create inode_operation no longer receives the 'excl' arg.  It must
 always assume the file does not already exist.  If the filesystem needs
 to be involved in non-exclusive create, it should provide atomic_open.
+
+---
+
+**mandatory**
+
+d_add_ci() must now be passed the flags arguemnt that was given to ->lookup
+
diff --git a/fs/dcache.c b/fs/dcache.c
index 83790c7a4dee..61e0896dc077 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2383,6 +2383,7 @@ EXPORT_SYMBOL(d_obtain_root);
  * @dentry: the negative dentry that was passed to the parent's lookup func
  * @inode:  the inode case-insensitive lookup has found
  * @name:   the case-exact name to be associated with the returned dentry
+ * @lookup_flags: flags passed to ->lookup
  *
  * This is to avoid filling the dcache with case-insensitive names to the
  * same inode, only the actual correct case is stored in the dcache for
@@ -2395,9 +2396,10 @@ EXPORT_SYMBOL(d_obtain_root);
  * the exact case, and return the spliced entry.
  */
 struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
-			struct qstr *name)
+			struct qstr *name, unsigned int lookup_flags)
 {
 	struct dentry *found, *res;
+	bool must_unlock = false;
 
 	/*
 	 * First check if a dentry matching the name already exists,
@@ -2409,24 +2411,46 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
 		return found;
 	}
 	if (d_in_lookup(dentry)) {
+		/*
+		 * We are holding parent lock and so don't want to wait
+		 * for a d_in_lookup() dentry.  We can safely drop the
+		 * parent lock and reclaim it as we have exclusive
+		 * access to dentry as it is d_in_lookup() (so
+		 * ->d_parent is stable) and we are near the end
+		 * ->lookup() and will shortly drop the lock anyway.
+		 * We cannot retake the lock while the new dentry is in-lookup
+		 */
+		if (lookup_flags & LOOKUP_SHARED)
+			inode_unlock_shared(d_inode(dentry->d_parent));
+		else
+			inode_unlock(d_inode(dentry->d_parent));
+		must_unlock = true;
 		found = d_alloc_parallel(dentry->d_parent, name);
 		if (IS_ERR(found) || !d_in_lookup(found)) {
 			iput(inode);
-			return found;
+			goto out_unlock;
 		}
 	} else {
 		found = d_alloc(dentry->d_parent, name);
 		if (!found) {
 			iput(inode);
 			return ERR_PTR(-ENOMEM);
-		} 
+		}
 	}
 	res = d_splice_alias(inode, found);
 	if (res) {
 		d_lookup_done(found);
 		dput(found);
-		return res;
+		found = res;
 	}
+	if (!must_unlock)
+		return found;
+out_unlock:
+	d_lookup_done(dentry);
+	if (lookup_flags & LOOKUP_SHARED)
+		inode_lock_shared(d_inode(dentry->d_parent));
+	else
+		inode_lock_nested(d_inode(dentry->d_parent), I_MUTEX_PARENT);
 	return found;
 }
 EXPORT_SYMBOL(d_add_ci);
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index 7091b2496fac..61cfa4e16586 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -309,7 +309,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
 		}
 		nls_name.hash = full_name_hash(dent, nls_name.name, nls_name.len);
 
-		dent = d_add_ci(dent, dent_inode, &nls_name);
+		dent = d_add_ci(dent, dent_inode, &nls_name, flags);
 		kfree(nls_name.name);
 		return dent;
 
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 4a3299abf774..fd480c0e4147 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -368,7 +368,7 @@ xfs_vn_ci_lookup(
 	/* else case-insensitive match... */
 	dname.name = ci_name.name;
 	dname.len = ci_name.len;
-	dentry = d_add_ci(dentry, VFS_I(ip), &dname);
+	dentry = d_add_ci(dentry, VFS_I(ip), &dname, flags);
 	kfree(ci_name.name);
 	return dentry;
 }
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index adf239f8205f..97d11f5e6a7b 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -267,7 +267,8 @@ struct dentry *d_duplicate(struct dentry *dentry);
 /* weird procfs mess; *NOT* exported */
 extern struct dentry * d_splice_alias_ops(struct inode *, struct dentry *,
 					  const struct dentry_operations *);
-extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
+extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *,
+				unsigned int);
 extern bool d_same_name(const struct dentry *dentry, const struct dentry *parent,
 			const struct qstr *name);
 extern struct dentry *d_find_any_alias(struct inode *inode);

base-commit: 3879f51857325da9bf3cfb073280257cd16ae067
-- 
2.50.0.107.gf914562f5916.dirty


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 2/7] shmem: use d_duplicate()
  2026-09-29  3:36 [PATCH 0/7] multiple-filesystems: prepare for changes to VFS locking NeilBrown
  2026-09-29  3:36 ` [PATCH 1/7] VFS/xfs/ntfs: drop parent lock across d_alloc_parallel() in d_add_ci() NeilBrown
@ 2026-09-29  3:36 ` NeilBrown
  2026-09-29  3:36 ` [PATCH 3/7] coda: don't d_drop() early NeilBrown
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: NeilBrown @ 2026-09-29  3:36 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein, Kees Cook, Joel Granados,
	Richard Weinberger, Anton Ivanov, Johannes Berg, Breno Leitao,
	Andreas Hindborg, Jan Harkes, Hugh Dickins, Baolin Wang,
	Namjae Jeon, Hyunchul Lee, Carlos Maiolino, Alexander Viro,
	Christian Brauner
  Cc: Jeff Layton, Jan Kara, linux-fsdevel, fuse-devel, linux-kernel,
	linux-unionfs, linux-um, codalist, coda, linux-mm, ntfs,
	linux-xfs

From: NeilBrown <neil@brown.name>

To prepare for d_alloc_parallel() being permitted without a directory
lock, use d_duplicate() when duplicating a dentry in order to create a
whiteout.

Signed-off-by: NeilBrown <neil@brown.name>
---
 mm/shmem.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index 897fa2b61346..8fbab956466c 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3976,11 +3976,12 @@ static int shmem_whiteout(struct mnt_idmap *idmap,
 	struct dentry *whiteout;
 	int error;
 
-	whiteout = d_alloc(old_dentry->d_parent, &old_dentry->d_name);
+	whiteout = d_duplicate(old_dentry);
 	if (!whiteout)
 		return -ENOMEM;
 	error = shmem_mknod(idmap, old_dir, whiteout,
 			    S_IFCHR | WHITEOUT_MODE, WHITEOUT_DEV);
+	d_lookup_done(whiteout);
 	dput(whiteout);
 	return error;
 }
-- 
2.50.0.107.gf914562f5916.dirty


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 3/7] coda: don't d_drop() early.
  2026-09-29  3:36 [PATCH 0/7] multiple-filesystems: prepare for changes to VFS locking NeilBrown
  2026-09-29  3:36 ` [PATCH 1/7] VFS/xfs/ntfs: drop parent lock across d_alloc_parallel() in d_add_ci() NeilBrown
  2026-09-29  3:36 ` [PATCH 2/7] shmem: use d_duplicate() NeilBrown
@ 2026-09-29  3:36 ` NeilBrown
  2026-09-29  3:36 ` [PATCH 4/7] configfs: remove d_add() calls before configfs_attach_group() NeilBrown
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: NeilBrown @ 2026-09-29  3:36 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein, Kees Cook, Joel Granados,
	Richard Weinberger, Anton Ivanov, Johannes Berg, Breno Leitao,
	Andreas Hindborg, Jan Harkes, Hugh Dickins, Baolin Wang,
	Namjae Jeon, Hyunchul Lee, Carlos Maiolino, Alexander Viro,
	Christian Brauner
  Cc: Jeff Layton, Jan Kara, linux-fsdevel, fuse-devel, linux-kernel,
	linux-unionfs, linux-um, codalist, coda, linux-mm, ntfs,
	linux-xfs

From: NeilBrown <neil@brown.name>

Proposed locking changes will mean that calling d_drop() could
effectively unlock the name allowing a parallel lookup to proceed.
For this reason it could only be called *after* the attempt to create a
symlink (in this case) has completed (whether successfully or not).

So move the d_drop() to after the venus_symlink() call.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/coda/dir.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 67148edfadee..bcbc9d058303 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -249,13 +249,13 @@ static int coda_symlink(struct mnt_idmap *idmap,
 	if (symlen > CODA_MAXPATHLEN)
 		return -ENAMETOOLONG;
 
+	error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len,
+			      symname, symlen);
 	/*
-	 * This entry is now negative. Since we do not create
+	 * This entry is still negative. Since we did not create
 	 * an inode for the entry we have to drop it.
 	 */
 	d_drop(de);
-	error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len,
-			      symname, symlen);
 
 	/* mtime is no good anymore */
 	if (!error)
-- 
2.50.0.107.gf914562f5916.dirty


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 4/7] configfs: remove d_add() calls before configfs_attach_group()
  2026-09-29  3:36 [PATCH 0/7] multiple-filesystems: prepare for changes to VFS locking NeilBrown
                   ` (2 preceding siblings ...)
  2026-09-29  3:36 ` [PATCH 3/7] coda: don't d_drop() early NeilBrown
@ 2026-09-29  3:36 ` NeilBrown
  2026-09-29  5:07   ` Al Viro
  2026-09-29  3:36 ` [PATCH 5/7] hostfs: don't d_drop() before d_splice_alias() in hostfs_mkdir() NeilBrown
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 11+ messages in thread
From: NeilBrown @ 2026-09-29  3:36 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein, Kees Cook, Joel Granados,
	Richard Weinberger, Anton Ivanov, Johannes Berg, Breno Leitao,
	Andreas Hindborg, Jan Harkes, Hugh Dickins, Baolin Wang,
	Namjae Jeon, Hyunchul Lee, Carlos Maiolino, Alexander Viro,
	Christian Brauner
  Cc: Jeff Layton, Jan Kara, linux-fsdevel, fuse-devel, linux-kernel,
	linux-unionfs, linux-um, codalist, coda, linux-mm, ntfs,
	linux-xfs

From: NeilBrown <neil@brown.name>

These d_add() calls cannot be necessary.  The inode given is NULL so all
they do is attach the dentry to the hash table.

If configfs_attach_group() fails, then d_drop() is called so the dentry
will be detached.
If configfs_attach_group() succeeds, then
 configfs_attach_group -> configfs_attach_item ->configfs_create_dir
must have succeeded, so d_instantiate() will have been called and the
dentry hashed there.

So the only effect is that the dentry will be hashed-negative for a
short period which will allow a lookup to find nothing without waiting
for the directory i_rwsem.  I can find no indication that this might be
important.

Adding a dentry as negative, and then later making it positive is an
unusual pattern and appears to be unnecessary, so it is best avoided.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/configfs/dir.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 3c88f13f1ca2..145a092171fe 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -715,8 +715,6 @@ static int create_default_group(struct dentry *parent,
 	ret = -ENOMEM;
 	child = d_alloc_name(parent, group->cg_item.ci_name);
 	if (child) {
-		d_add(child, NULL);
-
 		ret = configfs_attach_group(&group->cg_item, child, frag);
 		if (!ret) {
 			sd = child->d_fsdata;
@@ -1901,8 +1899,6 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
 	err = -ENOMEM;
 	dentry = d_alloc_name(root, group->cg_item.ci_name);
 	if (dentry) {
-		d_add(dentry, NULL);
-
 		err = configfs_dirent_exists(dentry);
 		if (!err)
 			err = configfs_attach_group(&group->cg_item,
-- 
2.50.0.107.gf914562f5916.dirty


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 5/7] hostfs: don't d_drop() before d_splice_alias() in hostfs_mkdir()
  2026-09-29  3:36 [PATCH 0/7] multiple-filesystems: prepare for changes to VFS locking NeilBrown
                   ` (3 preceding siblings ...)
  2026-09-29  3:36 ` [PATCH 4/7] configfs: remove d_add() calls before configfs_attach_group() NeilBrown
@ 2026-09-29  3:36 ` NeilBrown
  2026-09-29  3:36 ` [PATCH 6/7] procfs: drop parent lock for d_alloc_parallel() in iterate_shared() NeilBrown
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: NeilBrown @ 2026-09-29  3:36 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein, Kees Cook, Joel Granados,
	Richard Weinberger, Anton Ivanov, Johannes Berg, Breno Leitao,
	Andreas Hindborg, Jan Harkes, Hugh Dickins, Baolin Wang,
	Namjae Jeon, Hyunchul Lee, Carlos Maiolino, Alexander Viro,
	Christian Brauner
  Cc: Jeff Layton, Jan Kara, linux-fsdevel, fuse-devel, linux-kernel,
	linux-unionfs, linux-um, codalist, coda, linux-mm, ntfs,
	linux-xfs

From: NeilBrown <neil@brown.name>

hostfs_mkdir() uses d_drop() and d_splice_alias() to ensure it has the
right dentry after a mkdir.
d_drop() is no longer needed here and will cause problem for future
changes to directory locking.  So remove the d_drop().

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/hostfs/hostfs_kern.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 7add056d47d8..f68e75981436 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -700,7 +700,6 @@ static struct dentry *hostfs_mkdir(struct mnt_idmap *idmap, struct inode *ino,
 		dentry = ERR_PTR(err);
 	} else {
 		inode = hostfs_iget(dentry->d_sb, file);
-		d_drop(dentry);
 		dentry = d_splice_alias(inode, dentry);
 	}
 	__putname(file);
-- 
2.50.0.107.gf914562f5916.dirty


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 6/7] procfs: drop parent lock for d_alloc_parallel() in iterate_shared()
  2026-09-29  3:36 [PATCH 0/7] multiple-filesystems: prepare for changes to VFS locking NeilBrown
                   ` (4 preceding siblings ...)
  2026-09-29  3:36 ` [PATCH 5/7] hostfs: don't d_drop() before d_splice_alias() in hostfs_mkdir() NeilBrown
@ 2026-09-29  3:36 ` NeilBrown
  2026-09-29  3:36 ` [PATCH 7/7] ovl: stop using lookup_one() in ovl_iterate() NeilBrown
  2026-09-30 10:22 ` [syzbot ci] Re: multiple-filesystems: prepare for changes to VFS locking syzbot ci
  7 siblings, 0 replies; 11+ messages in thread
From: NeilBrown @ 2026-09-29  3:36 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein, Kees Cook, Joel Granados,
	Richard Weinberger, Anton Ivanov, Johannes Berg, Breno Leitao,
	Andreas Hindborg, Jan Harkes, Hugh Dickins, Baolin Wang,
	Namjae Jeon, Hyunchul Lee, Carlos Maiolino, Alexander Viro,
	Christian Brauner
  Cc: Jeff Layton, Jan Kara, linux-fsdevel, fuse-devel, linux-kernel,
	linux-unionfs, linux-um, codalist, coda, linux-mm, ntfs,
	linux-xfs

From: NeilBrown <neil@brown.name>

When procfs finds a name in iterate_shared() that isn't in the dcache it
*must* add it so that it can have a stable inode number to report
(inodes are only accessible from the dcache in procfs).

It uses d_alloc_parallel().  A planned change to locking will make it
unsafe to call d_alloc_parallel() while holding the directory lock.

Other filesystems which prime the dcache in iterate_shared() use
d_alloc_trylock() which is safe but can fail if it races with ->lookup.
As procfs cannot handle failure we need something better.

procfs doesn't *need* the parent to be locked.  There are no shared data
structures accessed that don't have their own locking.  So it is safe to
drop and re-take the parent lock.  We could do this around the whole
iteration, but as failure of d_alloc_trylock() is rare it is more
efficient to drop and retake it just around a call of d_alloc_parallel()
when d_alloc_trylock does fail.

Other code that drops and retakes the lock in iterate_shared needs to
be careful to check S_DEAD which could be set while the lock is
dropped.  This is not needed in procfs as the flag is never set.

As d_alloc_trylock() calls try_lookup_noperm(), we can skip that call
and simplify the code.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/proc/base.c        | 36 ++++++++++++++++++-------------
 fs/proc/proc_sysctl.c | 49 ++++++++++++++++++++++++-------------------
 2 files changed, 49 insertions(+), 36 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 6a39de424f62..49939527763d 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2106,24 +2106,32 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
 	unsigned type = DT_UNKNOWN;
 	ino_t ino = 1;
 
-	child = try_lookup_noperm(&qname, dir);
+	child = d_alloc_trylock(dir, &qname);
 	if (IS_ERR(child))
 		goto end_instantiate;
 
-	if (!child) {
+	if (child == ERR_PTR(-EWOULDBLOCK)) {
+		/*
+		 * Need to drop directory lock, which isn't really
+		 * needed here anyway.  As rmdir never happens in procfs
+		 * we don't need to be concerned about S_DEAD being set
+		 * while unlocked.
+		 */
+		inode_unlock_shared(dir->d_inode);
 		child = d_alloc_parallel(dir, &qname);
-		if (IS_ERR(child))
-			goto end_instantiate;
-		if (d_in_lookup(child)) {
-			struct dentry *res;
-			res = instantiate(child, task, ptr);
-			d_lookup_done(child);
-			if (unlikely(res)) {
-				dput(child);
-				child = res;
-				if (IS_ERR(child))
-					goto end_instantiate;
-			}
+		inode_lock_shared(dir->d_inode);
+	}
+	if (IS_ERR(child))
+		goto end_instantiate;
+	if (d_in_lookup(child)) {
+		struct dentry *res;
+		res = instantiate(child, task, ptr);
+		d_lookup_done(child);
+		if (unlikely(res)) {
+			dput(child);
+			child = res;
+			if (IS_ERR(child))
+				goto end_instantiate;
 		}
 	}
 	inode = d_inode(child);
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 04a382178c65..de96a08a1e64 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -686,29 +686,34 @@ static bool proc_sys_fill_cache(struct file *file,
 	ino_t ino = 0;
 	unsigned type = DT_UNKNOWN;
 
-	qname.name = table->procname;
-	qname.len  = strlen(table->procname);
-	qname.hash = full_name_hash(dir, qname.name, qname.len);
-
-	child = d_lookup(dir, &qname);
-	if (!child) {
+	qname = QSTR(table->procname);
+	child = d_alloc_trylock(dir, &qname);
+	if (child == ERR_PTR(-EWOULDBLOCK)) {
+		/*
+		 * Need to drop directory lock, which isn't really
+		 * needed here anyway.  As rmdir never happens in procfs
+		 * we don't need to be concerned about S_DEAD being set
+		 * while unlocked.
+		 */
+		inode_unlock_shared(dir->d_inode);
 		child = d_alloc_parallel(dir, &qname);
-		if (IS_ERR(child))
-			return false;
-		if (d_in_lookup(child)) {
-			struct dentry *res;
-			inode = proc_sys_make_inode(dir->d_sb, head, table);
-			res = d_splice_alias_ops(inode, child,
-						 &proc_sys_dentry_operations);
-			d_lookup_done(child);
-			if (unlikely(res)) {
-				dput(child);
-
-				if (IS_ERR(res))
-					return false;
-
-				child = res;
-			}
+		inode_lock_shared(dir->d_inode);
+	}
+	if (IS_ERR(child))
+		return false;
+	if (d_in_lookup(child)) {
+		struct dentry *res;
+		inode = proc_sys_make_inode(dir->d_sb, head, table);
+		res = d_splice_alias_ops(inode, child,
+					 &proc_sys_dentry_operations);
+		d_lookup_done(child);
+		if (unlikely(res)) {
+			dput(child);
+
+			if (IS_ERR(res))
+				return false;
+
+			child = res;
 		}
 	}
 	inode = d_inode(child);
-- 
2.50.0.107.gf914562f5916.dirty


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 7/7] ovl: stop using lookup_one() in ovl_iterate().
  2026-09-29  3:36 [PATCH 0/7] multiple-filesystems: prepare for changes to VFS locking NeilBrown
                   ` (5 preceding siblings ...)
  2026-09-29  3:36 ` [PATCH 6/7] procfs: drop parent lock for d_alloc_parallel() in iterate_shared() NeilBrown
@ 2026-09-29  3:36 ` NeilBrown
  2026-09-30 13:35   ` Amir Goldstein
  2026-09-30 10:22 ` [syzbot ci] Re: multiple-filesystems: prepare for changes to VFS locking syzbot ci
  7 siblings, 1 reply; 11+ messages in thread
From: NeilBrown @ 2026-09-29  3:36 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein, Kees Cook, Joel Granados,
	Richard Weinberger, Anton Ivanov, Johannes Berg, Breno Leitao,
	Andreas Hindborg, Jan Harkes, Hugh Dickins, Baolin Wang,
	Namjae Jeon, Hyunchul Lee, Carlos Maiolino, Alexander Viro,
	Christian Brauner
  Cc: Jeff Layton, Jan Kara, linux-fsdevel, fuse-devel, linux-kernel,
	linux-unionfs, linux-um, codalist, coda, linux-mm, ntfs,
	linux-xfs

From: NeilBrown <neil@brown.name>

lookup_one() is expected to be removed as it does not fit well with
proposed changes to directory locking.
Specifically d_alloc_parallel() will be ordered outside of i_rwsem
and as iterate_shared() is called with i_rwsem held it is not safe
to call d_alloc_parallel().

We can instead call d_alloc_trylock() and then call the ->lookup, but
that can fail if there is a lookup attempt concurrent with the
readdir().

ovl cannot afford for the lookup to fail as that could produce incorrect
results, and it cannot safely drop i_rwsem temporarily as that could
introduce races with handling of the directory cache.

Instead we rely on the fact that ovl_iterate() has an exclusive lock on
the directory, so any concurrent lookup will wait for the ovl_iterate()
call to complete.  We allocate a separate dentry and if the lookup is
successful, it is hashed with the result.

When the concurrent lookup gets i_rwsem it mustn't do its own lookup -
it must use the existing dentry.  This is found, if it exists, using
try_lookup_noperm().

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/overlayfs/namei.c   | 12 ++++++++++++
 fs/overlayfs/readdir.c | 26 ++++++++++++++++++++++++--
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index ca899fdfaafd..f56e33fd4d6b 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -1385,6 +1385,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
 	struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
 	struct ovl_entry *poe = OVL_E(dentry->d_parent);
 	bool check_redirect = (ovl_redirect_follow(ofs) || ofs->numdatalayer);
+	struct dentry *alias;
 	int err;
 	struct ovl_lookup_ctx ctx = {
 		.dentry = dentry,
@@ -1399,6 +1400,17 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
 	if (dentry->d_name.len > ofs->namelen)
 		return ERR_PTR(-ENAMETOOLONG);
 
+	/*
+	 * The existence of this in-lookup dentry might have forced
+	 * readdir to do the lookup with a new dentry.  If so we must
+	 * return that one.
+	 */
+	alias = try_lookup_noperm(&QSTR_LEN(dentry->d_name.name,
+					    dentry->d_name.len),
+				  dentry->d_parent);
+	if (alias && !IS_ERR(alias))
+		return alias;
+
 	with_ovl_creds(dentry->d_sb)
 		err = ovl_lookup_layers(&ctx, &d);
 
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index e7fe29cb6028..bc41da4bace8 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -574,8 +574,30 @@ static int ovl_cache_update(const struct path *path, struct ovl_cache_entry *p,
 		}
 	}
 	/* This checks also for xwhiteouts */
-	this = lookup_one(mnt_idmap(path->mnt), &QSTR_LEN(p->name, p->len), dir);
-	if (IS_ERR_OR_NULL(this) || !this->d_inode) {
+	this = d_alloc_trylock(dir, &QSTR_LEN(p->name, p->len));
+	if (this == ERR_PTR(-EWOULDBLOCK)) {
+		/*
+		 * Some other thread is looking up this name and will
+		 * block on i_rwsem before it can complete the lookup.
+		 * We will do the lookup in a new dentry and when that
+		 * lookup gets a turn it will find and return this
+		 * dentry.
+		 */
+		this = d_alloc_name(dir, p->name);
+		if (!this)
+			this = ERR_PTR(-ENOMEM);
+	}
+	if (!IS_ERR(this) && d_unhashed(this)) {
+		/* Either we got an in-lookup or we made our own unhashed */
+		struct dentry *alias = ovl_lookup(dir->d_inode, this, 0);
+
+		d_lookup_done(this);
+		if (alias) {
+			dput(this);
+			this = alias;
+		}
+	}
+	if (IS_ERR(this) || !this->d_inode) {
 		/* Mark a stale entry */
 		p->is_whiteout = true;
 		if (IS_ERR(this)) {
-- 
2.50.0.107.gf914562f5916.dirty


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/7] configfs: remove d_add() calls before configfs_attach_group()
  2026-09-29  3:36 ` [PATCH 4/7] configfs: remove d_add() calls before configfs_attach_group() NeilBrown
@ 2026-09-29  5:07   ` Al Viro
  0 siblings, 0 replies; 11+ messages in thread
From: Al Viro @ 2026-09-29  5:07 UTC (permalink / raw)
  To: NeilBrown
  Cc: Miklos Szeredi, Amir Goldstein, Kees Cook, Joel Granados,
	Richard Weinberger, Anton Ivanov, Johannes Berg, Breno Leitao,
	Andreas Hindborg, Jan Harkes, Hugh Dickins, Baolin Wang,
	Namjae Jeon, Hyunchul Lee, Carlos Maiolino, Christian Brauner,
	Jeff Layton, Jan Kara, linux-fsdevel, fuse-devel, linux-kernel,
	linux-unionfs, linux-um, codalist, coda, linux-mm, ntfs,
	linux-xfs

On Tue, Sep 29, 2026 at 01:36:04PM +1000, NeilBrown wrote:
> From: NeilBrown <neil@brown.name>
> 
> These d_add() calls cannot be necessary.  The inode given is NULL so all
> they do is attach the dentry to the hash table.
> 
> If configfs_attach_group() fails, then d_drop() is called so the dentry
> will be detached.
> If configfs_attach_group() succeeds, then
>  configfs_attach_group -> configfs_attach_item ->configfs_create_dir
> must have succeeded, so d_instantiate() will have been called and the
> dentry hashed there.

Neither in mainline, nor in -next...

d_add() _is_ wrong there, but this is not the right solution.  What
we really ought to do is build the subtree first, then either dissolve
it (without any pathname resolution having ever seen it) or move it
in place once we are sure that everything worked.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [syzbot ci] Re: multiple-filesystems: prepare for changes to VFS locking
  2026-09-29  3:36 [PATCH 0/7] multiple-filesystems: prepare for changes to VFS locking NeilBrown
                   ` (6 preceding siblings ...)
  2026-09-29  3:36 ` [PATCH 7/7] ovl: stop using lookup_one() in ovl_iterate() NeilBrown
@ 2026-09-30 10:22 ` syzbot ci
  7 siblings, 0 replies; 11+ messages in thread
From: syzbot ci @ 2026-09-30 10:22 UTC (permalink / raw)
  To: a.hindborg, amir73il, anton.ivanov, baolin.wang, brauner, cem,
	coda, codalist, fuse-devel, hughd, hyc.lee, jack, jaharkes,
	jlayton, joel.granados, johannes, kees, leitao, linkinjeon,
	linux-fsdevel, linux-kernel, linux-mm, linux-um, linux-unionfs,
	linux-xfs, miklos, neilb, ntfs, richard, viro
  Cc: syzbot, syzkaller-bugs

syzbot ci has tested the following series

[v1] multiple-filesystems: prepare for changes to VFS locking
https://lore.kernel.org/all/20260929034158.1455429-1-neilb@ownmail.net
* [PATCH 1/7] VFS/xfs/ntfs: drop parent lock across d_alloc_parallel() in d_add_ci()
* [PATCH 2/7] shmem: use d_duplicate()
* [PATCH 3/7] coda: don't d_drop() early.
* [PATCH 4/7] configfs: remove d_add() calls before configfs_attach_group()
* [PATCH 5/7] hostfs: don't d_drop() before d_splice_alias() in hostfs_mkdir()
* [PATCH 6/7] procfs: drop parent lock for d_alloc_parallel() in iterate_shared()
* [PATCH 7/7] ovl: stop using lookup_one() in ovl_iterate().

and found the following issue:
WARNING in __d_instantiate

Full report is available here:
https://ci.syzbot.org/series/b87296ff-c49f-416e-834c-a886ea8bd6c3

***

WARNING in __d_instantiate

tree:      linux-next
URL:       https://kernel.googlesource.com/pub/scm/linux/kernel/git/next/linux-next
base:      3879f51857325da9bf3cfb073280257cd16ae067
arch:      amd64
compiler:  Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
config:    https://ci.syzbot.org/builds/dd8fcfa5-13f0-458f-bd3b-9c06d4d67a78/config
syz repro: https://ci.syzbot.org/findings/fdffe42d-ac1a-40d9-b05c-014808f5b0ec/syz_repro

------------[ cut here ]------------
d_in_lookup(dentry)
WARNING: fs/dcache.c:2197 at __d_instantiate+0x3f4/0x700 fs/dcache.c:2197, CPU#1: syz.0.17/5823
Modules linked in:
CPU: 1 UID: 0 PID: 5823 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
RIP: 0010:__d_instantiate+0x3f4/0x700 fs/dcache.c:2197
Code: 03 41 80 f6 01 41 0f b6 ce c1 e1 0d 09 c1 89 0b 48 83 c4 10 5b 41 5c 41 5d 41 5e 41 5f 5d e9 03 26 96 09 cc e8 0d 84 75 ff 90 <0f> 0b 90 e9 7f fd ff ff e8 ff 83 75 ff 41 81 cc 00 00 01 00 e9 34
RSP: 0018:ffffc900038d73a0 EFLAGS: 00010293
RAX: ffffffff825242a3 RBX: ffff8881b4eef380 RCX: ffff888169801e00
RDX: 0000000000000000 RSI: 0000000001000000 RDI: 0000000000000000
RBP: 0000000001000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffff5200071ae6c R12: 0000000000280000
R13: dffffc0000000000 R14: ffff8881bc29f3e0 R15: ffff8881bc29f3e4
FS:  00007f15d1af96c0(0000) GS:ffff8882a8cc9000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000001000 CR3: 00000001bd5c4000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 d_make_persistent+0x8e/0x180 fs/dcache.c:3139
 shmem_mknod+0x2d4/0x340 mm/shmem.c:3851
 shmem_whiteout mm/shmem.c:3982 [inline]
 shmem_rename2+0x267/0x430 mm/shmem.c:4022
 vfs_rename+0xbd9/0xef0 fs/namei.c:6219
 ovl_do_rename_rd fs/overlayfs/overlayfs.h:371 [inline]
 ovl_check_rename_whiteout fs/overlayfs/super.c:593 [inline]
 ovl_make_workdir fs/overlayfs/super.c:713 [inline]
 ovl_get_workdir+0x93d/0x1980 fs/overlayfs/super.c:836
 ovl_fill_super_creds fs/overlayfs/super.c:1449 [inline]
 ovl_fill_super+0x1702/0x4360 fs/overlayfs/super.c:1561
 vfs_get_super fs/super.c:1405 [inline]
 get_tree_nodev+0xbb/0x150 fs/super.c:1424
 vfs_get_tree+0x92/0x2a0 fs/super.c:1947
 fc_mount fs/namespace.c:1198 [inline]
 do_new_mount_fc fs/namespace.c:3772 [inline]
 do_new_mount+0x319/0xdc0 fs/namespace.c:3848
 do_mount fs/namespace.c:4181 [inline]
 __do_sys_mount fs/namespace.c:4397 [inline]
 __se_sys_mount+0x31d/0x420 fs/namespace.c:4374
 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
 do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f15d0b9e159
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f15d1af9028 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007f15d0e25fa0 RCX: 00007f15d0b9e159
RDX: 0000200000000440 RSI: 0000200000000100 RDI: 0000000000000000
RBP: 00007f15d0c3506b R08: 0000200000000080 R09: 0000000000000000
R10: 0000000000000008 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f15d0e26038 R14: 00007f15d0e25fa0 R15: 00007ffe9e1b3308
 </TASK>


***

If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
  Tested-by: syzbot@syzkaller.appspotmail.com

---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.

To test a fix for this bug, please reply with `#syz test`
(on a separate line) and attach the patch to the email.

Notes:
- The patch will be applied on top of the tested series (as an
  incremental fix).
- To test a new version of the whole series, please send it directly
  to syzbot@lists.linux.dev.
- Arguments like custom git repos and branches are not supported.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 7/7] ovl: stop using lookup_one() in ovl_iterate().
  2026-09-29  3:36 ` [PATCH 7/7] ovl: stop using lookup_one() in ovl_iterate() NeilBrown
@ 2026-09-30 13:35   ` Amir Goldstein
  0 siblings, 0 replies; 11+ messages in thread
From: Amir Goldstein @ 2026-09-30 13:35 UTC (permalink / raw)
  To: NeilBrown
  Cc: Miklos Szeredi, Kees Cook, Joel Granados, Richard Weinberger,
	Anton Ivanov, Johannes Berg, Breno Leitao, Andreas Hindborg,
	Jan Harkes, Hugh Dickins, Baolin Wang, Namjae Jeon, Hyunchul Lee,
	Carlos Maiolino, Alexander Viro, Christian Brauner, Jeff Layton,
	Jan Kara, linux-fsdevel, fuse-devel, linux-kernel, linux-unionfs,
	linux-um, codalist, coda, linux-mm, ntfs, linux-xfs

On Tue, Sep 29, 2026 at 5:43 AM NeilBrown <neilb@ownmail.net> wrote:
>
> From: NeilBrown <neil@brown.name>
>
> lookup_one() is expected to be removed as it does not fit well with
> proposed changes to directory locking.
> Specifically d_alloc_parallel() will be ordered outside of i_rwsem
> and as iterate_shared() is called with i_rwsem held it is not safe
> to call d_alloc_parallel().
>
> We can instead call d_alloc_trylock() and then call the ->lookup, but
> that can fail if there is a lookup attempt concurrent with the
> readdir().
>
> ovl cannot afford for the lookup to fail as that could produce incorrect
> results, and it cannot safely drop i_rwsem temporarily as that could
> introduce races with handling of the directory cache.
>
> Instead we rely on the fact that ovl_iterate() has an exclusive lock on
> the directory, so any concurrent lookup will wait for the ovl_iterate()
> call to complete.  We allocate a separate dentry and if the lookup is
> successful, it is hashed with the result.

Please document this assumption with:

rwsem_assert_held_write(&dir->d_inode->i_rwsem);

and comment in the code. Having it in the git commit message is not
enough for future code reviewers.

Other than that, I have no further comments, but I would like
to have a review from Miklos before this patch lands, because
I don't remember him reviewing any of the revisions and this is subtle.
I am a bit concerned that we have no test coverage for this subtle code.

>
> When the concurrent lookup gets i_rwsem it mustn't do its own lookup -
> it must use the existing dentry.  This is found, if it exists, using
> try_lookup_noperm().
>
> Signed-off-by: NeilBrown <neil@brown.name>
> ---
>  fs/overlayfs/namei.c   | 12 ++++++++++++
>  fs/overlayfs/readdir.c | 26 ++++++++++++++++++++++++--
>  2 files changed, 36 insertions(+), 2 deletions(-)
>
> diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
> index ca899fdfaafd..f56e33fd4d6b 100644
> --- a/fs/overlayfs/namei.c
> +++ b/fs/overlayfs/namei.c
> @@ -1385,6 +1385,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
>         struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
>         struct ovl_entry *poe = OVL_E(dentry->d_parent);
>         bool check_redirect = (ovl_redirect_follow(ofs) || ofs->numdatalayer);
> +       struct dentry *alias;
>         int err;
>         struct ovl_lookup_ctx ctx = {
>                 .dentry = dentry,
> @@ -1399,6 +1400,17 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
>         if (dentry->d_name.len > ofs->namelen)
>                 return ERR_PTR(-ENAMETOOLONG);
>
> +       /*
> +        * The existence of this in-lookup dentry might have forced
> +        * readdir to do the lookup with a new dentry.  If so we must
> +        * return that one.
> +        */
> +       alias = try_lookup_noperm(&QSTR_LEN(dentry->d_name.name,
> +                                           dentry->d_name.len),
> +                                 dentry->d_parent);
> +       if (alias && !IS_ERR(alias))
> +               return alias;
> +
>         with_ovl_creds(dentry->d_sb)
>                 err = ovl_lookup_layers(&ctx, &d);
>
> diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
> index e7fe29cb6028..bc41da4bace8 100644
> --- a/fs/overlayfs/readdir.c
> +++ b/fs/overlayfs/readdir.c
> @@ -574,8 +574,30 @@ static int ovl_cache_update(const struct path *path, struct ovl_cache_entry *p,
>                 }
>         }
>         /* This checks also for xwhiteouts */
> -       this = lookup_one(mnt_idmap(path->mnt), &QSTR_LEN(p->name, p->len), dir);
> -       if (IS_ERR_OR_NULL(this) || !this->d_inode) {
> +       this = d_alloc_trylock(dir, &QSTR_LEN(p->name, p->len));
> +       if (this == ERR_PTR(-EWOULDBLOCK)) {
> +               /*
> +                * Some other thread is looking up this name and will
> +                * block on i_rwsem before it can complete the lookup.
> +                * We will do the lookup in a new dentry and when that
> +                * lookup gets a turn it will find and return this
> +                * dentry.
> +                */
> +               this = d_alloc_name(dir, p->name);
> +               if (!this)
> +                       this = ERR_PTR(-ENOMEM);
> +       }
> +       if (!IS_ERR(this) && d_unhashed(this)) {
> +               /* Either we got an in-lookup or we made our own unhashed */
> +               struct dentry *alias = ovl_lookup(dir->d_inode, this, 0);
> +
> +               d_lookup_done(this);
> +               if (alias) {
> +                       dput(this);
> +                       this = alias;
> +               }
> +       }
> +       if (IS_ERR(this) || !this->d_inode) {
>                 /* Mark a stale entry */
>                 p->is_whiteout = true;
>                 if (IS_ERR(this)) {

How do you test your patch set? Do you have tests that exercise
parallel create/lookup/readdir?

It would be irresponsible to merge code without showing that the `alias`
branches have been exercised. Do you have an idea how to do that?

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-09-30 13:36 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-29  3:36 [PATCH 0/7] multiple-filesystems: prepare for changes to VFS locking NeilBrown
2026-09-29  3:36 ` [PATCH 1/7] VFS/xfs/ntfs: drop parent lock across d_alloc_parallel() in d_add_ci() NeilBrown
2026-09-29  3:36 ` [PATCH 2/7] shmem: use d_duplicate() NeilBrown
2026-09-29  3:36 ` [PATCH 3/7] coda: don't d_drop() early NeilBrown
2026-09-29  3:36 ` [PATCH 4/7] configfs: remove d_add() calls before configfs_attach_group() NeilBrown
2026-09-29  5:07   ` Al Viro
2026-09-29  3:36 ` [PATCH 5/7] hostfs: don't d_drop() before d_splice_alias() in hostfs_mkdir() NeilBrown
2026-09-29  3:36 ` [PATCH 6/7] procfs: drop parent lock for d_alloc_parallel() in iterate_shared() NeilBrown
2026-09-29  3:36 ` [PATCH 7/7] ovl: stop using lookup_one() in ovl_iterate() NeilBrown
2026-09-30 13:35   ` Amir Goldstein
2026-09-30 10:22 ` [syzbot ci] Re: multiple-filesystems: prepare for changes to VFS locking syzbot ci

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®