[PATCH 0/15] mm: introduce ANON_VMA_LAZY for deferred anon_vma creation

From: tao

Date: Wed May 27 2026 - 07:28:45 EST


TL;DR
-----

This series introduces ANON_VMA_LAZY, which defers anon_vma creation
until it is actually required.

- anon_vma memory reduced by ~92-97%, anon_vma_chain reduced by ~50-57%
- rmap operations on ANON_VMA_LAZY VMAs do not require anon_vma locking

Background
----------

Currently anon_vma structures are created eagerly when anonymous VMAs
are initialized. However, many VMAs never participate in fork or rmap
operations that require anon_vma chains, so the allocated anon_vma and
anon_vma_chain objects are often unnecessary.

Design overview
---------------

ANON_VMA_LAZY defers anon_vma allocation until it is actually needed
(for example during fork). VMAs that never participate in sharing can
avoid creating anon_vma structures entirely.

Before an anon_vma exists, rmap operations rely directly on VMA
information, so no anon_vma locking is required. An anon_vma is created
and linked only when sharing semantics are required.

This series introduces anon_rmap helpers to make rmap less dependent on
direct anon_vma access. It also introduces anon_vma_tree_t as a container
to support both the lazy and the existing anon_vma layouts.

Once a VMA becomes associated with an anon_vma, the normal behavior
remains unchanged.

Memory impact
-------------

Preliminary measurements show significant reductions in anon_vma-related
slab allocations.

After boot:

Object | Before (active KB) | After (active KB) | Change
vm_area_struct | 117035 | 118176 | +1.0%
anon_vma_chain | 18865.8 | 8112.06 | -57.0%
anon_vma | 20426.4 | 613.75 | -97.0%

After launching 24 apps:

Object | Before (active KB) | After (active KB) | Change
vm_area_struct | 196873 | 197345 | +0.2%
anon_vma_chain | 31477.1 | 15576.8 | -50.5%
anon_vma | 33280 | 2648.12 | -92.0%

Simple fork microbenchmarks also show a slight improvement in fork
performance, since child VMAs do not need to allocate anon_vma
structures during fork.

Feedback and suggestions are welcome.


tao (15):
mm/rmap: introduce anon_rmap APIs for anonymous folios
mm: convert anon_vma rmap APIs to anon_rmap
mm: introduce anon_vma_tree_t for multiple anon_vma topologies
mm: switch to anon_vma_tree_t APIs in preparation for ANON_VMA_LAZY
mm: add CONFIG_ANON_VMA_LAZY and folio helpers
mm: add CONFIG_VMA_REF and VMA helpers
mm: replace direct FOLIO_MAPPING_ANON usage with helpers
mm: prepare rmap infrastructure for ANON_VMA_LAZY
mm: implement ANON_VMA_LAZY rmap semantics
mm: defer anon_vma creation with ANON_VMA_LAZY
mm: handle ANON_VMA_LAZY in huge page operations
mm: handle ANON_VMA_LAZY during migration
mm: support setup and upgrade of ANON_VMA_LAZY folios
mm: support merging of ANON_VMA_LAZY VMAs
mm: enable CONFIG_ANON_VMA_LAZY on arm64 and x86_64

arch/arm64/Kconfig | 1 +
arch/x86/Kconfig | 1 +
fs/proc/page.c | 6 +-
include/linux/mm.h | 38 ++
include/linux/mm_types.h | 9 +-
include/linux/page-flags.h | 34 +-
include/linux/pagemap.h | 2 +-
include/linux/rmap.h | 165 ++++++++-
mm/Kconfig | 22 ++
mm/damon/ops-common.c | 4 +-
mm/debug.c | 2 +-
mm/debug_vm_pgtable.c | 2 +-
mm/gup.c | 6 +-
mm/huge_memory.c | 16 +-
mm/internal.h | 171 +++++++++
mm/khugepaged.c | 13 +-
mm/ksm.c | 43 ++-
mm/memory-failure.c | 11 +-
mm/memory.c | 19 +-
mm/migrate.c | 126 ++++---
mm/mmap.c | 15 +-
mm/mremap.c | 4 +-
mm/page_idle.c | 2 +-
mm/rmap.c | 690 ++++++++++++++++++++++++++++++++++---
mm/vma.c | 76 ++--
mm/vma.h | 4 +-
mm/vma_exec.c | 2 +-
mm/vma_init.c | 1 +
28 files changed, 1279 insertions(+), 206 deletions(-)

--
2.17.1