|
|
Log in / Subscribe / Register

mm: rework anon_vma and remove anon_vma_chain

From:  tao <tao.wangtao-AT-honor.com>
To:  <akpm-AT-linux-foundation.org>, <david-AT-kernel.org>, <catalin.marinas-AT-arm.com>, <will-AT-kernel.org>, <tglx-AT-kernel.org>, <mingo-AT-redhat.com>, <bp-AT-alien8.de>, <dave.hansen-AT-linux.intel.com>, <x86-AT-kernel.org>, <willy-AT-infradead.org>, <sj-AT-kernel.org>, <kees-AT-kernel.org>, <luizcap-AT-redhat.com>, <zhangjiao2-AT-cmss.chinamobile.com>, <kas-AT-kernel.org>, <ljs-AT-kernel.org>
Subject:  [RFC PATCH v2 00/13] mm: rework anon_vma and remove anon_vma_chain
Date:  Tue, 07 Jul 2026 14:32:55 +0800
Message-ID:  <20260707063308.29176-1-tao.wangtao@honor.com>
Cc:  <hpa-AT-zytor.com>, <liam-AT-infradead.org>, <vbabka-AT-kernel.org>, <rppt-AT-kernel.org>, <surenb-AT-google.com>, <mhocko-AT-suse.com>, <jack-AT-suse.cz>, <riel-AT-surriel.com>, <harry-AT-kernel.org>, <jannh-AT-google.com>, <jgg-AT-ziepe.ca>, <jhubbard-AT-nvidia.com>, <peterx-AT-redhat.com>, <ziy-AT-nvidia.com>, <baolin.wang-AT-linux.alibaba.com>, <npache-AT-redhat.com>, <ryan.roberts-AT-arm.com>, <dev.jain-AT-arm.com>, <baohua-AT-kernel.org>, <lance.yang-AT-linux.dev>, <xu.xin16-AT-zte.com.cn>, <chengming.zhou-AT-linux.dev>, <muchun.song-AT-linux.dev>, <baoquan.he-AT-linux.dev>, <nao.horiguchi-AT-gmail.com>, <matthew.brost-AT-intel.com>, <joshua.hahnjy-AT-gmail.com>, <rakie.kim-AT-sk.com>, <byungchul-AT-sk.com>, <gourry-AT-gourry.net>, <ying.huang-AT-linux.alibaba.com>, <apopple-AT-nvidia.com>, <pfalcato-AT-suse.de>, <linux-arm-kernel-AT-lists.infradead.org>, <linux-kernel-AT-vger.kernel.org>, <linux-fsdevel-AT-vger.kernel.org>, <linux-mm-AT-kvack.org>, <damon-AT-lists.linux.dev>, <shakeel.butt-AT-linux.dev>, <ryncsn-AT-gmail.com>, <jparsana-AT-google.com>, <dvander-AT-google.com>, <zhangji1-AT-honor.com>, <wangzicheng-AT-honor.com>, tao <tao.wangtao-AT-honor.com>
Archive-link:  Article

Hi all,

Since v1 was relatively complex and difficult to extend, this version
adopts a simpler anon_vma implementation approach.


Replace the original anon_vma + anon_vma_chain multiple rbtree
structures with a depth-aware doubly linked list, and remove anon_vma_chain.


During rmap walks, vma_rmap_base(vma) is used to compute the page
address and look up the corresponding VMA from mm_mt:

  vma_rmap_base(vma) = vma->vm_start - vma->vm_pgoff * PAGE_SIZE

  page_address(vma, pgoff)
    = vma->vm_start + (pgoff - vma->vm_pgoff) * PAGE_SIZE
    = vma->vm_start - vma->vm_pgoff * PAGE_SIZE + pgoff * PAGE_SIZE
    = vma_rmap_base(vma) + pgoff * PAGE_SIZE

Since vma_rmap_base(vma) remains invariant across VMA merge and split
operations, VMA updates only need to adjust the VMA count of the
corresponding anon_vma. The anon_vma no longer directly tracks VMAs,
which eliminates the need for anon_vma_chain.

Process fork behaves like a fractal expansion of both tasks and
anon_vmas. A dedicated fractal_list records forked anon_vmas, while
descendant anon_vmas are derived from fork depth during rmap walks.
For this reason, the new design is named ANON_VMA_FRACTAL.

