diff options
| author | NeilBrown <neil@brown.name> | 2026-09-05 07:48:11 +1000 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-09-25 16:27:19 +0200 |
| commit | f1ac607f786f5216d40ffbbc557d0cf87e21bfd9 (patch) | |
| tree | 1c8ee1e9de57e531d4c4f505c3c7275846be09a3 /include | |
| parent | f8550827bf3df4c74040d5245d019908eceba4f7 (diff) | |
| download | linux-next-f1ac607f786f5216d40ffbbc557d0cf87e21bfd9.tar.gz linux-next-f1ac607f786f5216d40ffbbc557d0cf87e21bfd9.zip | |
VFS: enhance d_splice_alias() to handle hashed dentries
We currently have three interfaces for attaching existing inodes to
normal filesystems(*).
- d_add() requires an unhashed or in-lookup dentry and doesn't handle
splicing in case a directory already has dentry
- d_instantiate() requires a hashed dentry, and also doesn't handle
splicing.
- d_splice_alias() requires unhashed or in-lookup and does handle
splicing, and can return an alternate dentry.
So there is no interface that supports both hashed and in-lookup, which
is what ->atomic_open needs to deal with.
Some filesystems check for in-lookup in their atomic_open and if found,
perform a ->lookup and can subsequently use d_instantiate() if the
dentry is still negative. Others d_drop() the dentry so they can use
d_splice_alias().
This last will cause a problem for proposed changes to locking which
require the dentry to remain hashed while an operation proceeds on it.
There is also no interface which splices a directory (which might
already have a dentry) to a hashed dentry. Filesystems which need to do
this d_drop() first.
Some filesystems (NFS) skip ->lookup processing for
LOOKUP_CREATE|LOOKUP_EXCL
which includes mknod, link, symlink etc. So these inode operations
might get an unhashed or a hashed-negative dentry. There is no
interface for instantiating these so again they need to unhash
first (nfs_link)
So with this patch d_splice_alias() can handle hashed, unhashed, or
in-lookup dentries. This makes it suitable for ->lookup, ->atomic_open,
and ->mkdir as well as others.
As a side effect d_add() will also now handle hashed dentries, but
I have plans to remove d_add() as there is no benefit having it as
well as the others.
Once updated to handle nr_dentry_negative as is required for hashed
dentrties, __d_add() contains code that is identical to
__d_instantiate(), so the former is changed to call the later so now:
- d_add() calls __d_add() which hashes and might call __d_instantiate.
- d_instantiate() calls __d_instantiate() with appropriate locks.
It was suggested by Al Viro
https://lore.kernel.org/all/20250813050717.GD222315@ZenIV/
that rather than allow d_splice_alias() to handle both hashed and
unhashed, we should have a new d_splice_alias_hashed().
I chose not to follow this path because, as noted above, there
are several cases where the filesystem has no a priori knowledge
of the state of the dentry, and so would need
if (d_unhashed(dentry))
alias = d_splice_alias(inode, dentry);
else
alias = d_splice_alias_hashed(inode, dentry);
which is clumsy.
Also I hope to minimise the distinction between hashed and in-lookup
(they will both be hashed, just with different DCACHE_ENTRY_TYPE)
and reduce the use of unhashed dentries.
Unhashed dentries would only be created by d_alloc_name() and all
of those are passed to d_make_persistent() (though configfs passes
some to d_add(dentry, NULL) first!). So the use-case for
d_splice_alias() on unhashed dentries would disappear.
Note that d_make_persistent() already handles both hashed and
unhashed dentries - just not in-lookup.
* There is also d_make_persistent() for filesystems which are
dcache-based and don't support mkdir, create etc, and
d_instantiate_new() for newly created inodes that are still locked.
Signed-off-by: NeilBrown <neil@brown.name>
Link: https://patch.msgid.link/20260904215142.1060510-3-neilb@ownmail.net
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'include')
0 files changed, 0 insertions, 0 deletions
