Subject: [PATCHES][RFC] the meat of tree-in-dcache series

From: Al Viro <[email-masked]>
Date: Sat, 20 Sep 2025 08:41:56 +0100

[my apologies for the size of patchbomb and the size of Cc; this series
really affects a lot of places, if lightly]

Some filesystems use a kinda-sorta controlled dentry refcount leak to pin
dentries of created objects in dcache (and undo it when removing those).
Reference is grabbed and not released, but it's not actually _stored_
anywhere.  That works, but it's hard to follow and verify; among other
things, we have no way to tell _which_ of the increments is intended
to be an unpaired one.  Worse, on removal we need to decide whether
the reference had already been dropped, which can be non-trivial if
that removal is on umount and we need to figure out if this dentry is
pinned due to e.g. unlink() not done.  Usually that is handled by using
kill_litter_super() as ->kill_sb(), but there are open-coded special
cases of the same (consider e.g. /proc/self).

Things get simpler if we introduce a new dentry flag (DCACHE_PERSISTENT)
marking those "leaked" dentries.  Having it set claims responsibility
for +1 in refcount.

The end result this series is aiming for:

* get these unbalanced dget() and dput() replaced with new primitives that
  would, in addition to adjusting refcount, set and clear persistency flag.
* instead of having kill_litter_super() mess with removing the remaining
  "leaked" references (e.g. for all tmpfs files that hadn't been removed
  prior to umount), have the regular shrink_dcache_for_umount() strip
  DCACHE_PERSISTENT of all dentries, dropping the corresponding
  reference if it had been set.  After that kill_litter_super() becomes
  an equivalent of kill_anon_super().

Doing that in a single step is not feasible - it would affect too many places
in too many filesystems.  It has to be split into a series.

This work has really started early in 2024; quite a few preliminary pieces
have already gone into mainline.  This chunk is finally getting to the
meat of that stuff - infrastructure and most of the conversions to it.

Some pieces are still sitting in the local branches, but the bulk of
that stuff is here.

The branch is -rc5-based; it lives in
git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git #work.persistency
individual patches in followups.

Please, help with review and testing; it does appear to survive the local beating,
but extra eyes on it would be very welcome.

First two commits add a couple of useful helpers, the next three add the
infrastructure and the rest consists of per-filesystem conversions.

Shortlog:
      new helper: simple_remove_by_name()
      new helper: simple_done_creating()
      introduce a flag for explicitly marking persistently pinned dentries
      primitives for maintaining persisitency
      convert simple_{link,unlink,rmdir,rename,fill_super}() to new primitives
      convert ramfs and tmpfs
      procfs: make /self and /thread_self dentries persistent
      configfs, securityfs: kill_litter_super() not needed
      convert xenfs
      convert smackfs
      convert hugetlbfs
      convert mqueue
      convert bpf
      convert dlmfs
      convert fuse_ctl
      convert pstore
      convert tracefs
      convert debugfs
      debugfs: remove duplicate checks in callers of start_creating()
      convert efivarfs
      convert spufs
      convert ibmasmfs
      ibmasmfs: get rid of ibmasmfs_dir_ops
      convert devpts
      binderfs: use simple_start_creating()
      binderfs_binder_ctl_create(): kill a bogus check
      convert binderfs
      autofs_{rmdir,unlink}: dentry->d_fsdata->dentry == dentry there
      convert autofs
      convert binfmt_misc
      convert selinuxfs
      functionfs: switch to simple_remove_by_name()
      convert functionfs
      gadgetfs: switch to simple_remove_by_name()
      convert gadgetfs
      hypfs: don't pin dentries twice
      hypfs: switch hypfs_create_str() to returning int
      hypfs: swich hypfs_create_u64() to returning int
      convert hypfs

Diffstat:
 arch/powerpc/platforms/cell/spufs/inode.c | 15 ++---
 arch/s390/hypfs/hypfs.h                   |  6 +-
 arch/s390/hypfs/hypfs_diag_fs.c           | 60 +++++++-------------
 arch/s390/hypfs/hypfs_vm_fs.c             | 21 +++----
 arch/s390/hypfs/inode.c                   | 82 +++++++++------------------
 drivers/android/binderfs.c                | 82 +++++++--------------------
 drivers/base/devtmpfs.c                   |  2 +-
 drivers/misc/ibmasm/ibmasmfs.c            | 24 ++++----
 drivers/usb/gadget/function/f_fs.c        | 54 ++++++++----------
 drivers/usb/gadget/legacy/inode.c         | 49 ++++++++--------
 drivers/xen/xenfs/super.c                 |  2 +-
 fs/autofs/inode.c                         |  2 +-
 fs/autofs/root.c                          | 11 ++--
 fs/binfmt_misc.c                          | 69 +++++++++++------------
 fs/configfs/mount.c                       |  2 +-
 fs/dcache.c                               | 93 ++++++++++++++++++++++++-------
 fs/debugfs/inode.c                        | 32 +++--------
 fs/devpts/inode.c                         | 57 +++++++------------
 fs/efivarfs/inode.c                       |  7 +--
 fs/efivarfs/super.c                       |  5 +-
 fs/fuse/control.c                         | 19 ++++---
 fs/hugetlbfs/inode.c                      | 12 ++--
 fs/libfs.c                                | 31 +++++++++--
 fs/ocfs2/dlmfs/dlmfs.c                    |  8 +--
 fs/proc/base.c                            |  6 +-
 fs/proc/internal.h                        |  1 +
 fs/proc/root.c                            | 14 ++---
 fs/proc/self.c                            | 10 +---
 fs/proc/thread_self.c                     | 11 +---
 fs/pstore/inode.c                         |  7 ++-
 fs/ramfs/inode.c                          |  8 +--
 fs/tracefs/event_inode.c                  |  4 +-
 fs/tracefs/inode.c                        | 13 ++---
 include/linux/dcache.h                    |  3 +
 include/linux/fs.h                        |  3 +
 include/linux/proc_fs.h                   |  2 -
 init/do_mounts.c                          |  2 +-
 ipc/mqueue.c                              | 12 +---
 kernel/bpf/inode.c                        | 15 ++---
 mm/shmem.c                                | 23 ++------
 security/inode.c                          |  2 +-
 security/selinux/selinuxfs.c              | 52 +++++++++--------
 security/smack/smackfs.c                  |  2 +-
 43 files changed, 412 insertions(+), 523 deletions(-)