On Mon, Oct 23, 2023 at 08:30:32PM +0200, Bernd Schubert wrote: > + if (!switched && !d_in_lookup(entry)) { > + d_drop(entry); > + new = d_alloc_parallel(entry->d_parent, &entry->d_name, > + wq); > + if (IS_ERR(new)) > + return new; > + > + if (unlikely(!d_in_lookup(new))) { > + dput(new); > + new = ERR_PTR(-EIO); > + return new; Again, huh? You call d_drop(). Then another thread tries to look the same thing up and gets there while d_alloc_parallel() is allocating a new dentry. d_alloc_parallel() sees that dentry is already in hash (if lookup has managed to complete) or in in-lookup hash (if lookup is in progress). In the former case it returns the dentry it had found (and frees the one it intended to put in); in the latter it waits for lookup to complete and checks if dentry is hashed, has the same name and the same parent. If it is, same as if we'd found it hashed in the first place - we return an additional reference to it. It's perfectly valid and I really don't understand what are you trying to achieve here.