]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
make cursors NORCU
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 5 May 2026 04:20:19 +0000 (00:20 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 5 Jun 2026 04:34:56 +0000 (00:34 -0400)
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>
fs/dcache.c

index e7487c92c21a64c019de7b53ec600e5b38b13b18..1f50100bce49ed0bb6cff05038532e0054fe6e4e 100644 (file)
@@ -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;