The depth is initialized to 0.
When a child is added, the root depth is set to 1.
A remap child has a depth of parent->depth + 1,
while a fork child has a depth of parent->depth + 2.
For example:
 1) A forks B and C:

	                   (1A)
	                  /    \
	                (3B)---(3C)

 2) B remaps D:

	                   (1A)
	                  /    \
	                (3B)   (3C)
	                /       /
	              (4D)-----o

 3) B forks E and F:

	                   (1A)--o
	                  /       \
	                (3B)      (3C)
	                /         /
	              (4D)       /
	              /         /
	            (5E)------(5F)

 4) C forks G:

	                   (1A)------------o
	                  /                 \
	                (3B)      (3C)       o
	                /         /  \      /
	              (4D)       /    \    /
	              /         /      \  /
	            (5E)------(5F)     (5G)

Only the root node A needs to traverse all descendants; non-root nodes
only traverse their own descendant nodes. For example:
- When rmap-ing A: first process A, then traverse all descendants
  B/D/E/F/C/G. A does not need to be traversed again.
- When rmap-ing B: first process B, then traverse its descendants
  D/E/F. Since C->depth <= B->depth, the rmap walk terminates at C.

The fractal_list remains stable across VMA merge and split operations.
It is updated only when anon_vmas are forked, remapped, or unlinked, and
is traversed during rmap walks.

On an Android device after boot, memory usage of vm_area_struct,
anon_vma, and anon_vma_chain is reduced by about 35 MB.

  struct              base(KB)  patch(KB)  patch_struct      saved(KB)
  --------------------------------------------------------------------
  vm_area_struct        110760     103837  vm_area_struct         6887
  anon_vma               19152       8576  anon_node             10576
  anon_vma_chain         17560          0  NA                    17560
  NA                         0        346  anon_semaphore         -346

lat_proc shows fork performance improves by about 15% at P=10.

Changes since v1:
- anon_vma now stores mm and rmap_base for VMA lookup, and only tracks
  the number of associated VMAs instead of directly tracking VMAs
- Use fractal_list + depth to maintain anon_vma topology and remove
  anon_vma_chain completely
- Keep folio->mapping storing anon_vma
- Preserve existing APIs and external callers unchanged while
  introducing ANON_RMAP_FOREACH_VMA() to unify anonymous rmap traversal
- Use vm_refcnt on leaf VMAs for rmap protection
- Optimize rwsem memory usage with shared semaphores

Patch layout:
  1-2: add CONFIG_ANON_VMA_FRACTAL and basic helpers
  3-7: implement anon_vma fractal infrastructure
  8: implement anonymous folio rmap
  9-10: replace anon_vma with anon_node
  11: use vm_refcnt on leaf VMAs for rmap protection
  12: optimize anon_vma memory usage with shared semaphores

v1:
https://lore.kernel.org/all/20260527110147.17815-1-tao.wa...

tao (13):
  mm: add CONFIG_ANON_VMA_FRACTAL
  mm: implement helpers for ANON_VMA_FRACTAL
  mm: implement __anon_node_prepare for ANON_VMA_FRACTAL
  mm: implement anon_node_clone for ANON_VMA_FRACTAL
  mm: implement anon_node_fork_with_prev for ANON_VMA_FRACTAL
  mm: implement unlink_anon_nodes for ANON_VMA_FRACTAL
  mm: handle rmap_base changes for ANON_VMA_FRACTAL
  mm: implement anonymous folio rmap for ANON_VMA_FRACTAL
  mm: prepare anon_node replacement for ANON_VMA_FRACTAL
  mm: replace anon_vma with anon_node for ANON_VMA_FRACTAL
  mm: optimize rmap for ANON_VMA_FRACTAL with PVL
  mm: shared semaphores for ANON_VMA_FRACTAL
  mm: Enable CONFIG_ANON_VMA_FRACTAL by default

 include/linux/mm.h       |   2 +
 include/linux/mm_types.h |   2 +
 include/linux/rmap.h     |  56 ++++
 include/linux/rwsem.h    |  10 +
 mm/Kconfig               |  37 +++
 mm/internal.h            | 205 ++++++++++++
 mm/ksm.c                 |  19 +-
 mm/memory-failure.c      |   8 +-
 mm/mmap.c                |   7 +-
 mm/rmap.c                | 686 +++++++++++++++++++++++++++++++++++++--
 mm/vma.c                 |  76 ++++-
 mm/vma_init.c            |   2 +
 12 files changed, 1056 insertions(+), 54 deletions(-)

-- 
2.17.1




Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds