linux/fs/proc
Suren Baghdasaryan 5631da56c9 fs/proc/task_mmu: read proc/pid/maps under per-vma lock
With maple_tree supporting vma tree traversal under RCU and per-vma locks,
/proc/pid/maps can be read while holding individual vma locks instead of
locking the entire address space.

A completely lockless approach (walking vma tree under RCU) would be quite
complex with the main issue being get_vma_name() using callbacks which
might not work correctly with a stable vma copy, requiring original
(unstable) vma - see special_mapping_name() for example.

When per-vma lock acquisition fails, we take the mmap_lock for reading,
lock the vma, release the mmap_lock and continue.  This fallback to mmap
read lock guarantees the reader to make forward progress even during lock
contention.  This will interfere with the writer but for a very short time
while we are acquiring the per-vma lock and only when there was contention
on the vma reader is interested in.

We shouldn't see a repeated fallback to mmap read locks in practice, as
this require a very unlikely series of lock contentions (for instance due
to repeated vma split operations).  However even if this did somehow
happen, we would still progress.

One case requiring special handling is when a vma changes between the time
it was found and the time it got locked.  A problematic case would be if a
vma got shrunk so that its vm_start moved higher in the address space and
a new vma was installed at the beginning:

reader found:               |--------VMA A--------|
VMA is modified:            |-VMA B-|----VMA A----|
reader locks modified VMA A
reader reports VMA A:       |  gap  |----VMA A----|

This would result in reporting a gap in the address space that does not
exist.  To prevent this we retry the lookup after locking the vma, however
we do that only when we identify a gap and detect that the address space
was changed after we found the vma.

This change is designed to reduce mmap_lock contention and prevent a
process reading /proc/pid/maps files (often a low priority task, such as
monitoring/data collection services) from blocking address space updates. 
Note that this change has a userspace visible disadvantage: it allows for
sub-page data tearing as opposed to the previous mechanism where data
tearing could happen only between pages of generated output data.  Since
current userspace considers data tearing between pages to be acceptable,
we assume is will be able to handle sub-page data tearing as well.

Link: https://lkml.kernel.org/r/20250719182854.3166724-7-surenb@google.com
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: David Hildenbrand <david@redhat.com>
Cc: Jann Horn <jannh@google.com>
Cc: Jeongjun Park <aha310510@gmail.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Josef Bacik <josef@toxicpanda.com>
Cc: Kalesh Singh <kaleshsingh@google.com>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: "Paul E . McKenney" <paulmck@kernel.org>
Cc: Peter Xu <peterx@redhat.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Thomas Weißschuh <linux@weissschuh.net>
Cc: T.J. Mercier <tjmercier@google.com>
Cc: Ye Bin <yebin10@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2025-07-24 19:12:37 -07:00
..
array.c fs/proc: do_task_stat: Fix ESP not readable during coredump 2025-01-04 10:12:18 +01:00
base.c - The 3 patch series "hung_task: extend blocking task stacktrace dump to 2025-05-31 19:12:53 -07:00
bootconfig.c fs/proc: Skip bootloader comment if no embedded kernel parameters 2024-04-09 23:36:18 +09:00
cmdline.c
consoles.c proc: Add nbcon support for /proc/consoles 2024-09-04 15:56:33 +02:00
cpuinfo.c
devices.c
fd.c Pass parent directory inode and expected name to ->d_revalidate() 2025-01-27 19:25:23 -05:00
fd.h
generic.c proc: use the same treatment to check proc_lseek as ones for proc_read_iter et.al 2025-07-09 22:42:01 -07:00
inode.c proc: use the same treatment to check proc_lseek as ones for proc_read_iter et.al 2025-07-09 22:42:01 -07:00
internal.h fs/proc/task_mmu: read proc/pid/maps under per-vma lock 2025-07-24 19:12:37 -07:00
interrupts.c fs/procfs: Switch to irq_get_nr_irqs() 2024-10-16 21:56:59 +02:00
Kconfig virtio-mem: support CONFIG_PROC_VMCORE_DEVICE_RAM 2025-01-27 09:39:25 -05:00
kcore.c crash: Use note name macros 2025-02-10 16:56:58 -08:00
kmsg.c
loadavg.c
Makefile kbuild: make -Woverride-init warnings more consistent 2024-03-31 11:32:26 +09:00
meminfo.c mm, vmstat: remove the NR_WRITEBACK_TEMP node_stat_item counter 2025-07-19 18:59:47 -07:00
namespaces.c vfs: support caching symlink lengths in inodes 2024-12-22 11:29:50 +01:00
nommu.c
page.c fs: stable_page_flags(): use snapshot_page() 2025-07-24 19:12:35 -07:00
proc_net.c fs: Add kernel-doc comments to proc_create_net_data_write() 2024-03-26 09:01:18 +01:00
proc_sysctl.c fix proc_sys_compare() handling of in-lookup dentries 2025-07-03 20:59:09 -04:00
proc_tty.c
root.c procfs: make freeing proc_fs_info rcu-delayed 2024-02-25 02:10:32 -05:00
self.c
softirqs.c proc/softirqs: replace seq_printf with seq_put_decimal_ull_width 2024-11-07 07:40:14 -10:00
stat.c fs/procfs: Switch to irq_get_nr_irqs() 2024-10-16 21:56:59 +02:00
task_mmu.c fs/proc/task_mmu: read proc/pid/maps under per-vma lock 2025-07-24 19:12:37 -07:00
task_nommu.c proc: fix the issue of proc_mem_open returning NULL 2025-05-11 17:54:05 -07:00
thread_self.c
uptime.c
util.c
version.c
vmcore.c procfs: fix a locking bug in a vmcore_add_device_dump() error path 2025-02-17 22:40:00 -08:00