
Of the many VFS changes to be merged for Linux 7.4 is now closing files synchrously for close_range, exec, and exit calls. In turn when needing to close many file descriptors this provides for much lower latency than the status quo.
Stemming from varying proposals for making Linux exit files before generating coredumps, Christian Brauner has been working on closing file descriptors synchronously before generating coredumps. In the end files are closed synchronously for close_range, exec, and exit calls.
Brauner explained in the VFS pull request:
"This makes closing files synchronous for close_range(), exec and exit. It is based on the vfs-7.4-rc1.close_range tag and contains it.Since fput() was switched to task work every final __fput() of an exiting task is queued on task work and run from exit_task_work(). exec and close_range() do the same. For a task with a large descriptor table that is a cmpxchg() and a TIF_NOTIFY_RESUME test-and-set per file plus a list entry for any later task_work_cancel() to search under pi_lock, and then a second pass over every struct file that isn't cache hot anymore by then. Oleg and Neil have pointed this out over the years.
close_files(), close_range() and close-on-exec now flush and put each file inline the way close(2) does. Kernel threads aren't affected."
On a 64 vCPU KVM guest running on an AMD EPYC server with varying numbers of file descriptors (FDs) scatered at random positions in the FD table, these patches yield a very significant reduction in time spent closing them:
Brauner added in the pull request:
"So that is 16-21% or 40-150 ns per closed file, largest at 1M descriptors. With eight processes tearing down 65536 descriptors each at once it stays at 16-21% because the second pass over 16 MB of struct file is what gets expensive when CPUs compete for the cache. With 32 or 64 processes both kernels are bound by pushing millions of files through slab and rcu and the difference shrinks to 4-8%. Files whose own release dominates gain less, 13% for eventfds, 11% for pipes, 6% for AF_UNIX sockets. close(2) is untouched and will-it-scale is within 2%."
One of many nice improvements now part of the in-development Linux 7.4 kernel. Linux 7.4 stable should be out around the end of December.