[PATCH RFC/RFT v1 00/12] Fix easy bits of the negative dentry problem

NeilBrown <[email protected]> Mon, 3 Aug 2026 11:21:09 +1000
Newsgroups org.kernel.vger.ceph-devel,org.kernel.vger.autofs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-nfs
Message-ID <[email protected]>
Hi all,

 I was reading about the negative dentry problem in
 https://lwn.net/Articles/1079407/ and thought I would have ago at the
 easy bits.  Given how involved some of that was I'm glad I didn't try
 the tricky bits!

 So I didn't try to reduce the number of negative dentries or handle
 them differently to positive dentries.  I just tried to address
 specific symptoms.

 This series addresses two reported symptoms.
  1/ refcounts on parents can potentially overflow if there are billions
     of (negative) children.  This was the easiest easy bit.  The first
     patch is all that is needed.

  2/ Walking the ->d_children list can take arbitrarily long and can
     trigger soft lockups.  I haven't addresses the "arbitrarily long"
     part, but the "soft lockups" only takes another 11 patches.
     With these in place I would feel more confident addressing
     the "arbitrarily long" part.

 The core idea is to use a common helper for all walking of
 ->d_children, and teach it to drop the lock and schedule when needed,
 inserting a cursor to keep its place.
 This simple idea requires:
   - nothing should be holding any other lock while walking ->d_children
   - dentries shouldn't be moved around needlessly, else things might
     get missed.
   - quite a bit of refactoring in libfs for readdir code.

 so I have probably missed some bits and would be very happy to be told
 what I have missed.
 I would also be very happy if someone who can trigger the soft lockups
 can try this code and confirm that the locks are gone, and nothing bad
 happens.
 I have done some basic testing including the "notify" parts of
 ltp, but that is all.

 I haven't addressed d_walk() in this series - I thought it was big
 enough for now.  Most of d_walk() already schedules as needed, but I
 think there is still room for improvement, but that can come later.

Details worth checking in various modules:

NFS: patch 02 drops the parent lock between calling
        nfs_unset_verifier_delegated()
     on the parent and calling it on all the children.  I don't
     think this is significant.

autofs:  patch 09 removes the ->lookup_lock from
             get_next_positive_subdir() 
         and
             get_next_positive_dentry()
         I cannot see that this is serving any purpose

cephfs:  nothing interesting
coda:  patch 02 dropped the rcu_read_lock() because the spinlock() implies it.

libfs: the offset_dir code has been changed (08) quite a bit but should
      have identical behaviour.  It now uses scan_positives() (which has
      been substantially refactored (05, 06, 07, 12)) in place of
      find_positive_dentry()

fsnotify: a few changes (03 04) to move the ->d_children walk out from under
     various spinlocks.  This is the change I'm least confident of
     as it is non-trivial code that I'm not familiar with.

dcache: patch 11 uses an on-stack dentry as a dcache cursor.  This is
     not something that other code does so I would appreciate it if
     someone checked my logic.

dcache: patch 10 changed d_move to *not* move dentries in the
     ->d_children list when they are both in the same parent.
     This brings no value and could cause some instability in
     a d_children walk.

Thanks for any review or testing that you have time for.

NeilBrown

This series is against v7.2-rc6 and can be found at the 
   vfs-neg-dentries
branch of
   https://github.com/neilbrown/linux
where top commit is
   56768a600dd9145fea601649dbc74031aa25e459

 [PATCH v1 01/12] VFS: don't count references through ->d_parent
 [PATCH v1 02/12] Add and use d_for_each_positive_child family of
 [PATCH v1 03/12] fsnotify: don't hold a spin_lock across
 [PATCH v1 04/12] fsnotify: reduce i_lock hold time in
 [PATCH v1 05/12] libfs: simplify scan_positives()
 [PATCH v1 06/12] libfs: change scan_positives() to use
 [PATCH v1 07/12] libfs: allow scan_positives() to be called without a
 [PATCH v1 08/12] libfs: replace find_positive_dentry() with
 [PATCH v1 09/12] autofs: don't hold ->lookup_lock in
 [PATCH v1 10/12] VFS: don't move dentries in d_sib list when they
 [PATCH v1 11/12] Call cond_reshed() as needed in
 [PATCH v1 12/12] libfs: remove cond_resched() from scan_positives()