summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2026-05-05 00:20:19 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2026-06-05 00:34:56 -0400
commit3df5153c5f123d6018c82a24341ccd99c79d64a0 (patch)
tree3ebbf62a6f550305edc3d3e4aad33887d590db04
parent144bef84e1cfadfe100c6728593ea9838853f347 (diff)
downloadlinux-stable-3df5153c5f123d6018c82a24341ccd99c79d64a0.tar.gz
linux-stable-3df5153c5f123d6018c82a24341ccd99c79d64a0.zip
make cursors NORCU
All it requires is making sure that d_walk() will skip *all* CURSOR dentries, even if somebody passes it one as an argument. Cursors are negative and unhashed all along, never get added to LRU or to shrink lists and no RCU references via ->d_sib are possible for those - dentry_unlist() makes sure that no killed dentry has ->d_sib.next left pointing to a cursor. Seeing that a cursor is allocated every time we open a directory on autofs, debugfs, devpts, etc., avoiding an RCU delay when such opened files get closed is attractive... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/dcache.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index e7487c92c21a..1f50100bce49 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1443,6 +1443,8 @@ again:
read_seqbegin_or_lock(&rename_lock, &seq);
this_parent = parent;
spin_lock(&this_parent->d_lock);
+ if (unlikely(this_parent->d_flags & DCACHE_DENTRY_CURSOR))
+ goto out_unlock;
ret = enter(data, this_parent);
switch (ret) {
@@ -1996,7 +1998,7 @@ struct dentry *d_alloc_cursor(struct dentry * parent)
{
struct dentry *dentry = d_alloc_anon(parent->d_sb);
if (dentry) {
- dentry->d_flags |= DCACHE_DENTRY_CURSOR;
+ dentry->d_flags |= DCACHE_DENTRY_CURSOR | DCACHE_NORCU;
dentry->d_parent = dget(parent);
}
return dentry;