Re: [PATCH v3] kernfs: allocate inodes and dentry outside kernfs_rwsem
From: Greg Kroah-Hartman
Date: Sat Oct 17 2026 - 05:14:37 EST
On Fri, Oct 16, 2026 at 12:42:29PM -1000, Tejun Heo wrote:
> On Fri, Oct 16, 2026 at 03:00:29PM -0700, Shakeel Butt wrote:
> > In the Meta fleet, on 6.16 with the kernfs changes queued for 7.4
> > backported, we still see long cgroupfs stalls:
> >
> > - oomd and below waited 72 seconds in kernfs_fop_readdir() while an out
> > of memory container created cgroups. They resumed when the kernel OOM
> > killer killed the container's workload.
> >
> > - oomd waited 15 minutes in kernfs_iop_lookup(). PID 1 waited for
> > kernfs_rwsem in cgroup_rmdir() while holding cgroup_mutex.
> >
> > - A lock profiler sampling part of the fleet saw kernfs_iop_lookup()
> > hold kernfs_rwsem across memcg reclaim on 26 hosts in 29 days, for up
> > to 625 ms.
> >
> > The profiler shows where these stalls come from. kernfs_iop_lookup()
> > and the export ops allocate a new inode while holding kernfs_rwsem for
> > read. The inode is charged to the caller's memcg. If that memcg is at
> > memory.max, the allocation can stay in reclaim for a long time,
> > sometimes until an OOM kill. A writer then queues on the lock and every
> > new reader queues behind it. On cgroup2 this blocks every cgroupfs user
> > on the machine.
> >
> > Such lookups are common in a memcg that is out of memory. Its reclaim
> > drops its kernfs dentries fast, and the files of a new cgroup have no
> > inodes yet.
> >
> > Allocate the inode before taking kernfs_rwsem, and free it if it is not
> > used, as commit 8b64f32fee95 ("kernfs: allocate the new name outside
> > kernfs_rwsem") and commit 5ad03af18434 ("kernfs: allocate the open node
> > outside the open file mutex") do. Everything else still runs under the
> > lock, so a new inode is added only for an active node, and
> > __kernfs_remove() still finds every inode it must clear i_nlink on, as
> > commit dc1a0cc95737 ("kernfs: don't lose IN_DELETE_SELF when decoding a
> > file handle") needs.
> >
> > The inode goes unused when the name does not exist, the node is
> > inactive, or it already has an inode. In a VM, a lookup of a missing
> > name takes about 0.35 us longer, 1.65 us instead of 1.3 us on
> > cgroupfs. Cold lookups of existing sysfs and cgroupfs files are not
> > slower.
> >
> > kernfs_get_parent_dentry() also held the lock across d_obtain_alias(),
> > which allocates a dentry. Hold it only around the inode lookup, as
> > __kernfs_fh_to_dentry() already does. This also gives ->get_parent the
> > active test that the IN_DELETE_SELF fix left out: a parent that is
> > being removed and has no inode now gets -ESTALE instead of a new inode
> > with i_nlink 1.
> >
> > kernfs_fill_super() preallocates the root inode the same way, so no
> > inode is allocated under kernfs_rwsem any more.
> >
> > Tested on a 316-CPU machine. A task in a full 256 MB memcg with slow
> > swap looks up the files of new cgroups. Worst waits in 60 seconds:
> >
> > before after
> > oomd, for kernfs_rwsem 236 ms 0.1 ms
> > below, for kernfs_rwsem 356 ms 0.8 ms
> > systemd, for kernfs_rwsem 160 ms 37 us
> > readdir of another directory 530 ms 3.9 ms
> >
> > The lookup itself is still slow. The VFS still holds its directory's
> > lock, so other work in that one directory still waits.
> >
> > Signed-off-by: Shakeel Butt <shakeel.butt@xxxxxxxxx>
> > Suggested-by: Tejun Heo <tj@xxxxxxxxxx>
>
> Acked-by: Tejun Heo <tj@xxxxxxxxxx>
This looks sane, but it's really late in the cycle, can we wait until
after -rc1 to add it to the tree for lots of testing in -next?
thanks,
greg k-h